public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] scox/dyninst: Support for using upstream gdb as a client.
@ 2015-07-10 22:09 scox
0 siblings, 0 replies; only message in thread
From: scox @ 2015-07-10 22:09 UTC (permalink / raw)
To: archer-commits
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 <scox@redhat.com>
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<Breakpoint::ptr> BreakpointSet;
BreakpointSet dyninst_bpset;
-ProcessSet::ptr dyninst_procset;
-typedef std::vector<Library::ptr> 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<std::pair<ptid_t, Event::const_ptr> > 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<std::pair<ptid_t,Event::const_ptr> >::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<std::pair<ptid_t,Event::const_ptr> >::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.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2015-07-10 22:09 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-10 22:09 [SCM] scox/dyninst: Support for using upstream gdb as a client scox
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).