From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 25733 invoked by alias); 20 Jan 2015 15:19:32 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 17554 invoked by uid 440); 20 Jan 2015 15:16:27 -0000 Date: Tue, 20 Jan 2015 15:19:00 -0000 Message-ID: <20150120151619.17429.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/dyninst: Remove global state, an initial step to enable multiple targets. X-Git-Refname: refs/heads/scox/dyninst X-Git-Reftype: branch X-Git-Oldrev: 02afeed30a601bea111805ef89f3c6a27dd59ad9 X-Git-Newrev: aa94c518bc927f2214532a512d9c7399f9ec32d2 X-SW-Source: 2015-q1/txt/msg00000.txt.bz2 List-Id: The branch, scox/dyninst has been updated via aa94c518bc927f2214532a512d9c7399f9ec32d2 (commit) from 02afeed30a601bea111805ef89f3c6a27dd59ad9 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit aa94c518bc927f2214532a512d9c7399f9ec32d2 Author: Stan Cox Date: Tue Jan 20 10:08:12 2015 -0500 Remove global state, an initial step to enable multiple targets. * server.h (client_state): Data structure for per client info. Currently, global state has been moved here. * server.c: Move global state to client_state. (set_client_state, get_client_state, new_client_state): New. Currently, there is only one client_state. (start_inferior, handle_btrace_general_set) (parse_debug_format_options, handle_monitor_command) (handle_qxfer_btrace, handle_query, handle_v_cont, resume) (handle_v_attach, handle_v_run, handle_v_kill, handle_v_requests) (find_status_pending_thread_callback, handle_status) (captured_main, process_serial_event, handle_target_event): Use client_state. * target.c (set_desired_thread, mywait, target_stop_and_wait): Likewise. * remote-utils.c (handle_accept_event, remote_prepare) (remote_open, prepare_resume_reply): Likewise. * linux-low.c (linux_create_inferior, linux_attach_lwp) (linux_attach, get_detach_signal, lp_status_maybe_breakpoint) (linux_wait_1, wait_for_sigstop, linux_resume) (linux_look_up_symbols, linux_request_interrupt) (linux_unpause_all, linux_prepare_to_access_memory): Likewise. * spu-low.c (spu_wiat): Likewise. * win32-low.c (handle_output_debug_string): Likewise * dyninst-low.cc (DYNERR): New. (ptid_t operator< operator==): New. (EventSet): Use a map , change callers. (is_threadcreate): Make LWPCreate, UserThreadCreate aware. (stop_handler): New. (dyninst_resume): Improve thread handling. (dyninst_wait_1): Likewise. (dyninst_fetch_registers): Stop thread if needed. (dyninst_read_memory, dyninst_write_memory): Improve error handling. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/dyninst-low.cc | 500 ++++++++++++++++++++++------------- gdb/gdbserver/linux-low.c | 51 +++-- gdb/gdbserver/remote-utils.c | 31 ++- gdb/gdbserver/remote-utils.h | 2 +- gdb/gdbserver/server.c | 606 ++++++++++++++++++++++-------------------- gdb/gdbserver/server.h | 60 ++++- gdb/gdbserver/spu-low.c | 5 +- gdb/gdbserver/target.c | 17 +- gdb/gdbserver/win32-low.c | 3 +- 9 files changed, 745 insertions(+), 530 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/dyninst-low.cc b/gdb/gdbserver/dyninst-low.cc index 39747ac..fec8825 100644 --- a/gdb/gdbserver/dyninst-low.cc +++ b/gdb/gdbserver/dyninst-low.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2009-2014 Free Software Foundation, Inc. +/* Copyright (C) 2009-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -46,13 +46,16 @@ extern "C" #include #include -#define DEBUG(func,cerrstr,args...) \ +#define DEBUG(cerrstr,args...) \ if (debug_threads) { \ - cerr << "DEBUG(dyninst): " << func << ' '; \ + cerr << "DEBUG(dyninst): " << __FUNCTION__ << ' '; \ args; \ cerr << cerrstr << '\n'; \ } +#define DYNERR(errstr,args...) \ + error ("%s %s " errstr, __FUNCTION__, dyninst_process->getLastErrorMsg(), ##args); + using namespace std; using namespace __gnu_cxx; using namespace Dyninst; @@ -69,6 +72,8 @@ Thread::const_ptr NULL_Thread = Thread::const_ptr(); /* Are there pending callbacks for handleEvents */ +bool have_callbacks () __attribute__ ((unused)); + bool have_callbacks () { @@ -81,8 +86,8 @@ have_callbacks () FD_SET (evNotify()->getFD(), &set); /* Initialize the timeout data structure. */ - timeout.tv_sec = 1; - timeout.tv_usec = 0; + timeout.tv_sec = 0; + timeout.tv_usec = 250; int result = TEMP_FAILURE_RETRY (select (FD_SETSIZE, &set, NULL, NULL, @@ -94,27 +99,49 @@ have_callbacks () return true; } - void pid_to_string (Event::const_ptr ev); void pid_to_string (ptid_t ptid); +bool operator<(const ptid_t & l, const ptid_t & r ) +{ + if (l.pid < r.pid) + return true; + if (l.tid < r.tid) + return true; + if (l.lwp < r.lwp) + return true; + return false; +} + +bool operator==(const ptid_t & l, const ptid_t & r ) +{ + if (l.pid == r.pid && l.tid == r.tid && l.lwp == r.lwp) + return true; + return false; +} + class EventSet { private: /* The list of events that handleEvents has encountered */ - std::vector current_events; + std::vector current_events_; + std::map current_events; public: EventSet() { NULL_Event = Event::const_ptr(); } Event::const_ptr NULL_Event; - void insert (Event::const_ptr ev) { current_events.push_back(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(ev); + } void erase (Event::const_ptr ev) { - std::vector::iterator it; + std::map::iterator it; for (it = current_events.begin() ; it != current_events.end(); ++it) { - Event::const_ptr event = *it; + Event::const_ptr event = it->second; if (event == ev) { current_events.erase(it); @@ -127,28 +154,29 @@ public: Event::const_ptr get (ptid_t ptid) { - DEBUG("events.get",(!have_callbacks() ? "(no callbacks)" : ""),pid_to_string (ptid)); Event::const_ptr event; - bool result; - result = Process::handleEvents(true); - if (!result) + if (! Process::handleEvents(true)) return NULL_Event; - DEBUG("events.get","after handleEvents"); + DEBUG("after handleEvents",pid_to_string(ptid)); - std::vector::reverse_iterator rit; + std::map::reverse_iterator rit; for (rit = current_events.rbegin() ; rit != current_events.rend(); ++rit) { - - event = *rit; - if (ptid.pid == -1 || event->getProcess()->getPid() == ptid.pid) + 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)) { - DEBUG("events.get","returning event " << event->name()); + DEBUG("returning event " << event->name()); return event; } } - DEBUG("events.get","returning null event"); + DEBUG("returning null event"); return NULL_Event; } @@ -190,13 +218,25 @@ public: else return false; } - bool is_threadcreate (Event::const_ptr event) + Thread::const_ptr is_threadcreate (Event::const_ptr event) { + Thread::const_ptr thr; if (event != NULL) - DEBUG("is_threadcreate", event->getEventType().code() << EventType::LWPCreate); + DEBUG(event->getEventType().code() << " " << EventType::LWPCreate); if (event != NULL) - return event->getEventType().code() == EventType::LWPCreate; - else return false; + { + if (event->getEventType().code() == EventType::LWPCreate) + { + EventNewLWP::const_ptr newlwp_ev = event->getEventNewLWP(); + return newlwp_ev->getNewThread(); + } + else if (event->getEventType().code() == EventType::UserThreadCreate) + { + EventNewUserThread::const_ptr newlwp_ev = event->getEventNewUserThread(); + return newlwp_ev->getNewThread(); + } + } + return NULL_Thread; } bool is_threaddestroy(Event::const_ptr event) @@ -208,14 +248,15 @@ public: void dump () { - std::vector::iterator it; + std::map::iterator it; for (it = current_events.begin() ; it != current_events.end(); ++it) { - Event::const_ptr event = *it; + ptid_t ptid = it->first; + Event::const_ptr event = it->second; if (event == NULL) continue; - DEBUG("dump",event->name(), pid_to_string (event)); + DEBUG(event->name() << " pid=" << ptid.pid << " lwp=" << ptid.lwp << " tid=" << ptid.tid); } } @@ -226,11 +267,13 @@ void pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid) { if (pid == -1) - cerr << "pid=NULL"; + cerr << "pid=*"; else { cerr << "pid=" << pid; - if (pid != lwp && lwp > 0) + if (lwp < 0) + cerr << " lwp=*"; + else cerr << " lwp=" << lwp; if (tid > 0) cerr << " thr=" << tid; @@ -335,9 +378,9 @@ dyninst_add_thread(int pid, Thread::const_ptr thread) static Thread::const_ptr dyninst_get_inferior_thread() { - DEBUG("dyninst_get_inferior_thread", "current_thread=" << current_thread); + DEBUG("current_thread=" << current_thread); struct thread_info_private *tip = (struct thread_info_private*)(current_thread->target_data); - DEBUG("dyninst_get_inferior_thread", "", pid_to_string (current_thread->entry.id)); + DEBUG("", pid_to_string (current_thread->entry.id)); if (!tip) error ("No inferior thread"); return tip->thread; @@ -350,7 +393,7 @@ Process::cb_ret_t signal_handler(Event::const_ptr ev) { events.insert(ev); - DEBUG("signal_handler", ev->name()); + DEBUG(ev->name()); return Process::cbDefault; } @@ -361,12 +404,23 @@ Process::cb_ret_t singlestep_handler(Event::const_ptr ev) { events.insert(ev); - DEBUG("singlestep_handler", ev->name()); + DEBUG(ev->name()); ev->getThread()->setSingleStepMode(false); return Process::cbThreadStop; } +/* Handle a dyninst Stop event */ + +Process::cb_ret_t +stop_handler(Event::const_ptr ev) +{ + events.insert(ev); + DEBUG(ev->name()); + return Process::cbThreadStop; +} + + /* Handle a dyninst Library event */ Process::cb_ret_t @@ -377,8 +431,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("dyninst_attach", "added library " << lib->getAbsoluteName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); -// loaded_dll (lib->getAbsoluteName().c_str(), lib->getDynamicAddress()); + DEBUG("added library " << lib->getAbsoluteName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); } return Process::cbDefault; @@ -388,10 +441,8 @@ library_handler(Event::const_ptr ev) void myregisterCB(EventType et, Process::cb_func_t f) { - bool result = Process::registerEventCallback(et, f); - if (!result) { + if (! Process::registerEventCallback(et, f)) cout << "Error registering thread callback " << et.name() << '\n'; - } } @@ -422,19 +473,19 @@ dyninst_create_inferior (char *program, char **allargs) 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::Library, library_handler); myregisterCB(EventType::RPC, signal_handler); myregisterCB(EventType::Signal, signal_handler); myregisterCB(EventType::SingleStep, singlestep_handler); - myregisterCB(EventType::Stop, signal_handler); + myregisterCB(EventType::Stop, stop_handler); myregisterCB(EventType::Terminate, signal_handler); - myregisterCB(EventType::ThreadCreate, signal_handler); - myregisterCB(EventType::ThreadDestroy, signal_handler); - myregisterCB(EventType::UserThreadCreate, signal_handler); - myregisterCB(EventType::UserThreadDestroy, signal_handler); + // ThreadCreate, UserThreadCreate handled via LWPCreate + // ThreadDestroy, UserThreadDestroy handled via LWPDestroy - DEBUG("dyninst_create_inferior", "created process " << dyninst_process->getPid() << program); + DEBUG("created process " << dyninst_process->getPid() << program); pid_t pid = dyninst_process->getPid(); dyninst_add_process (pid, 0, dyninst_process); @@ -443,12 +494,13 @@ dyninst_create_inferior (char *program, char **allargs) for (thidx = dyninst_process->threads().begin(); thidx != dyninst_process->threads().end(); thidx++) { - DEBUG("dyninst_create_inferior", "created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); + DEBUG("created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); Thread::ptr th = *thidx; dyninst_add_thread (pid, th); } - dyninst_process->stopProc(); + if (! dyninst_process->stopProc()) + error ("Cannot stop process %ld: %s", (long int)pid, getLastErrorMsg()); return dyninst_process->getPid(); } @@ -457,24 +509,30 @@ dyninst_create_inferior (char *program, char **allargs) static int dyninst_attach (unsigned long pid) { - static Process::ptr dyninst_proc = Process::attachProcess(pid); + Process::ptr dyninst_proc = Process::attachProcess(pid); + if (dyninst_proc == Process::ptr()) + error ("Cannot attach to process %ld: %s", + pid, getLastErrorMsg()); + + dyninst_procset->insert(dyninst_proc); - DEBUG("dyninst_attach", "pid=" << pid); + DEBUG("pid=" << pid); myregisterCB(EventType::Bootstrap, signal_handler); myregisterCB(EventType::Breakpoint, signal_handler); myregisterCB(EventType::Crash, signal_handler); myregisterCB(EventType::Exec, signal_handler); myregisterCB(EventType::Exit, signal_handler); myregisterCB(EventType::Fork, signal_handler); - myregisterCB(EventType::Library, signal_handler); + myregisterCB(EventType::LWPCreate, signal_handler); + myregisterCB(EventType::LWPDestroy, signal_handler); + myregisterCB(EventType::Library, library_handler); myregisterCB(EventType::RPC, signal_handler); myregisterCB(EventType::Signal, signal_handler); - myregisterCB(EventType::SingleStep, signal_handler); - myregisterCB(EventType::Stop, signal_handler); + myregisterCB(EventType::SingleStep, singlestep_handler); + myregisterCB(EventType::Stop, stop_handler); myregisterCB(EventType::Terminate, signal_handler); - myregisterCB(EventType::ThreadCreate, signal_handler); - myregisterCB(EventType::ThreadDestroy, signal_handler); - myregisterCB(EventType::UserThreadCreate, signal_handler); + // ThreadCreate, UserThreadCreate handled via LWPCreate + // ThreadDestroy, UserThreadDestroy handled via LWPDestroy if (dyninst_proc == Process::ptr()) @@ -486,7 +544,7 @@ dyninst_attach (unsigned long pid) for (thidx = dyninst_proc->threads().begin(); thidx != dyninst_proc->threads().end(); thidx++) { - DEBUG("dyninst_attach", "created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); + DEBUG("created thread " << (*thidx)->getTID() << ' ' << (*thidx)->getLWP()); Thread::const_ptr th = *thidx; dyninst_add_thread (pid, th); } @@ -495,8 +553,7 @@ dyninst_attach (unsigned long pid) for (libidx = dyninst_proc->libraries().begin(); libidx != dyninst_proc->libraries().end(); libidx++) { Library::ptr lib = *libidx; - DEBUG("dyninst_attach", "added library " << lib->getName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); -// loaded_dll (lib->getAbsoluteName().c_str(), lib->getDynamicAddress()); + DEBUG("added library " << lib->getName() << " " << lib->getDynamicAddress() << " " << lib->getLoadAddress() << endl); } return 0; @@ -507,68 +564,85 @@ dyninst_attach (unsigned long pid) static void dyninst_resume (struct thread_resume *resume_info, size_t n) { - /* FIXME: Assume for now that n == 1. */ - ptid_t ptid = resume_info[0].thread; + for (int i = 0; i < (int)n; i++) + { + DEBUG("",pid_to_string(resume_info[i].thread)); + ptid_t ptid = resume_info[i].thread; - if (ptid_equal (ptid, minus_one_ptid)) - ptid = thread_to_gdb_id (current_thread); + if (ptid_equal (ptid, minus_one_ptid)) + ptid = thread_to_gdb_id (current_thread); - Dyninst::PID pid = ptid_get_pid (ptid); - ProcessSet::iterator procset_it = dyninst_procset->find(pid); - if (procset_it == dyninst_procset->end()) - error ("Cannot resume process %lu\n", (long unsigned)pid); + Dyninst::PID pid = ptid_get_pid (ptid); + ProcessSet::iterator procset_it = dyninst_procset->find(pid); + if (procset_it == dyninst_procset->end()) + error ("Cannot resume process %lu\n", (long unsigned)pid); - Process::ptr dyninst_process = *procset_it; + Process::ptr dyninst_process = *procset_it; - DEBUG("dyninst_resume", "", pid_to_string (ptid)); - DEBUG("dyninst_resume", "found proc " << dyninst_process->getPid()); - ThreadPool::iterator thidx; - Thread::ptr th; + DEBUG("", pid_to_string (ptid)); + DEBUG("found proc " << dyninst_process->getPid()); + ThreadPool::iterator thidx; + Thread::ptr th; - if (dyninst_process->isTerminated()) - return; - for (thidx = dyninst_process->threads().begin(); - thidx != dyninst_process->threads().end(); thidx++) - { - th = *thidx; - if (th->getTID() == ptid.tid) + if (dyninst_process->isTerminated()) + return; + + if (resume_info[i].thread == minus_one_ptid) { - th = *thidx; - break; + DEBUG("before regcache_invalidate"); + regcache_invalidate (); + DEBUG("before continue pid=" << pid); + if (! dyninst_process->continueProc()) + DEBUG("Unable to continueProc " << dyninst_process->getLastErrorMsg()); + return; } - } - // resume_continue, resume_step, resume_stop - struct thread_info_private *tip = (struct thread_info_private*)(current_thread->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 (current_thread, 1); - CORE_ADDR pc = (*the_low_target.get_pc) (regcache); - DEBUG("dyninst_resume", "range " << resume_info->step_range_start << "/" << resume_info->step_range_end << " pc=" << pc << "kind=" << resume_info[0].kind); - if (resume_info[0].kind == resume_step) - { - DEBUG("dyninst_resume", "in step mode", pid_to_string (th)); - th->setSingleStepMode(true); + for (thidx = dyninst_process->threads().begin(); + thidx != dyninst_process->threads().end(); thidx++) + { + th = *thidx; + if (th->getLWP() == ptid.lwp) + { + // 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); + 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); + CORE_ADDR pc = (*the_low_target.get_pc) (regcache); + DEBUG("range " << resume_info->step_range_start << "/" << resume_info->step_range_end << " pc=" << pc << " kind=" << resume_info[i].kind); + + switch (resume_info[i].kind) + { + case resume_step: + DEBUG("in step mode", pid_to_string (th)); + if (! th->setSingleStepMode(true)) + DYNERR("Unable to setSingleStepMode"); + case resume_continue: + regcache_invalidate (); + if (! th->continueThread()) + DYNERR("Unable to continueThread"); + break; + case resume_stop: + if (! th->stopThread()) + DYNERR("Unable to stopThread"); + } + } + } } - else - th->setSingleStepMode(false); - - regcache_invalidate (); - - DEBUG("dyninst_resume","before continue"); - bool result = dyninst_process->continueProc(); - if (! result) - cout << "Cannot continueProc " << dyninst_process->getLastErrorMsg() << '\n'; } + /* Handle a vCont packet */ +static void dyninst_continue (ptid_t) __attribute__ ((unused)); + static void dyninst_continue (ptid_t ptid) hooks/post-receive -- Repository for Project Archer.