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).