From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17214 invoked by alias); 4 May 2015 21:00:51 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 17189 invoked by uid 440); 4 May 2015 21:00:51 -0000 Date: Mon, 04 May 2015 21:00:00 -0000 Message-ID: <20150504210051.17161.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/dyninst: Categorize client packets for handling multiplexed client connections. X-Git-Refname: refs/heads/scox/dyninst X-Git-Reftype: branch X-Git-Oldrev: 182451b3fd3afbf1b88867a90c222d4e7c91d3c3 X-Git-Newrev: 21f64f60c407b97df755cc686c89b5d148450bdd X-SW-Source: 2015-q2/txt/msg00000.txt.bz2 List-Id: The branch, scox/dyninst has been updated via 21f64f60c407b97df755cc686c89b5d148450bdd (commit) from 182451b3fd3afbf1b88867a90c222d4e7c91d3c3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit 21f64f60c407b97df755cc686c89b5d148450bdd Author: Stan Cox Date: Mon May 4 16:58:54 2015 -0400 Categorize client packets for handling multiplexed client connections. * dyninst-low.cc (DYNERRMSG): New for error reporting. (EventSet): Convert current_events from a map to a vector. (insert, erase, get): Likewise. (is_threadcreate, is_threaddestroy): Handle all types of thread events. (pid_to_string): Display pc if possible. (lwpdestroy_handler): New. (dyninst_store_registers, dyninst_fetch_registers) (dyninst_insert_point, dyninst_remove_point): Add howto_continue; * dyninst-x86-low.cc (x86_get_pc): New. * server.c (set_client_state) Simplify to only set or add a client_state. Change all callers. (set_lock): Remove. (normalize_packet): Given multiple requests for the same process, determine which should be allowed to proceed. (handle_monitor_command): Add 'client status' (process_serial_event): Handle multiple requests to the same process. * server.h (server_state): Move own_buf to client_state. (client_state): Add in_buf to record the incoming packet when own_buf is overwritten. Add normalized_packet and pending. (struct client_states): Points to the current state. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/dyninst-low.cc | 519 +++++++++++++++++++++++++---------- gdb/gdbserver/dyninst-low.h | 3 +- gdb/gdbserver/dyninst-x86-low.cc | 32 ++- gdb/gdbserver/event-loop.c | 21 +- gdb/gdbserver/server.c | 568 ++++++++++++++++++++++---------------- gdb/gdbserver/server.h | 20 +- 6 files changed, 754 insertions(+), 409 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/dyninst-low.cc b/gdb/gdbserver/dyninst-low.cc index 4e3ac2c..199d7a1 100644 --- a/gdb/gdbserver/dyninst-low.cc +++ b/gdb/gdbserver/dyninst-low.cc @@ -54,8 +54,13 @@ extern "C" } -#define DYNERR(errstr,args...) \ +#define DYNERRMSG(errstr,args...) \ fprintf (stderr, "%s %s " errstr "\n", __FUNCTION__, dyninst_process->getLastErrorMsg(), ##args); +#define DYNERR(errstr,args...) \ + fprintf (stderr, "%s " errstr "\n", __FUNCTION__, ##args); +#define DEBUG_ENTER() if (debug_threads) debug_enter() +#define DEBUG_EXIT() if (debug_threads) debug_exit() + using namespace std; using namespace __gnu_cxx; @@ -71,6 +76,25 @@ LibrarySet dyninst_libset; Thread::const_ptr NULL_Thread = Thread::const_ptr(); +void +dump_procset () +{ + ProcessSet::iterator it; + ThreadPool::const_iterator thidx; + 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'; + } +} + /* Are there pending callbacks for handleEvents */ bool have_callbacks () __attribute__ ((unused)); @@ -125,69 +149,80 @@ class EventSet { private: /* The list of events that handleEvents has encountered */ - std::map current_events; + std::vector > current_events; public: EventSet() { NULL_Event = Event::const_ptr(); } Event::const_ptr NULL_Event; - void insert (Event::const_ptr ev) { + 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[ptid] = ev; + current_events.push_back(make_pair (ptid, ev)); if (debug_threads) + { dump("after insert "); + dump_procset (); + } } void erase (Event::const_ptr ev) - { - std::map::iterator it; - for (it = current_events.begin() ; - it != current_events.end(); ++it) - { - Event::const_ptr event = it->second; - if (event == ev) - { - current_events.erase(it); - break; - } - } - if (debug_threads) - dump("after erase "); - } + { + if (ev != NULL_Event) + DEBUG(ev->name()); + std::vector >::iterator it; + for (it = current_events.begin() ; + it != current_events.end(); ++it) + { + Event::const_ptr event = it->second; + if (event == ev) + { + current_events.erase(it); + break; + } + } + if (debug_threads) + dump("after erase "); + } /* Get the event for a given PTID */ Event::const_ptr get (ptid_t ptid) { Event::const_ptr event; + int attempt = 1; - if (! Process::handleEvents(true)) - return NULL_Event; - DEBUG("after handleEvents",pid_to_string(ptid)); - - std::map::reverse_iterator rit; - for (rit = current_events.rbegin() ; - rit != current_events.rend(); ++rit) + do { - ptid_t ceptid = rit->first; - event = rit->second; - DEBUG(event->name() << " " << ptid.pid << " " << ceptid.pid << " " << ptid.lwp << " " << ceptid.lwp << " " << ptid.tid << " " << ceptid.tid); - if (ptid.pid == -1 - || (ceptid.pid == ptid.pid)) -// || (ceptid.pid == ptid.pid -// && ceptid.lwp == ptid.lwp)) + std::vector >::iterator it; + for (it = current_events.begin() ; + it != current_events.end(); ++it) { - DEBUG("returning event " << event->name()); - return event; + ptid_t ceptid = it->first; + event = it->second; + if (ptid.pid == -1 + || (ceptid.pid == ptid.pid)) +// || (ceptid.pid == ptid.pid +// && ceptid.lwp == ptid.lwp)) + { + CORE_ADDR pc = (the_low_target.get_pc) (event->getThread()); + DEBUG(event->name() << ' ' << ceptid.pid << '/' << ceptid.lwp << "pc=" << pc); + return event; + } } + if (! Process::handleEvents(true)) + return NULL_Event; + DEBUG("after handleEvents",pid_to_string(ptid)); + attempt += 1; } + while (attempt <= 2); + DEBUG("returning null event"); return NULL_Event; } bool is_stopped (Event::const_ptr event) { - if (event == NULL) - return false; - else + if (event != NULL) return event->getEventType().code() == EventType::Stop; + else return false; } bool is_exit (Event::const_ptr event) @@ -197,7 +232,6 @@ public: else return false; } - bool is_breakpoint(Event::const_ptr event) { if (event != NULL) @@ -239,28 +273,59 @@ public: DEBUG(event->getEventType().code() << " UserThreadCreate"); return newlwp_ev->getNewThread(); } + else if (event->getEventType().code() == EventType::ThreadCreate) + { + EventNewUserThread::const_ptr newlwp_ev = event->getEventNewUserThread(); + if (event != NULL) + DEBUG(event->getEventType().code() << " ThreadCreate"); + return newlwp_ev->getNewThread(); + } } return NULL_Thread; } - bool is_threaddestroy(Event::const_ptr event) + Thread::const_ptr is_threaddestroy (Event::const_ptr event) { + Thread::const_ptr thr; if (event != NULL) - return event->getEventType().code() == EventType::UserThreadDestroy; - else return false; + { + if (event->getEventType().code() == EventType::LWPDestroy) + { + EventLWPDestroy::const_ptr lwpd_ev = event->getEventLWPDestroy(); + if (event != NULL) + DEBUG(event->getEventType().code() << " LWPDestroy"); + return lwpd_ev->getThread(); + } + else if (event->getEventType().code() == EventType::UserThreadDestroy) + { + EventUserThreadDestroy::const_ptr utd_ev = event->getEventUserThreadDestroy(); + if (event != NULL) + DEBUG(event->getEventType().code() << " UserThreadDestroy"); + return utd_ev->getThread(); + } + else if (event->getEventType().code() == EventType::ThreadDestroy) + { + EventThreadDestroy::const_ptr td_ev = event->getEventThreadDestroy(); + if (event != NULL) + DEBUG(event->getEventType().code() << " ThreadDestroy"); + return td_ev->getThread(); + } + } + return NULL_Thread; } void dump (string comment) { - std::map::iterator it; + int idx = 1; + std::vector >::iterator it; for (it = current_events.begin() ; it != current_events.end(); ++it) { - ptid_t ptid = it->first; Event::const_ptr event = it->second; if (event == NULL) continue; - DEBUG(comment << event->name() << " pid=" << ptid.pid << " lwp=" << ptid.lwp << " tid=" << ptid.tid); + DEBUG(dec << idx << hex << ' ' << comment << event->name(), pid_to_string (event)); + idx += 1; } } @@ -268,14 +333,12 @@ public: void -pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid) +pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid, CORE_ADDR pc) { if (pid == -1) cerr << "pid=*"; else { - ptid_t ptid = ptid_build (pid, lwp, tid); - struct thread_info *ti = find_thread_ptid (ptid); cerr << "pid=" << pid; if (lwp < 0) cerr << " lwp=*"; @@ -283,23 +346,40 @@ pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid) cerr << " lwp=" << lwp; if (tid > 0) cerr << " thr=" << tid; - if (ti != NULL) + + string source = ""; + if (pc == 0) { - struct regcache *regcache = get_thread_regcache (ti, 1); - CORE_ADDR pc = (*the_low_target.get_pc) (regcache); - cerr << " pc=" << pc; + struct thread_info *ti = find_thread_ptid (ptid_build (pid, lwp, tid)); + if (ti == NULL) + ti = find_thread_ptid (ptid_build (pid, lwp, 0)); + if (ti != NULL) + { + struct regcache *regcache = get_thread_regcache (ti, 0); + pc = (*the_low_target.read_pc) (regcache); + source = " cached"; + } } + cerr << source << " pc=" << pc; } cerr << ' '; } +static Thread::const_ptr dyninst_get_thread(ptid_t ptid); + /* Pretty print a pid/lwp/tid tuple */ void pid_to_string (ptid_t ptid) { - pid_to_string (ptid.pid, ptid.lwp, ptid.tid); + CORE_ADDR pc; + Thread::const_ptr thr = dyninst_get_thread(ptid); + if (thr != NULL_Thread) + pc = (the_low_target.get_pc) (thr); + else + pc = 0; + pid_to_string (ptid.pid, ptid.lwp, ptid.tid, pc); } void @@ -313,7 +393,9 @@ pid_to_string (Thread::const_ptr thr) else tid = -1; - pid_to_string (thr->getProcess()->getPid(), thr->getLWP(), tid); + CORE_ADDR pc = (the_low_target.get_pc) (thr); + + pid_to_string (thr->getProcess()->getPid(), thr->getLWP(), tid, pc); } void @@ -351,6 +433,17 @@ struct thread_info_private }; +static Thread::const_ptr +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; + else + return NULL_Thread; +} + + /* Add a PROCESS PID, that is possibly being ATTACHED */ static struct process_info * @@ -413,7 +506,7 @@ dyninst_get_inferior_thread() struct thread_info_private *tip = (struct thread_info_private*)(cs->ss->current_thread->target_data); if (!tip) - error ("No inferior thread"); + DYNERR ("No inferior thread"); return tip->thread; } @@ -423,8 +516,21 @@ dyninst_get_inferior_thread() Process::cb_ret_t signal_handler(Event::const_ptr ev) { - events.insert(ev); DEBUG(ev->name()); + if (ev->name() != "post-LWPDestroy") + events.insert(ev); + return Process::cbDefault; +} + + +/* Handle a dyninst Breakpoint event */ + +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()); + events.insert(ev); return Process::cbDefault; } @@ -434,21 +540,34 @@ signal_handler(Event::const_ptr ev) Process::cb_ret_t singlestep_handler(Event::const_ptr ev) { - events.insert(ev); DEBUG(ev->name()); + events.insert(ev); ev->getThread()->setSingleStepMode(false); return Process::cbThreadStop; } +// Handle a dyninst LWPDestroy event + +Process::cb_ret_t +lwpdestroy_handler(Event::const_ptr ev) +{ + Process::cb_ret_t cbret (Process::cbProcStop, Process::cbProcStop); + DEBUG(ev->name()); + if (ev->name() != "post-LWPDestroy") + events.insert(ev); + return cbret; +} + + /* Handle a dyninst Stop event */ Process::cb_ret_t stop_handler(Event::const_ptr ev) { + DEBUG(ev->name() << " stopped=" << ev->getThread()->isStopped() << " running=" << ev->getThread()->isRunning(), pid_to_string (ev->getThread())); events.insert(ev); - DEBUG(ev->name()); - return Process::cbThreadStop; + return Process::cbDefault; } @@ -462,7 +581,7 @@ library_handler(Event::const_ptr ev) for (set::const_iterator i = lib_ev->libsAdded().begin(); i != lib_ev->libsAdded().end(); i++) { Library::ptr lib = *i; - DEBUG("added library " << lib->getAbsoluteName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); + DEBUG("added library " << lib->getAbsoluteName() << ' ' << lib->getDynamicAddress() << ' ' << lib->getLoadAddress() << endl); } return Process::cbDefault; @@ -495,17 +614,17 @@ dyninst_create_inferior (char *program, char **allargs) Process::ptr dyninst_process = Process::createProcess(exec, args); if (dyninst_process == Process::ptr()) - error ("No such file: %s\n", exec.c_str()); + DYNERRMSG ("No such file: %s\n", exec.c_str()); dyninst_procset->insert(dyninst_process); myregisterCB(EventType::Bootstrap, signal_handler); - myregisterCB(EventType::Breakpoint, signal_handler); + myregisterCB(EventType::Breakpoint, breakpoint_handler); myregisterCB(EventType::Crash, signal_handler); myregisterCB(EventType::Exec, signal_handler); myregisterCB(EventType::Exit, signal_handler); myregisterCB(EventType::Fork, signal_handler); myregisterCB(EventType::LWPCreate, signal_handler); - myregisterCB(EventType::LWPDestroy, signal_handler); + myregisterCB(EventType::LWPDestroy, lwpdestroy_handler); myregisterCB(EventType::Library, library_handler); myregisterCB(EventType::RPC, signal_handler); myregisterCB(EventType::Signal, signal_handler); @@ -539,7 +658,7 @@ dyninst_create_inferior (char *program, char **allargs) } if (! dyninst_process->stopProc()) - error ("Cannot stop process %ld: %s", (long int)pid, getLastErrorMsg()); + DYNERRMSG ("Cannot stop process %ld", (long int)pid); return dyninst_process->getPid(); } @@ -551,16 +670,15 @@ dyninst_attach (unsigned long pid) ProcessSet::iterator procset_it = dyninst_procset->find(pid); if (procset_it != dyninst_procset->end()) DEBUG("already attached to pid " << pid); - Process::ptr dyninst_proc = Process::attachProcess(pid); - if (dyninst_proc == Process::ptr()) - error ("Cannot attach to process %ld: %s", - pid, getLastErrorMsg()); + Process::ptr dyninst_process = Process::attachProcess(pid); + if (dyninst_process == Process::ptr()) + DYNERRMSG ("Cannot attach to process %ld", pid); - dyninst_procset->insert(dyninst_proc); + dyninst_procset->insert(dyninst_process); DEBUG("pid=" << pid); myregisterCB(EventType::Bootstrap, signal_handler); - myregisterCB(EventType::Breakpoint, signal_handler); + myregisterCB(EventType::Breakpoint, breakpoint_handler); myregisterCB(EventType::Crash, signal_handler); myregisterCB(EventType::Exec, signal_handler); myregisterCB(EventType::Exit, signal_handler); @@ -577,14 +695,13 @@ dyninst_attach (unsigned long pid) // ThreadDestroy, UserThreadDestroy handled via LWPDestroy - if (dyninst_proc == Process::ptr()) - error ("Cannot attach to process %lu: %s (%d)\n", pid, - dyninst_proc->getLastErrorMsg(), dyninst_proc->getLastError()); + if (dyninst_process == Process::ptr()) + DYNERRMSG ("Cannot attach to process %lu", pid); - dyninst_add_process (pid, 1, dyninst_proc); + dyninst_add_process (pid, 1, dyninst_process); ThreadPool::iterator thidx; - for (thidx = dyninst_proc->threads().begin(); - thidx != dyninst_proc->threads().end(); thidx++) + for (thidx = dyninst_process->threads().begin(); + thidx != dyninst_process->threads().end(); thidx++) { bool reg_map_setup = false; RegisterPool regpool; @@ -600,10 +717,10 @@ dyninst_attach (unsigned long pid) } LibraryPool::iterator libidx; - for (libidx = dyninst_proc->libraries().begin(); libidx != dyninst_proc->libraries().end(); libidx++) + for (libidx = dyninst_process->libraries().begin(); libidx != dyninst_process->libraries().end(); libidx++) { Library::ptr lib = *libidx; - DEBUG("added library " << lib->getName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); + DEBUG("added library " << lib->getName() << ' ' << lib->getDynamicAddress() << ' ' << lib->getLoadAddress() << endl); } return 0; @@ -617,36 +734,41 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) client_state *cs = get_client_state (); + DEBUG_ENTER (); + for (int i = 0; i < (int)n; i++) { hooks/post-receive -- Repository for Project Archer.