From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 35534 invoked by alias); 10 Jul 2015 22:09:37 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 35513 invoked by uid 440); 10 Jul 2015 22:09:36 -0000 Date: Fri, 10 Jul 2015 22:09:00 -0000 Message-ID: <20150710220936.35486.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/dyninst: Support for using upstream gdb as a client. X-Git-Refname: refs/heads/scox/dyninst X-Git-Reftype: branch X-Git-Oldrev: 21eefb613838106f216f8d779326a10ffd7a1fd7 X-Git-Newrev: d7e297fed3bc38f07f5d0dbbf9658eade3c6a51e X-SW-Source: 2015-q3/txt/msg00000.txt.bz2 List-Id: The branch, scox/dyninst has been updated via d7e297fed3bc38f07f5d0dbbf9658eade3c6a51e (commit) from 21eefb613838106f216f8d779326a10ffd7a1fd7 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit d7e297fed3bc38f07f5d0dbbf9658eade3c6a51e Author: Stan Cox Date: Fri Jul 10 18:07:38 2015 -0400 Support for using upstream gdb as a client. * dyninst-low.cc (EventSet.remove): New, to remove a procs events. (EventSet.get): Ignore terminated procs. (is_fork): New, to determine if there is a fork event. (dump_events, dump_processes): Debugging tools. (lwp_info) Renamed to match usage in linux-low.c. (dyninst_add_lwp) Link lwp_info to both gdb and dyninst lwp structs. (dyninst_resume) For now, just handle one resume request. (dyninst_wait_1) Add separate cases for singlestep and fork events. (dyninst_mourn, dyninst_fetch_registers, dyninst_store_registers) (dyninst_write_pc, dyninst_write_memory, dyninst_insert_point) (dyninst_remove_point) Insure process is active. * dyninst-low.h (breakpoint, breakpoint_len): Opcode the arch uses for a breakpoint trap. * dyninst-x86=low.cc (dyninst_x86_fill_gregset) (dyninst_x86_store_gregset): Allow for smaller dyninst regset size. * mem-break.c (has_client_breakpoint_at): Given multiple clients for the same process does clientA have a break at location addr. (insert_shadow_memory): Allows shadow memory use by a backend that manages its own breakpoints. * server.c (free_client_state): Free all client state memory. (count_client_state) Return the file desc for an active client in case an existing client has terminated. (add_client_breakpoint, delete_client_breakpoint) As per has_client_breakpoint_at. (normalize_packet): Improve handling for multiple clients for the same process. (process_serial_event): Likewise. Save the original getpkt contents in in_buf. * server.h (struct client_breakpoint): New, as per has_client_breakpoint_at ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/dyninst-low.cc | 427 ++++++++++++++++++++++++++++++-------- gdb/gdbserver/dyninst-low.h | 3 + gdb/gdbserver/dyninst-x86-low.cc | 17 ++- gdb/gdbserver/event-loop.c | 3 - gdb/gdbserver/mem-break.c | 48 ++++- gdb/gdbserver/mem-break.h | 6 + gdb/gdbserver/regcache.c | 3 + gdb/gdbserver/remote-utils.c | 13 +- gdb/gdbserver/remote-utils.h | 4 + gdb/gdbserver/server.c | 368 ++++++++++++++++++++++----------- gdb/gdbserver/server.h | 7 + 11 files changed, 680 insertions(+), 219 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/dyninst-low.cc b/gdb/gdbserver/dyninst-low.cc index 24206e6..23dc735 100644 --- a/gdb/gdbserver/dyninst-low.cc +++ b/gdb/gdbserver/dyninst-low.cc @@ -70,11 +70,11 @@ using namespace ProcControlAPI; typedef std::vector BreakpointSet; BreakpointSet dyninst_bpset; -ProcessSet::ptr dyninst_procset; -typedef std::vector LibrarySet; -LibrarySet dyninst_libset; + Thread::const_ptr NULL_Thread = Thread::const_ptr(); +Process::const_ptr NULL_Process = Process::const_ptr(); +ProcessSet::ptr dyninst_procset; void dump_procset () @@ -84,14 +84,15 @@ dump_procset () for (it = dyninst_procset->begin(); it != dyninst_procset->end(); it++) { Process::const_ptr proc = *it; - cout << __FUNCTION__ << ' ' << proc->getPid() << ' ' << hex; - for (thidx = proc->threads().begin(); - thidx != proc->threads().end(); thidx++) - { - Thread::const_ptr thr = *thidx; - cout << thr->getLWP() << ' ' << the_low_target.get_pc (thr) << ' '; - } - cout << '\n'; + Dyninst::PID pid = proc->getPid(); + cout << hex; + if (! proc->isTerminated()) + for (thidx = proc->threads().begin(); + thidx != proc->threads().end(); thidx++) + { + Thread::const_ptr thr = *thidx; + cout << "pid=0x" << pid << " tid=0x" << thr->getLWP() << " pc=0x" << the_low_target.get_pc (thr) << '\n'; + } } } @@ -147,22 +148,27 @@ bool operator==(const ptid_t & l, const ptid_t & r ) class EventSet { -private: +public: /* The list of events that handleEvents has encountered */ std::vector > current_events; -public: EventSet() { NULL_Event = Event::const_ptr(); } Event::const_ptr NULL_Event; void insert (Event::const_ptr ev) { ptid_t ptid = ptid_build (ev->getProcess()->getPid(), ev->getThread()->getLWP(), (ev->getThread()->haveUserThreadInfo() ? ev->getThread()->getTID() : -1)); - current_events.push_back(make_pair (ptid, ev)); - if (debug_threads) + ProcessSet::iterator it; + // Ignore spurious events from a now exited process + for (it = dyninst_procset->begin(); + it != dyninst_procset->end(); ++it) { - dump("after insert "); - dump_procset (); + Process::ptr proc = *it; + if (proc->getPid() == ev->getProcess()->getPid()) + break; } + if (it != dyninst_procset->end()) + current_events.push_back(make_pair (ptid, ev)); } + void erase (Event::const_ptr ev) { if (ev != NULL_Event) @@ -182,6 +188,22 @@ public: dump("after erase "); } + /* Remove any outstanding events for this process */ + + void remove (Process::ptr pid) + { + std::vector >::iterator it; + for (it = current_events.begin() ; + it != current_events.end(); ++it) + { + Event::const_ptr event = it->second; + if (event->getProcess()->getPid() == pid->getPid()) + { + current_events.erase(it); + } + } + } + /* Get the event for a given PTID */ Event::const_ptr get (ptid_t ptid) @@ -197,19 +219,17 @@ public: { ptid_t ceptid = it->first; event = it->second; - if (ptid.pid == -1 - || (ceptid.pid == ptid.pid)) -// || (ceptid.pid == ptid.pid -// && ceptid.lwp == ptid.lwp)) + if ((ptid.pid == -1 || (ceptid.pid == ptid.pid)) + && ! event->getProcess()->isTerminated()) { CORE_ADDR pc = (the_low_target.get_pc) (event->getThread()); - DEBUG(event->name() << ' ' << ceptid.pid << '/' << ceptid.lwp << "pc=" << pc); + DEBUG(event->name() << ' ' << dec << ceptid.pid << '/' << ceptid.lwp << hex << " pc=" << pc); return event; } } if (! Process::handleEvents(true)) return NULL_Event; - DEBUG("after handleEvents",pid_to_string(ptid)); + DEBUG("after handleEvents", pid_to_string(ptid)); attempt += 1; } while (attempt <= 2); @@ -314,6 +334,21 @@ public: return NULL_Thread; } + Process::const_ptr is_fork (Event::const_ptr event) + { + if (event != NULL) + { + if (event->getEventType().code() == EventType::Fork) + { + EventFork::const_ptr fork_ev = event->getEventFork(); + if (event != NULL) + DEBUG(event->getEventType().code() << " Fork"); + return fork_ev->getChildProcess(); + } + } + return NULL_Process; + } + void dump (string comment) { int idx = 1; @@ -332,6 +367,78 @@ public: } events; +static void dump_events (void) __attribute__ ((unused)); +static void +dump_events (void) +{ + int idx = 1; + std::vector >::iterator it; + for (it = events.current_events.begin() ; + it != events.current_events.end(); ++it) + { + Event::const_ptr event = it->second; + if (event == NULL) + continue; + cerr << dec << idx << hex << ' ' << event->name() << ' ' << event->getProcess()->getPid() << '\n'; + idx += 1; + } +} + + +static void dump_processes (void) __attribute__ ((unused)); +static void +dump_processes (void) +{ + ProcessSet::iterator it; + int idx = 1; + for (it = dyninst_procset->begin(); + it != dyninst_procset->end(); ++it) + { + Process::ptr proc = *it; + ThreadPool::iterator thidx; + if (proc == NULL) + continue; + cerr << dec << idx << hex << ' ' << proc->getPid(); + if (proc->isTerminated()) + cerr << " terminated "; + if (proc->isExited()) + cerr << " exited "; + cerr << '\n'; + + if (!proc->isTerminated()) + for (thidx = proc->threads().begin(); + thidx != proc->threads().end(); ++thidx) + { + Thread::const_ptr th = *thidx; + cerr << "Thread tid=" << th->getTID() << " lwp=" << th->getLWP(); + if (th->isRunning()) + cerr << " running "; + if (th->isStopped()) + cerr << " stopped "; + cerr << '\n'; + } + + idx += 1; + } + + client_state *cs = get_client_state (); + struct inferior_list_entry *inf; + cerr << "all processes "; + for (inf = cs->ss->all_processes.head; inf != NULL; inf = inf->next) + { + struct process_info *pi = (process_info*)inf; + cerr << pi->entry.id.pid << '/' << pi->entry.id.lwp << '/' << pi->entry.id.tid << ' '; + } + cerr << '\n'; + cerr << "all threads "; + for (inf = cs->ss->all_threads.head; inf != NULL; inf = inf->next) + { + struct thread_info *ti = (thread_info*)inf; + cerr << ti->entry.id.pid << '/' << ti->entry.id.lwp << '/' << ti->entry.id.tid << ' '; + } + cerr << '\n'; +} + void pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid, CORE_ADDR pc) { @@ -339,6 +446,7 @@ pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid, CORE_ADD cerr << "pid=*"; else { + cerr << dec; cerr << "pid=" << pid; if (lwp < 0) cerr << " lwp=*"; @@ -346,6 +454,7 @@ pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid, CORE_ADD cerr << " lwp=" << lwp; if (tid > 0) cerr << " thr=" << tid; + cerr << hex; string source = ""; if (pc == 0) @@ -375,10 +484,10 @@ pid_to_string (ptid_t ptid) { CORE_ADDR pc; Thread::const_ptr thr = dyninst_get_thread(ptid); - if (thr != NULL_Thread) - pc = (the_low_target.get_pc) (thr); - else + if (thr == NULL_Thread || thr->getProcess()->isTerminated()) pc = 0; + else + pc = (the_low_target.get_pc) (thr); pid_to_string (ptid.pid, ptid.lwp, ptid.tid, pc); } @@ -386,15 +495,18 @@ void pid_to_string (Thread::const_ptr thr) { long tid; - if (thr == NULL) + if (thr == NULL_Thread) return; if (thr->haveUserThreadInfo()) tid = thr->getTID(); else tid = -1; - CORE_ADDR pc = (the_low_target.get_pc) (thr); - + CORE_ADDR pc; + if (thr->getProcess()->isTerminated()) + pc = 0; + else + pc = (the_low_target.get_pc) (thr); pid_to_string (thr->getProcess()->getPid(), thr->getLWP(), tid, pc); } @@ -418,15 +530,14 @@ extern "C" struct process_info_private { - /* The PTID obtained from the last wait performed on this process. - Initialized to null_ptid until the first wait is performed. */ - ptid_t last_wait_event_ptid; Process::ptr process; } process_info_private; -struct thread_info_private +struct lwp_info { Thread::const_ptr thread; + /* Backlink to the parent object. */ + struct thread_info *thread_info; Event::const_ptr event; CORE_ADDR step_range_start; CORE_ADDR step_range_end; @@ -438,7 +549,7 @@ dyninst_get_thread(ptid_t ptid) { struct thread_info *ti = find_thread_ptid (ptid); if (ti != NULL) - return ((struct thread_info_private*)ti->target_data)->thread; + return ((struct lwp_info*)(ti->target_data))->thread; else return NULL_Thread; } @@ -451,6 +562,8 @@ dyninst_add_process (int pid, int attached, Process::ptr process) { struct process_info *proc; + process->setData(0); + dyninst_procset->insert (process); proc = add_process (pid, attached); proc->tdesc = dyninst_tdesc; proc->priv = new struct process_info_private; @@ -461,21 +574,21 @@ dyninst_add_process (int pid, int attached, Process::ptr process) /* Add a THREAD to enable mapping a gdbserver thread to a dyninst Thread */ void -dyninst_add_thread(int pid, Thread::const_ptr thread) +dyninst_add_lwp (int pid, Thread::const_ptr thread) { - Dyninst::LWP lwp; - client_state *cs = get_client_state (); + Dyninst::LWP dyn_lwp; if (thread != NULL) { - struct thread_info_private *tip = new struct thread_info_private; - tip->thread = thread; - lwp = thread->getLWP(); - cs->ss->current_thread = add_thread (ptid_build (pid, lwp, 0), tip); + struct lwp_info *lwp = new struct lwp_info; + thread->setData(lwp); + lwp->thread = thread; + dyn_lwp = thread->getLWP(); + lwp->thread_info = add_thread (ptid_build (pid, dyn_lwp, 0), lwp); } else { - cs->ss->current_thread = add_thread (ptid_build (pid, pid, 0), NULL); + add_thread (ptid_build (pid, pid, 0), NULL); } } @@ -489,7 +602,7 @@ dyninst_remove_thread(Thread::const_ptr thread) struct thread_info *ti = find_thread_ptid (ptid); if (ti != NULL) { - delete (struct thread_info_private*)ti->target_data; + delete (struct lwp_info*)ti->target_data; ti->target_data = NULL; remove_thread (ti); } @@ -504,7 +617,7 @@ dyninst_get_inferior_thread() { client_state *cs = get_client_state (); - struct thread_info_private *tip = (struct thread_info_private*)(cs->ss->current_thread->target_data); + struct lwp_info *tip = (struct lwp_info*)(cs->ss->current_thread->target_data); if (!tip) DYNERR ("No inferior thread"); return tip->thread; @@ -516,8 +629,8 @@ dyninst_get_inferior_thread() Process::cb_ret_t signal_handler(Event::const_ptr ev) { - DEBUG(ev->name()); - if (ev->name() != "post-LWPDestroy") + DEBUG(ev->name(), pid_to_string (ev->getThread())); + if (ev->name() != "post-LWPDestroy" && ev->name() != "post-Exit") events.insert(ev); return Process::cbDefault; } @@ -529,7 +642,7 @@ Process::cb_ret_t breakpoint_handler(Event::const_ptr ev) { EventBreakpoint::const_ptr bp_ev = ev->getEventBreakpoint(); - DEBUG('@' << bp_ev->getAddress() << " lwp=" << bp_ev->getThread()->getLWP()); + DEBUG(ev->name() << bp_ev->getAddress(), pid_to_string (ev->getThread())); events.insert(ev); return Process::cbDefault; } @@ -615,7 +728,6 @@ dyninst_create_inferior (char *program, char **allargs) Process::ptr dyninst_process = Process::createProcess(exec, args); if (dyninst_process == Process::ptr()) DYNERRMSG ("No such file: %s\n", exec.c_str()); - dyninst_procset->insert(dyninst_process); myregisterCB(EventType::Bootstrap, signal_handler); myregisterCB(EventType::Breakpoint, breakpoint_handler); @@ -635,7 +747,7 @@ dyninst_create_inferior (char *program, char **allargs) // ThreadDestroy, UserThreadDestroy handled via LWPDestroy - DEBUG("created process " << dyninst_process->getPid() << program); + DEBUG("created process " << dec << dyninst_process->getPid() << hex << program); pid_t pid = dyninst_process->getPid(); dyninst_add_process (pid, 0, dyninst_process); @@ -646,9 +758,9 @@ dyninst_create_inferior (char *program, char **allargs) { bool reg_map_setup = false; RegisterPool regpool; - DEBUG("created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); + DEBUG("created thread " << dec << (*thidx)->getTID() << ' ' << (*thidx)->getLWP() << hex); Thread::ptr th = *thidx; - dyninst_add_thread (pid, th); + dyninst_add_lwp (pid, th); if (! reg_map_setup) { th->getAllRegisters (regpool); @@ -674,8 +786,6 @@ dyninst_attach (unsigned long pid) if (dyninst_process == Process::ptr()) DYNERRMSG ("Cannot attach to process %ld", pid); - dyninst_procset->insert(dyninst_process); - DEBUG("pid=" << pid); myregisterCB(EventType::Bootstrap, signal_handler); myregisterCB(EventType::Breakpoint, breakpoint_handler); @@ -705,9 +815,9 @@ dyninst_attach (unsigned long pid) { bool reg_map_setup = false; RegisterPool regpool; - DEBUG("created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); + DEBUG("created thread " << dec << (*thidx)->getTID() << ' ' << (*thidx)->getLWP() << hex); Thread::const_ptr th = *thidx; - dyninst_add_thread (pid, th); + dyninst_add_lwp (pid, th); if (! reg_map_setup) { th->getAllRegisters (regpool); @@ -736,7 +846,9 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) DEBUG_ENTER (); - for (int i = 0; i < (int)n; i++) + // see linux-low.c::linux_set_resume_request for the proper way to handle multiple resumes + // for (int i = 0; i < (int)n; i++) + int i = 0; { ptid_t ptid = resume_info[i].thread; @@ -744,12 +856,22 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) ptid = thread_to_gdb_id (cs->ss->current_thread); Dyninst::PID pid = ptid_get_pid (ptid); - ProcessSet::iterator procset_it = dyninst_procset->find(pid); - if (procset_it == dyninst_procset->end()) +// ProcessSet::iterator procset_it = dyninst_procset->find(pid); + ProcessSet::iterator it; + Process::ptr dyninst_process; + for (it = dyninst_procset->begin(); + it != dyninst_procset->end(); ++it) + { + Process::ptr proc = *it; + if (proc->getPid() == pid) + { + dyninst_process = proc; + break; + } + } + if (it == dyninst_procset->end()) DYNERR ("Cannot resume process %lu\n", (long unsigned)pid); - Process::ptr dyninst_process = *procset_it; - ThreadPool::iterator thidx; Thread::ptr th; @@ -780,7 +902,7 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) { // resume_continue, resume_step, resume_stop struct thread_info *ti = find_thread_ptid (ptid); - struct thread_info_private *tip = (struct thread_info_private*)(ti->target_data); + struct lwp_info *tip = (struct lwp_info*)(ti->target_data); tip->step_range_start = resume_info->step_range_start; tip->step_range_end = resume_info->step_range_end; struct regcache *regcache = get_thread_regcache (ti, 1); @@ -837,7 +959,7 @@ in_step_range () { client_state *cs = get_client_state (); - struct thread_info_private *tip = (struct thread_info_private*)(cs->ss->current_thread->target_data); + struct lwp_info *tip = (struct lwp_info*)(cs->ss->current_thread->target_data); struct regcache *regcache = get_thread_regcache (cs->ss->current_thread, 1); CORE_ADDR pc = (*the_low_target.read_pc) (regcache); @@ -862,12 +984,8 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) { if ((event = events.get(new_ptid))) { - struct process_info *pi; pid = (ptid.pid != -1) ? ptid.pid : event->getProcess()->getPid(); new_ptid = ptid_build (pid, pid, 0); - pi = find_process_pid(pid); - if (pi && pi->priv) - pi->priv->last_wait_event_ptid = new_ptid; } if (event == NULL) hooks/post-receive -- Repository for Project Archer.