From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19992 invoked by alias); 12 Nov 2014 15:08:55 -0000 Mailing-List: contact archer-commits-help@sourceware.org; run by ezmlm Sender: Precedence: bulk List-Post: List-Help: List-Subscribe: Received: (qmail 19971 invoked by uid 440); 12 Nov 2014 15:08:55 -0000 Date: Wed, 12 Nov 2014 15:08:00 -0000 Message-ID: <20141112150854.19944.qmail@sourceware.org> From: scox@sourceware.org To: archer-commits@sourceware.org Subject: [SCM] scox/dyninst: Add range step handling. X-Git-Refname: refs/heads/scox/dyninst X-Git-Reftype: branch X-Git-Oldrev: c93a51b7e31702961ecb060b36740dd0390d0a51 X-Git-Newrev: bc5aece835a317ef016557d57a6a32178091d821 X-SW-Source: 2014-q4/txt/msg00002.txt.bz2 List-Id: The branch, scox/dyninst has been updated via bc5aece835a317ef016557d57a6a32178091d821 (commit) from c93a51b7e31702961ecb060b36740dd0390d0a51 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email. - Log ----------------------------------------------------------------- commit bc5aece835a317ef016557d57a6a32178091d821 Author: Stan Cox Date: Wed Nov 12 10:05:56 2014 -0500 Add range step handling. * dyninst-low.cc (BreakpointSet, dyninst_bpset): New. (dyninst_resume): Add range step handling. (in_step_range): Check range step boundary. (dyninst_wait_1): Add range step handling. (dyninst_remove_point): Likewise. (dyninst_supports_range_stepping): Likewise. * dyninst-low.h: Likewise. * dyninst-x86-low.cc: Likewise. ----------------------------------------------------------------------- Summary of changes: gdb/gdbserver/ChangeLog | 11 ++ gdb/gdbserver/dyninst-low.cc | 221 +++++++++++++++++++++++-------------- gdb/gdbserver/dyninst-low.h | 1 + gdb/gdbserver/dyninst-x86-low.cc | 8 ++ 4 files changed, 157 insertions(+), 84 deletions(-) First 500 lines of diff: diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index e36db7f..f6113f8 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,14 @@ +2014-11-11 Stan Cox + + * dyninst-low.cc (BreakpointSet, dyninst_bpset): New. + (dyninst_resume): Add range step handling. + (in_step_range): Check range step boundary. + (dyninst_wait_1): Add range step handling. + (dyninst_remove_point): Likewise. + (dyninst_supports_range_stepping): Likewise. + * dyninst-low.h: Likewise. + * dyninst-x86-low.cc: Likewise. + 2014-10-31 Stan Cox * dyninst-low.cc: New. Preliminary generic rsp packet handling for dyninst rsp server. diff --git a/gdb/gdbserver/dyninst-low.cc b/gdb/gdbserver/dyninst-low.cc index 8cf9478..018fa61 100644 --- a/gdb/gdbserver/dyninst-low.cc +++ b/gdb/gdbserver/dyninst-low.cc @@ -39,8 +39,8 @@ extern "C" #include #include #include "dyninst-low.h" -#include // std::cout -#include // std::ostringstream +#include +#include #define DEBUG(func,cerrstr,args...) \ if (debug_threads) { \ @@ -55,6 +55,8 @@ using namespace Dyninst; using namespace ProcControlAPI; +typedef std::vector BreakpointSet; +BreakpointSet dyninst_bpset; ProcessSet::ptr dyninst_procset; Thread::const_ptr NULL_Thread = Thread::const_ptr(); @@ -146,7 +148,7 @@ public: bool is_stopped (Event::const_ptr event) { - if (event == NULL || event == NULL_Event) + if (event == NULL) return false; else return event->getEventType().code() == EventType::Stop; @@ -154,7 +156,7 @@ public: bool is_exit (Event::const_ptr event) { - if (event != NULL && event != NULL_Event) + if (event != NULL) return event->getEventType().code() == EventType::Exit; else return false; } @@ -162,7 +164,7 @@ public: bool is_breakpoint(Event::const_ptr event) { - if (event != NULL && event != NULL_Event) + if (event != NULL) return event->getEventType().code() == EventType::Breakpoint; else return false; } @@ -170,25 +172,32 @@ public: bool is_singlestep(Event::const_ptr event) { - if (event != NULL && event != NULL_Event) + if (event != NULL) return event->getEventType().code() == EventType::SingleStep; else return false; } bool is_signal (Event::const_ptr event) { - if (event != NULL && event != NULL_Event) + if (event != NULL) return event->getEventType().code() == EventType::Signal; else return false; } bool is_threadcreate (Event::const_ptr event) { - if (event != NULL && event != NULL_Event) + if (event != NULL) return event->getEventType().code() == EventType::ThreadCreate; else return false; } + bool is_threaddestroy(Event::const_ptr event) + { + if (event != NULL) + return event->getEventType().code() == EventType::ThreadDestroy; + else return false; + } + void dump () { std::vector::iterator it; @@ -196,7 +205,7 @@ public: it != current_events.end(); ++it) { Event::const_ptr event = *it; - if (event == NULL_Event) + if (event == NULL) continue; DEBUG("dump",event->name(), pid_to_string (event)); } @@ -206,7 +215,7 @@ public: void -pid_to_string (long pid, long lwp, long tid) +pid_to_string (Dyninst::PID pid, Dyninst::LWP lwp, Dyninst::THR_ID tid) { if (pid == -1) cerr << "pid=NULL"; @@ -234,7 +243,7 @@ void pid_to_string (Thread::const_ptr thr) { long tid; - if (thr == NULL_Thread) + if (thr == NULL) return; if (thr->haveUserThreadInfo()) tid = thr->getTID(); @@ -247,7 +256,7 @@ pid_to_string (Thread::const_ptr thr) void pid_to_string (Event::const_ptr ev) { - if (ev == events.NULL_Event) + if (ev == NULL) return; pid_to_string (ev->getThread()); } @@ -274,6 +283,8 @@ struct thread_info_private { Thread::const_ptr thread; Event::const_ptr event; + CORE_ADDR step_range_start; + CORE_ADDR step_range_end; }; @@ -296,8 +307,8 @@ dyninst_add_process (int pid, int attached, Process::ptr process) void dyninst_add_thread(int pid, Thread::const_ptr thread) { - int lwp; - if (thread != NULL_Thread) + Dyninst::LWP lwp; + if (thread != NULL) { struct thread_info_private *tip = new struct thread_info_private; tip->thread = thread; @@ -467,8 +478,11 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) if (ptid_equal (ptid, minus_one_ptid)) ptid = thread_to_gdb_id (current_thread); - unsigned long pid = ptid_get_pid (ptid); + 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; DEBUG("dyninst_resume", "", pid_to_string (ptid)); @@ -490,10 +504,16 @@ dyninst_resume (struct thread_resume *resume_info, size_t n) } // 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); + th->setSingleStepMode(true); } else th->setSingleStepMode(false); @@ -522,12 +542,27 @@ dyninst_continue (ptid_t ptid) dyninst_resume (&resume_info, 1); } + +/* True if LWP is stopped in its stepping range. */ + +bool +in_step_range () +{ + struct thread_info_private *tip = (struct thread_info_private*)(current_thread->target_data); + struct regcache *regcache = get_thread_regcache (current_thread, 1); + CORE_ADDR pc = (*the_low_target.get_pc) (regcache); + DEBUG("in_step_range", "range " << tip->step_range_start << "/" << tip->step_range_end << " pc=" << pc << " returning" << (pc >= tip->step_range_start && pc < tip->step_range_end)); + + return (pc >= tip->step_range_start && pc < tip->step_range_end); +} + + /* Wait for a thread PTID having a target STATUS */ static ptid_t dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) { - int pid = 0; + Dyninst::PID pid = 0; ptid_t new_ptid; @@ -551,24 +586,24 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) while (true) // wait events loop { - if ((event = events.get(new_ptid))) + if ((event = events.get(new_ptid))) { struct process_info *pi; pi = find_process_pid(pid); if (pi) pi->piprivate->last_wait_event_ptid = new_ptid; } - if (event == NULL || event == events.NULL_Event) - event = events.get(new_ptid); -// continue; + if (event == NULL) + event = events.get(new_ptid); - events.dump(); + events.dump(); if (events.is_threadcreate(event)) { Thread::const_ptr thr; - if (event != events.NULL_Event) +// if (event != events.NULL_Event) + if (event != NULL) thr = event->getThread(); else thr = NULL_Thread; @@ -577,61 +612,59 @@ dyninst_wait_1 (ptid_t ptid, struct target_waitstatus *status, int options) } else if (events.is_exit(event)) { - status->kind = TARGET_WAITKIND_EXITED; EventExit::const_ptr exit_ev = event->getEventExit(); + status->kind = TARGET_WAITKIND_EXITED; status->value.integer = exit_ev->getExitCode(); - DEBUG("dyninst_wait_1", "process exited with code: " << status->value.integer); + DEBUG("dyninst_wait_1", "process exited with status: " << status->value.integer); } - else if (events.is_stopped(event) || events.is_breakpoint(event) || events.is_singlestep(event)) + else if (events.is_breakpoint(event) || events.is_singlestep(event)) { + EventBreakpoint::const_ptr breakpoint_ev = event->getEventBreakpoint(); + if (breakpoint_ev) + { + std::vector bps; + breakpoint_ev->getBreakpoints(bps); + std::vector::iterator it; + for (it = bps.begin(); it != bps.end(); it++) + { + Breakpoint::const_ptr bp = *it; + DEBUG("dyninst_wait_1", "breakpoint " << bp->getToAddress()); + } + } events.erase(event); status->kind = TARGET_WAITKIND_STOPPED; // EventStop doesn't have a signal member - status->value.integer = gdb_signal_from_host (SIGSTOP); - DEBUG("dyninst_wait_1", "process stopped with signal: " << status->value.integer); + status->value.integer = gdb_signal_from_host (SIGTRAP); + DEBUG("dyninst_wait_1", "process trapped: "); } else if (events.is_signal(event)) { status->kind = TARGET_WAITKIND_SIGNALLED; EventSignal::const_ptr signal_ev = event->getEventSignal(); + DEBUG("dyninst_wait_1", signal_ev->name()); status->value.integer = signal_ev->getSignal(); - DEBUG("dyninst_wait_1", "process terminated with code: " << status->value.integer); + DEBUG("dyninst_wait_1", "process signalled with signal: " << status->value.integer); + } + else if (events.is_threadcreate(event)) + { + dyninst_continue (new_ptid); + continue; // wait events loop + } + else if (events.is_threaddestroy(event)) + { + remove_thread (find_thread_ptid (new_ptid)); + dyninst_continue (new_ptid); + continue; // wait events loop } else { status->kind = TARGET_WAITKIND_STOPPED; status->value.integer = gdb_signal_from_host (0); - } - - /* SIGTRAP events are generated for situations other than single-step/ - breakpoint events (Eg. new-thread events). Handle those other types - of events, and resume the execution if necessary. */ - if (status->kind == TARGET_WAITKIND_STOPPED - && status->value.integer == GDB_SIGNAL_TRAP) - { - EventSignal::const_ptr signal_ev = event->getEventSignal(); -// int realsig = signal_ev->getSignal(); - - switch (signal_ev->getEventType().code()) - { - case EventType::ThreadCreate: - /* We just added the new thread above. No need to do anything - further. Just resume the execution again. */ - dyninst_continue (new_ptid); - dyninst_process->continueProc(); - Process::handleEvents(true); - continue; // wait events loop - - case EventType::ThreadDestroy: - remove_thread (find_thread_ptid (new_ptid)); - dyninst_continue (new_ptid); - dyninst_process->continueProc(); - Process::handleEvents(true); - continue; // wait events loop - } +// DEBUG("dyninst_wait_1", "process received: " << (event != events.NULL_Event ? event->name() : "")); + DEBUG("dyninst_wait_1", "process received: " << (event != NULL ? event->name() : "")); } break; - } + } DEBUG("dyninst_wait_1 returning", "", pid_to_string (ptid)); return new_ptid; @@ -655,10 +688,8 @@ dyninst_wait (ptid_t ptid, struct target_waitstatus *status, int options) /* Kill a PID */ static int -dyninst_kill (int pid) +dyninst_kill (Dyninst::PID pid) { - // ptid_t ptid = ptid_build (pid, 0, 0); - // struct target_waitstatus status; struct process_info *process; ProcessSet::iterator procset_it = dyninst_procset->find(pid); Process::ptr dyninst_process = *procset_it; @@ -677,7 +708,7 @@ dyninst_kill (int pid) /* Detach a PID */ static int -dyninst_detach (int pid) +dyninst_detach (Dyninst::PID pid) { struct process_info *process; ProcessSet::iterator procset_it = dyninst_procset->find(pid); @@ -698,16 +729,14 @@ dyninst_detach (int pid) static void dyninst_mourn (struct process_info *proc) { - /* Free our private data. */ DEBUG("dyninst_mourn", "proc=" << proc); - free (proc->piprivate); proc->piprivate = NULL; clear_inferiors (); } static void -dyninst_join (int pid) +dyninst_join (Dyninst::PID pid) { } @@ -834,7 +863,7 @@ dyninst_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) static void dyninst_request_interrupt (void) { - int pid = ptid_get_pid (thread_to_gdb_id (current_thread)); + Dyninst::PID pid = ptid_get_pid (thread_to_gdb_id (current_thread)); ProcessSet::iterator procset_it = dyninst_procset->find(pid); Process::ptr dyninst_process = *procset_it; @@ -871,7 +900,9 @@ dyninst_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, int len, DEBUG("dyninst_insert_point", " addr=" << addr, pid_to_string(th)); Breakpoint::ptr brp = Breakpoint::newBreakpoint(); + brp->setData(bp); bool result = dyninst_process->addBreakpoint(addr, brp); + dyninst_bpset.push_back(brp); return result == false; } @@ -879,17 +910,39 @@ dyninst_insert_point (enum raw_bkpt_type type, CORE_ADDR addr, int len, static int dyninst_remove_point (enum raw_bkpt_type type, CORE_ADDR addr, int len, - struct raw_breakpoint *bp) + struct raw_breakpoint *rbp) { Thread::const_ptr th = dyninst_get_inferior_thread(); DEBUG("dyninst_remove_point", " addr=" << addr, pid_to_string (th) ); Process::const_ptr dyninst_process = th->getProcess(); - Breakpoint::ptr brp = Breakpoint::newBreakpoint(); - bool result = dyninst_process->addBreakpoint(addr, brp); + std::vector::iterator it; + bool result; + for (it = dyninst_bpset.begin(); it != dyninst_bpset.end(); it++) + { + Breakpoint::ptr bp = *it; + if ((struct raw_breakpoint*)bp->getData() == rbp) + { + result = dyninst_process->rmBreakpoint(addr, bp); + break; + } + } + dyninst_bpset.erase(it); + return result == false; } + +static int +dyninst_supports_range_stepping (void) +{ + if (*the_low_target.supports_range_stepping == NULL) + return 0; + + return (*the_low_target.supports_range_stepping) (); +} + + /* The Dyninst target_ops vector. */ static struct target_ops dyninst_target_ops = { @@ -914,20 +967,20 @@ static struct target_ops dyninst_target_ops = { dyninst_supports_z_point_type, dyninst_insert_point, /* insert_point */ dyninst_remove_point, /* remove_point */ - NULL, /* stopped_by_watchpoint */ - NULL, /* stopped_data_address */ - NULL, /* read_offsets */ - NULL, /* get_tls_address */ - NULL, /* qxfer_spu */ - NULL, /* hostio_last_error */ - NULL, /* qxfer_osdata */ - NULL, /* qxfer_siginfo */ - NULL, /* supports_non_stop */ - NULL, /* async */ - NULL, /* start_non_stop */ - NULL, /* supports_multi_process */ - NULL, /* handle_monitor_command */ - NULL, /* common_core_of_thread */ + NULL, // stopped_by_watchpoint + NULL, // stopped_data_address + NULL, // read_offsets + NULL, // get_tls_address + NULL, // qxfer_spu + NULL, // hostio_last_error + NULL, // qxfer_osdata + NULL, // qxfer_siginfo + NULL, // supports_non_stop + NULL, // async + NULL, // start_non_stop + NULL, // supports_multi_process + NULL, // handle_monitor_command + NULL, // common_core_of_thread NULL, // read_loadmap NULL, // process_qsupported NULL, // supports_tracepoints @@ -949,7 +1002,7 @@ static struct target_ops dyninst_target_ops = { NULL, NULL, NULL, - NULL // supports_range_stepping + dyninst_supports_range_stepping }; void diff --git a/gdb/gdbserver/dyninst-low.h b/gdb/gdbserver/dyninst-low.h index f07beee..aab96f2 100644 --- a/gdb/gdbserver/dyninst-low.h +++ b/gdb/gdbserver/dyninst-low.h @@ -57,6 +57,7 @@ struct dyninst_target_ops void (*arch_setup) (void); CORE_ADDR (*get_pc) (struct regcache *regcache); hooks/post-receive -- Repository for Project Archer.