preventive waits -> busylooping.
[debugger.git] / debugger.c
index f880038..81a3bd4 100644 (file)
 #include <sys/wait.h>
 #include <limits.h>
 #include <string.h>
-#include <execinfo.h>
-#include <thread_db.h>
-#include <elfutils/libdwfl.h>
+#include <time.h>
 
 #include "debugger.h"
 
 
+#if 0
 #define USLEEP (1000000 / 2)
+#endif
+#define TIMEOUT_SECS 10
 
 
 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
@@ -60,6 +61,7 @@ enum state
   {
     /* Separate the valid `1 << enum state' and `enum state' ranges.  */
     STATE_FIRST = 4,
+    STATE_INSTABLE,
     STATE_ENOENT,
     STATE_SLEEPING,
     STATE_RUNNING,
@@ -73,6 +75,7 @@ static const char *state_to_name (enum state state)
 {
   switch (state)
     {
+      case STATE_INSTABLE: return "STATE_INSTABLE";
       case STATE_ENOENT:   return "STATE_ENOENT";
       case STATE_SLEEPING: return "STATE_SLEEPING";
       case STATE_RUNNING:  return "STATE_RUNNING";
@@ -85,9 +88,7 @@ static const char *state_to_name (enum state state)
   crash ();
 }
 
-#define STATE(pid, expect_mask) state ((pid), (expect_mask), #expect_mask )
-
-static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mask_string)
+static enum state state_get (pid_t pid)
 {
   char status_name[32];
   char line[LINE_MAX];
@@ -96,16 +97,6 @@ static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mas
 
   delay ();
 
-  /* Sanity check `1 << enum state' was not misplaced with `enum state'.  */
-  assert (1 << (STATE_FIRST + 1) >= STATE_LAST);
-  assert (expect_mask != 0);
-#define MASK_UNDER_EXCLUSIVE(bit) ((1 << (bit)) - 1)
-#define MASK_ABOVE_INCLUSIVE(bit) (~MASK_UNDER_EXCLUSIVE (bit))
-  assert ((expect_mask & MASK_UNDER_EXCLUSIVE (STATE_FIRST + 1)) == 0);
-  assert ((expect_mask & MASK_ABOVE_INCLUSIVE (STATE_LAST)) == 0);
-#undef MASK_ABOVE_INCLUSIVE
-#undef MASK_UNDER_EXCLUSIVE
-
   snprintf (status_name, sizeof (status_name), "/proc/%d/status", (int) pid);
   f = fopen (status_name, "r");
   if (f == NULL && errno == ENOENT)
@@ -116,7 +107,7 @@ static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mas
     {
       int i;
 
-      found = STATE_ENOENT;
+      found = STATE_INSTABLE;
       while (errno = 0, fgets (line, sizeof (line), f) != NULL)
        {
          const char *const string = "State:\t";
@@ -140,23 +131,50 @@ static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mas
              crash ();
            }
        }
-      assert (found != STATE_ENOENT);
+      if (errno == ESRCH)
+        return found;
+      assert (found != STATE_INSTABLE);
       i = fclose (f);
       assert (i == 0);
     }
-  if (((1 << found) & expect_mask) == 0)
+  return found;
+}
+
+#define STATE(pid, expect_mask) state ((pid), (expect_mask), #expect_mask )
+
+static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mask_string)
+{
+  enum state found;
+  time_t timeout = time (NULL) + TIMEOUT_SECS;
+
+  /* Sanity check `1 << enum state' was not misplaced with `enum state'.  */
+  assert (1 << (STATE_FIRST + 1) >= STATE_LAST);
+  assert (expect_mask != 0);
+#define MASK_UNDER_EXCLUSIVE(bit) ((1 << (bit)) - 1)
+#define MASK_ABOVE_INCLUSIVE(bit) (~MASK_UNDER_EXCLUSIVE (bit))
+  assert ((expect_mask & MASK_UNDER_EXCLUSIVE (STATE_FIRST + 1)) == 0);
+  assert ((expect_mask & MASK_ABOVE_INCLUSIVE (STATE_LAST)) == 0);
+#undef MASK_ABOVE_INCLUSIVE
+#undef MASK_UNDER_EXCLUSIVE
+
+  do
     {
-      fprintf (stderr, "Found for PID %d state %s but expecting (%s)\n",
-              (int) pid, state_to_name (found), expect_mask_string);
-      crash ();
+      found = state_get (pid);
+
+      if (((1 << found) & expect_mask) != 0)
+        return found;
     }
-  return found;
+  while (time (NULL) < timeout);
+
+  fprintf (stderr, "Found for PID %d state %s but expecting (%s)\n",
+          (int) pid, state_to_name (found), expect_mask_string);
+  crash ();
 }
 
 /* Debugging only: Number of signal needing redelivery on PTRACE_ATTACH.  */
 int attach_redelivered;
 
-static int attach_single (pid_t pid)
+int attach (pid_t pid)
 {
   int i;
   int status;
@@ -222,208 +240,6 @@ static int attach_single (pid_t pid)
   return stopped;
 }
 
-struct ps_prochandle_module
-  {
-    struct ps_prochandle_module *next;
-    Dwfl_Module *module;
-  };
-
-struct ps_prochandle
-  {
-    pid_t pid;
-    Dwfl *dwfl;
-    struct ps_prochandle_module *module_list;
-  };
-
-static int get_dwfl_find_debuginfo (Dwfl_Module *mod, void **userdata,
-                                   const char *modname, GElf_Addr base,
-                                   const char *file_name,
-                                   const char *debuglink_file,
-                                   GElf_Word debuglink_crc,
-                                   char **debuginfo_file_name)
-{
-  printf("modname=<%s>,file_name=<%s>\n",modname,file_name);
-  return dwfl_standard_find_debuginfo (mod, userdata, modname, base, file_name,
-                                      debuglink_file, debuglink_crc,
-                                      debuginfo_file_name);
-}
-
-static Dwfl *get_dwfl (struct ps_prochandle *proc_handle)
-{
-  static char *debuginfo_path;
-
-  static const Dwfl_Callbacks proc_callbacks =
-   {
-     .find_debuginfo = get_dwfl_find_debuginfo,
-     .debuginfo_path = &debuginfo_path,
-
-     .find_elf = dwfl_linux_proc_find_elf,
-   };
-
-  if (proc_handle->dwfl == NULL)
-    {
-      proc_handle->dwfl = dwfl_begin (&proc_callbacks);
-      assert (proc_handle->dwfl != NULL);
-
-      if (dwfl_linux_proc_report (proc_handle->dwfl, proc_handle->pid) != 0
-        || dwfl_report_end (proc_handle->dwfl, NULL, NULL) != 0)
-       {
-         dwfl_end (proc_handle->dwfl);
-         proc_handle->dwfl = NULL;
-         crash ();
-       }
-    }
-  return proc_handle->dwfl;
-}
-
-/* Functions in this interface return one of these status codes.  */
-typedef enum
-{
-  PS_OK,               /* Generic "call succeeded".  */
-  PS_ERR,              /* Generic error. */
-  PS_BADPID,           /* Bad process handle.  */
-  PS_BADLID,           /* Bad LWP identifier.  */ 
-  PS_BADADDR,          /* Bad address.  */
-  PS_NOSYM,            /* Could not find given symbol.  */
-  PS_NOFREGS           /* FPU register set not available for given LWP.  */
-} ps_err_e;
-
-ps_err_e ps_pdread (struct ps_prochandle *proc_handle, psaddr_t addr,
-                   void *buffer, size_t length)
-{
-  crash ();
-}
-
-ps_err_e ps_pdwrite (struct ps_prochandle *proc_handle, psaddr_t addr,
-                    const void *buffer, size_t length)
-{
-  crash ();
-}
-
-ps_err_e ps_lgetregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
-                     prgregset_t regs)
-{
-  crash ();
-}
-
-ps_err_e ps_lsetregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
-                     const prgregset_t regs)
-{
-  crash ();
-}
-
-ps_err_e ps_lgetfpregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
-                       prfpregset_t *fpregs)
-{
-  crash ();
-}
-
-ps_err_e ps_lsetfpregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
-                       const prfpregset_t *fpregs)
-{
-  crash ();
-}
-
-/* Return the PID of the process.  */
-pid_t ps_getpid (struct ps_prochandle *proc_handle)
-{
-  crash ();
-}
-
-/* Look up the named symbol in the named DSO in the symbol tables
-   associated with the process being debugged, filling in *SYM_ADDR
-   with the corresponding run-time address.  */
-ps_err_e ps_pglobal_lookup (struct ps_prochandle *proc_handle,
-                           const char *object_name, const char *sym_name,
-                           psaddr_t *sym_addr)
-{
-  Dwfl *dwfl = get_dwfl (proc_handle);
-  dwfl = dwfl;
-  dwfl_addrmodule (dwfl, 0x3571d00000);
-
-#if 0
-  Elf *elf = FIXME;
-  Elf_Scn *scn = NULL;
-  int sym_count, ndx;
-
-  sym_count = dwfl_module_getsymtab (Dwfl_Module *mod);
-  assert (sym_count >= 0);
-  for (ndx = 0; ndx < sym_count; ndx++)
-    {
-      GElf_Sym sym;
-      const char *name_got;
-
-      name_got = dwfl_module_getsym (Dwfl_Module *mod, ndx, &sym, NULL);
-      assert (name_got != NULL);
-      if (strcmp (name_got, sym_name) == 0)
-        break;
-    }
-  assert (ndx < sym_count);
-
-extern Elf *dwarf_getelf (Dwarf *dwarf);
-
-
-  while ((scn = elf_nextscn (elf, scn)) != NULL)
-    {
-      /* Handle the section if it is a symbol table.  */
-      GElf_Shdr shdr_mem;
-      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-
-      if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
-        handle_symtab (ebl, scn, shdr);
-    }
-
-
-  for (modulei = 0; modulei < dwfl->nmodules; modulei++)
-    {
-      Dwfl_Module *m = dwfl->modules[modulei];
-
-      puts (m->name);
-    }
-#if 0
-  if (strcmp (sym_name, "nptl_version") == 0)
-    {
-      extern const char nptl_version[];
-      *sym_addr = (psaddr_t) nptl_version;
-      return PS_OK;
-    }
-#endif
-#endif
-  crash ();
-}
-
-int attach (pid_t pid)
-{
-  int stopped;
-  td_err_e err;
-  td_thragent_t *thread_agent;
-  struct ps_prochandle proc_handle_local;
-  static int thread_db_init = 0;
-
-  stopped = attach_single (pid);
-
-  if (thread_db_init == 0)
-    {
-      err = td_init ();
-      assert (err == TD_OK);
-      thread_db_init = 1;
-    }
-
-  proc_handle_local.pid = pid;
-  proc_handle_local.dwfl = NULL;
-  err = td_ta_new (&proc_handle_local, &thread_agent);
-  if (proc_handle_local.dwfl != NULL)
-    dwfl_end (proc_handle_local.dwfl);
-  if (err == TD_NOLIBTHREAD)
-    {
-      delay ();
-      return stopped;
-    }
-  assert (err == TD_OK);
-
-  assert (0);
-}
-
 void detach (pid_t pid, int stopped)
 {
   int i;