#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]))
{
/* Separate the valid `1 << enum state' and `enum state' ranges. */
STATE_FIRST = 4,
+ STATE_INSTABLE,
STATE_ENOENT,
STATE_SLEEPING,
STATE_RUNNING,
{
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";
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];
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)
{
int i;
- found = STATE_ENOENT;
+ found = STATE_INSTABLE;
while (errno = 0, fgets (line, sizeof (line), f) != NULL)
{
const char *const string = "State:\t";
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;
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;