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