Implemented nptl_db testing.
[debugger.git] / debugger.c
1 /* Copyright 2007, Red Hat Inc.  */
2
3 #define _GNU_SOURCE 1
4 #define ps_prochandle attach_state_struct
5
6 #include <unistd.h>
7 #include <assert.h>
8 #include <stdlib.h>
9 #include <signal.h>
10 #include <errno.h>
11 #include <stdio.h>
12 #include <sys/ptrace.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <limits.h>
16 #include <string.h>
17 #include <time.h>
18 #include <sys/reg.h>
19 #include <linux/ptrace.h>
20 #include <asm/prctl.h>
21 #include <elfutils/libdwfl.h>
22 #include <thread_db.h>
23 #include <fcntl.h>
24
25 #include "debugger.h"
26
27
28 #if 0
29 #define USLEEP (1000000 / 2)
30 #endif
31 #define TIMEOUT_SECS 20
32 /* LOOPS_MIN is a safety as QEMU clock time sucks.
33    100000 is 4s natively and 53s in QEMU.  */
34 #define LOOPS_MIN 500000
35
36
37 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
38
39 void delay (void)
40 {
41 #ifdef USLEEP
42   int i;
43
44   i = usleep (USLEEP);
45   assert (i == 0);
46 #endif
47 }
48
49 static __attribute__((__noreturn__)) void crash (void)
50 {
51 #if 0
52   void *array[0x100];
53   int count;
54 #endif
55   char command[256];
56
57   fputs (">>> CRASH START\n", stderr);
58 #if 0
59   count = backtrace (array, ARRAY_SIZE (array));
60   backtrace_symbols_fd (array, count, STDERR_FILENO);
61 #endif
62   snprintf (command, sizeof (command), "echo -e \"bt\\nquit\""
63             " >/tmp/debugger.%d; gdb --batch -nx --command=/tmp/debugger.%d"
64             " /proc/%d/exe %d </dev/null;rm -f /tmp/debugger.%d",
65             (int) getpid(), (int) getpid(), (int) getpid(), (int) getpid(),
66             (int) getpid());
67   system (command);
68   fputs (">>> CRASH FINISH\n", stderr);
69   abort ();
70 }
71
72 enum state
73   {
74     /* Separate the valid `1 << enum state' and `enum state' ranges.  */
75     STATE_FIRST = 4,
76     STATE_INSTABLE,
77     STATE_ENOENT,
78     STATE_SLEEPING,
79     STATE_RUNNING,
80     STATE_STOPPED,
81     STATE_PTRACED,
82     STATE_ZOMBIE,
83     STATE_DEAD,
84     STATE_LAST
85   };
86
87 static const char *state_to_name (enum state state)
88 {
89   switch (state)
90     {
91       case STATE_INSTABLE: return "STATE_INSTABLE";
92       case STATE_ENOENT:   return "STATE_ENOENT";
93       case STATE_SLEEPING: return "STATE_SLEEPING";
94       case STATE_RUNNING:  return "STATE_RUNNING";
95       case STATE_STOPPED:  return "STATE_STOPPED";
96       case STATE_PTRACED:  return "STATE_PTRACED";
97       case STATE_ZOMBIE:   return "STATE_ZOMBIE";
98       case STATE_DEAD:     return "STATE_DEAD";
99       default: crash ();
100     }
101   /* NOTREACHED */
102   crash ();
103 }
104
105 static enum state state_get (pid_t pid)
106 {
107   char status_name[32];
108   char line[LINE_MAX];
109   FILE *f;
110   enum state found;
111
112   delay ();
113
114   snprintf (status_name, sizeof (status_name), "/proc/%d/status", (int) pid);
115   f = fopen (status_name, "r");
116   if (f == NULL && errno == ENOENT)
117     found = STATE_ENOENT;
118   else if (f == NULL)
119     {
120       fprintf (stderr, "errno = %d\n", errno);
121       crash ();
122     }
123   else
124     {
125       int i;
126
127       found = STATE_INSTABLE;
128       while (errno = 0, fgets (line, sizeof (line), f) != NULL)
129         {
130           const char *const string = "State:\t";
131           const size_t length = sizeof "State:\t" - 1;
132
133           if (strncmp (line, string, length) != 0)
134             continue;
135           if (strcmp (line + length, "S (sleeping)\n") == 0)
136             found = STATE_SLEEPING;
137           else if (strcmp (line + length, "R (running)\n") == 0)
138             found = STATE_RUNNING;
139           else if (strcmp (line + length, "T (stopped)\n") == 0)
140             found = STATE_STOPPED;
141           else if (strcmp (line + length, "T (tracing stop)\n") == 0)
142             found = STATE_PTRACED;
143           else if (strcmp (line + length, "Z (zombie)\n") == 0)
144             found = STATE_ZOMBIE;
145           /* FIXME: What does it mean?  */
146           else if (strcmp (line + length, "X (dead)\n") == 0)
147             found = STATE_DEAD;
148           else
149             {
150               fprintf (stderr, "Found an unknown state: %s", line + length);
151               crash ();
152             }
153         }
154       assert (found != STATE_INSTABLE || errno == ESRCH);
155       i = fclose (f);
156       assert (i == 0);
157     }
158   return found;
159 }
160
161 #define STATE(pid, expect_mask) state ((pid), (expect_mask), #expect_mask )
162
163 static enum state state (pid_t pid, unsigned expect_mask, const char *expect_mask_string)
164 {
165   enum state found;
166   time_t timeout = time (NULL) + TIMEOUT_SECS;
167   unsigned loops = 0;
168
169   /* Sanity check `1 << enum state' was not misplaced with `enum state'.  */
170   assert (1 << (STATE_FIRST + 1) >= STATE_LAST);
171   assert (expect_mask != 0);
172 #define MASK_UNDER_EXCLUSIVE(bit) ((1 << (bit)) - 1)
173 #define MASK_ABOVE_INCLUSIVE(bit) (~MASK_UNDER_EXCLUSIVE (bit))
174   assert ((expect_mask & MASK_UNDER_EXCLUSIVE (STATE_FIRST + 1)) == 0);
175   assert ((expect_mask & MASK_ABOVE_INCLUSIVE (STATE_LAST)) == 0);
176 #undef MASK_ABOVE_INCLUSIVE
177 #undef MASK_UNDER_EXCLUSIVE
178
179   do
180     {
181       found = state_get (pid);
182
183       if (((1 << found) & expect_mask) != 0)
184         return found;
185     }
186   while (loops++ < LOOPS_MIN || time (NULL) < timeout);
187
188   fprintf (stderr, "Found for PID %d state %s but expecting (%s)\n",
189            (int) pid, state_to_name (found), expect_mask_string);
190   crash ();
191 }
192
193 struct attach_state_struct
194   {
195     pid_t pid;
196     Dwfl *dwfl;
197     int stopped;
198     td_thragent_t *thread_agent;
199     /* Debugging only: Number of signal needing redelivery on PTRACE_ATTACH.  */
200     int redelivered;
201     int threads_count;
202   };
203
204 int attach_state_redelivered_get (struct attach_state_struct *attach_state)
205 {
206   assert (attach_state != NULL);
207
208   return attach_state->redelivered;
209 }
210
211 int attach_state_threads_count_get (struct attach_state_struct *attach_state)
212 {
213   assert (attach_state != NULL);
214
215   return attach_state->threads_count;
216 }
217
218 int attach_state_stopped_get (struct attach_state_struct *attach_state)
219 {
220   assert (attach_state != NULL);
221
222   return attach_state->stopped;
223 }
224
225 pid_t attach_state_pid_get (struct attach_state_struct *attach_state)
226 {
227   assert (attach_state != NULL);
228
229   return attach_state->pid;
230 }
231
232 struct attach_state_struct *attach_single (pid_t pid)
233 {
234   int i;
235   int status;
236   struct attach_state_struct *attach_state;
237
238   attach_state = malloc (sizeof (*attach_state));
239   assert (attach_state != NULL);
240   attach_state->pid = pid;
241   attach_state->dwfl = NULL;
242   attach_state->redelivered = 0;
243   attach_state->threads_count = -1;
244
245   delay ();
246
247   attach_state->stopped = (STATE (pid, (1 << STATE_SLEEPING)
248                                        | (1 << STATE_RUNNING)
249                                        | (1 << STATE_STOPPED))
250                            == STATE_STOPPED);
251
252   i = ptrace (PTRACE_ATTACH, pid, NULL, NULL);
253   assert (i == 0);
254
255   /* FIXME: Why it does not work?
256      Disable also the STATE () call above.  */
257 #if 0
258   delay();
259
260   i = ptrace (PTRACE_CONT, pid, (void *) 1, (void *) SIGSTOP);
261   /* `STOPPED == 1' may be false, even if the process was not stopped.  */
262   if (i == 0)
263     attach_state->stopped = 1;
264   else if (errno == ESRCH)
265     attach_state->stopped = 0;
266   else
267     crash ();
268 #endif
269
270   for (;;)
271     {
272       delay ();
273
274       i = waitpid (pid, &status, 0);
275       assert (i == pid);
276       if (!WIFSTOPPED (status))
277         {
278           /* Process may have exited.  */
279           fprintf (stderr, "PID %d waitpid(2) status %d\n", (int) pid,
280                    status);
281           exit (EXIT_FAILURE);
282         }
283       if (WSTOPSIG (status) == SIGSTOP)
284         break;
285
286       if (attach_state->redelivered == 0)
287         attach_state->redelivered = WSTOPSIG (status);
288       else
289         attach_state->redelivered = -1;
290
291       delay ();
292
293       /* Re-deliver the signal received before SIGSTOP.
294          It happens with about only 1:200000 probability.  */
295       i = ptrace (PTRACE_CONT, pid, (void *) 1,
296                   (void *) (unsigned long) WSTOPSIG (status));
297       assert (i == 0);
298     }
299
300   return attach_state;
301 }
302
303 void detach_single (struct attach_state_struct *attach_state)
304 {
305   int i;
306
307   delay ();
308
309   i = ptrace (PTRACE_DETACH, attach_state->pid, NULL,
310               (void *) (unsigned long) (attach_state->stopped ? SIGSTOP : 0));
311   assert (i == 0);
312
313   delay ();
314 }
315
316 static Dwfl *get_dwfl (struct ps_prochandle *proc_handle)
317 {
318   static char *debuginfo_path;
319
320   static const Dwfl_Callbacks proc_callbacks =
321    {
322      .find_debuginfo = dwfl_standard_find_debuginfo,
323      .debuginfo_path = &debuginfo_path,
324
325      .find_elf = dwfl_linux_proc_find_elf,
326    };
327
328   if (proc_handle->dwfl == NULL)
329     {
330       proc_handle->dwfl = dwfl_begin (&proc_callbacks);
331       assert (proc_handle->dwfl != NULL);
332
333       errno = 0;
334       if (dwfl_linux_proc_report (proc_handle->dwfl, proc_handle->pid) != 0
335          || dwfl_report_end (proc_handle->dwfl, NULL, NULL) != 0)
336         {
337           fprintf (stderr, "dwfl reporting: %m\n");
338           dwfl_end (proc_handle->dwfl);
339           proc_handle->dwfl = NULL;
340           abort ();
341         }
342     }
343   return proc_handle->dwfl;
344 }
345
346 /* Functions in this interface return one of these status codes.  */
347 typedef enum
348 {
349   PS_OK,                /* Generic "call succeeded".  */
350   PS_ERR,               /* Generic error. */
351   PS_BADPID,            /* Bad process handle.  */
352   PS_BADLID,            /* Bad LWP identifier.  */ 
353   PS_BADADDR,           /* Bad address.  */
354   PS_NOSYM,             /* Could not find given symbol.  */
355   PS_NOFREGS            /* FPU register set not available for given LWP.  */
356 } ps_err_e;
357
358 ps_err_e ps_pdread (struct ps_prochandle *proc_handle, psaddr_t addr,
359                     void *buffer, size_t length)
360 {
361   pid_t pid = proc_handle->pid;
362   char filename[64];
363   int fd;
364
365   if (pid == getpid ())
366     {
367       memcpy (buffer, addr, length);
368       return PS_OK;
369     }
370
371 /* Already under PTRACE_ATTACH.  */
372 #if 0
373   if (ptrace (PTRACE_ATTACH, pid, NULL, NULL) != 0)
374     abort ();
375   if (waitpid (pid, NULL, 0) != pid)
376     abort ();
377 #endif
378
379   snprintf (filename, sizeof (filename), "/proc/%ld/mem", (long) pid);
380   fd = open (filename, O_RDONLY);
381   assert (fd != -1);
382   if (lseek64 (fd, (off64_t) addr, SEEK_SET) != (off64_t) addr)
383     abort ();
384   if (read (fd, buffer, length) != length)
385     {
386       /* It occurs for singlethreaded processes.  */
387       if ((off64_t) addr == 0)
388         return PS_ERR;
389       fprintf (stderr, "read() error @0x%lx length %lu: %m\n",
390                (unsigned long) addr, (unsigned long) length);
391       abort ();
392     }
393   if (close (fd) != 0)
394     abort ();
395
396 /* Already under PTRACE_ATTACH.  */
397 #if 0
398   if (ptrace (PTRACE_DETACH, pid, NULL, NULL) != 0)
399     abort ();
400 #endif
401
402   return PS_OK;
403 }
404
405 ps_err_e ps_pdwrite (struct ps_prochandle *proc_handle, psaddr_t addr,
406                      const void *buffer, size_t length)
407 {
408   crash ();
409 }
410
411 ps_err_e ps_lgetregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
412                       prgregset_t regs)
413 {
414   crash ();
415 }
416
417 ps_err_e ps_lsetregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
418                       const prgregset_t regs)
419 {
420   crash ();
421 }
422
423 ps_err_e ps_lgetfpregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
424                         prfpregset_t *fpregs)
425 {
426   crash ();
427 }
428
429 ps_err_e ps_lsetfpregs (struct ps_prochandle *proc_handle, lwpid_t lwp,
430                         const prfpregset_t *fpregs)
431 {
432   crash ();
433 }
434
435 /* Return the PID of the process.  */
436 pid_t ps_getpid (struct ps_prochandle *proc_handle)
437 {
438   return proc_handle->pid;
439 }
440
441 struct getmodules_callback_arg
442   {
443     const char *sym_name;
444     psaddr_t *sym_addr;
445     ps_err_e retval;
446   };
447
448 static int getmodules_callback (Dwfl_Module *module,
449                                 void **module_userdata_pointer,
450                                 const char *module_name,
451                                 Dwarf_Addr module_low_addr, void *arg)
452 {
453   struct getmodules_callback_arg *getmodules_callback_arg = arg;
454   int sym_count, ndx;
455   GElf_Sym sym;
456
457   sym_count = dwfl_module_getsymtab (module);
458 /* "/usr/lib/debug/lib64/ld-2.4.so.debug"?  */
459 #if 0
460   assert (sym_count >= 0);
461 #endif
462   for (ndx = 0; ndx < sym_count; ndx++)
463     {
464       const char *name_got;
465
466       name_got = dwfl_module_getsym (module, ndx, &sym,
467                                      NULL);
468       assert (name_got != NULL);
469       if (strcmp (name_got, getmodules_callback_arg->sym_name) == 0)
470         break;
471     }
472   if (ndx == sym_count)
473     return DWARF_CB_OK;
474
475   *getmodules_callback_arg->sym_addr = (psaddr_t) sym.st_value;
476   getmodules_callback_arg->retval = PS_OK;
477
478   return DWARF_CB_OK;
479 }
480
481 /* Look up the named symbol in the named DSO in the symbol tables
482    associated with the process being debugged, filling in *SYM_ADDR
483    with the corresponding run-time address.  */
484 ps_err_e ps_pglobal_lookup (struct ps_prochandle *proc_handle,
485                             const char *object_name, const char *sym_name,
486                             psaddr_t *sym_addr)
487 {
488   Dwfl *dwfl = get_dwfl (proc_handle);
489   struct getmodules_callback_arg getmodules_callback_arg;
490   ptrdiff_t err_ptrdiff;
491
492   /* FIXME: `object_name' ignored due to missing unresolving of shared
493      libraries symbolic links.  */
494   getmodules_callback_arg.sym_name = sym_name;
495   getmodules_callback_arg.sym_addr = sym_addr;
496   getmodules_callback_arg.retval = PS_NOSYM;
497   err_ptrdiff = dwfl_getmodules (dwfl, getmodules_callback,
498                                  &getmodules_callback_arg, 0);
499   assert (err_ptrdiff == 0);
500   return getmodules_callback_arg.retval;
501 }
502
503 #ifdef __x86_64__
504 ps_err_e ps_get_thread_area (const struct ps_prochandle *ph, lwpid_t lwpid,
505                              int idx, void **base)
506 {
507   long val;
508
509   assert (idx == FS || idx == GS);
510
511   if (ptrace (PTRACE_ATTACH, lwpid, NULL, NULL) != 0)
512     abort ();
513   if (waitpid (lwpid, NULL, 0) != lwpid)
514     abort ();
515
516   val = ptrace (PTRACE_ARCH_PRCTL, lwpid, base, (idx == FS ? ARCH_GET_FS
517                                                            : ARCH_GET_GS));
518
519   if (ptrace (PTRACE_DETACH, lwpid, NULL, NULL) != 0)
520     abort ();
521
522   if (val != 0)
523     {
524       fprintf (stderr, "PTRACE_ARCH_PRCTL (%s): %m\n", (idx == FS ? "FS"
525                                                                   : "GS"));
526       return PS_ERR;
527     }
528
529   return PS_OK;
530 }
531 #else
532 #error "Unsupported ps_get_thread_area ()!"
533 #endif
534
535 static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
536 {
537   td_err_e err;
538   td_thrinfo_t info;
539   struct attach_state_struct *attach_state = data;
540
541   err = td_thr_get_info (th_p, &info);
542   assert (err == TD_OK);
543   /* printf ("LWP = %ld TID = 0x%lx\n", (long) info.ti_lid, info.ti_tid);  */
544
545   attach_state->threads_count++;
546
547   return 0;
548 }
549
550 static void attach_multi (struct attach_state_struct *attach_state)
551 {
552   td_err_e err;
553
554   err = td_init ();
555   assert (err == TD_OK);
556
557   err = td_ta_new (attach_state, &attach_state->thread_agent);
558   assert (err == TD_OK || err == TD_NOLIBTHREAD);
559   attach_state->threads_count = 0;
560   if (err == TD_NOLIBTHREAD)
561     {
562       attach_state->thread_agent = NULL;
563       return;
564     }
565   assert (attach_state->thread_agent != NULL);
566   /* Multithreading test:  */
567   err = td_ta_thr_iter (attach_state->thread_agent, find_new_threads_callback,
568                         attach_state, TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
569                         TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
570   if (err != TD_OK)
571     {
572       fprintf (stderr, "err = %d\n", err);
573       abort ();
574     }
575   assert (attach_state->threads_count > 0);
576 }
577
578 struct attach_state_struct *attach (pid_t pid)
579 {
580   struct attach_state_struct *attach_state;
581
582   attach_state = attach_single (pid);
583   attach_multi (attach_state);
584
585   return attach_state;
586 }
587
588 void detach (struct attach_state_struct *attach_state)
589 {
590   if (attach_state->thread_agent != NULL)
591     {
592       td_err_e err;
593
594       err = td_ta_delete (attach_state->thread_agent);
595       assert (err == TD_OK);
596     }
597   if (attach_state->dwfl != NULL);
598     dwfl_end (attach_state->dwfl);
599
600   detach_single (attach_state);
601 }
602
603 #ifndef LIBRARY
604
605 int main (int argc, char **argv)
606 {
607   pid_t pid;
608   struct attach_state_struct *attach_state;
609
610   if (argc != 2)
611     {
612       fprintf (stderr, "Usage: %s <PID>\n", argv[0]);
613       exit (EXIT_FAILURE);
614     }
615
616   pid = atoi (argv[1]);
617
618   attach_state = attach (pid);
619   detach (attach_state);
620
621   return EXIT_SUCCESS;
622 }
623
624 #endif /* !LIBRARY */