Home | History | Annotate | Download | only in src
      1 /* Unwinding of frames like gstack/pstack.
      2    Copyright (C) 2013-2014 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 #include <config.h>
     19 #include <assert.h>
     20 #include <argp.h>
     21 #include <error.h>
     22 #include <stdlib.h>
     23 #include <inttypes.h>
     24 #include <stdio.h>
     25 #include <stdio_ext.h>
     26 #include <string.h>
     27 #include <locale.h>
     28 #include <fcntl.h>
     29 #include ELFUTILS_HEADER(dwfl)
     30 
     31 #include <dwarf.h>
     32 #include <system.h>
     33 
     34 /* Name and version of program.  */
     35 static void print_version (FILE *stream, struct argp_state *state);
     36 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
     37 
     38 /* Bug report address.  */
     39 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
     40 
     41 /* non-printable argp options.  */
     42 #define OPT_DEBUGINFO	0x100
     43 #define OPT_COREFILE	0x101
     44 
     45 static bool show_activation = false;
     46 static bool show_module = false;
     47 static bool show_build_id = false;
     48 static bool show_source = false;
     49 static bool show_one_tid = false;
     50 static bool show_quiet = false;
     51 static bool show_raw = false;
     52 static bool show_modules = false;
     53 static bool show_debugname = false;
     54 static bool show_inlines = false;
     55 
     56 static int maxframes = 256;
     57 
     58 struct frame
     59 {
     60   Dwarf_Addr pc;
     61   bool isactivation;
     62 };
     63 
     64 struct frames
     65 {
     66   int frames;
     67   int allocated;
     68   struct frame *frame;
     69 };
     70 
     71 static Dwfl *dwfl = NULL;
     72 static pid_t pid = 0;
     73 static int core_fd = -1;
     74 static Elf *core = NULL;
     75 static const char *exec = NULL;
     76 static char *debuginfo_path = NULL;
     77 
     78 static const Dwfl_Callbacks proc_callbacks =
     79   {
     80     .find_elf = dwfl_linux_proc_find_elf,
     81     .find_debuginfo = dwfl_standard_find_debuginfo,
     82     .debuginfo_path = &debuginfo_path,
     83   };
     84 
     85 static const Dwfl_Callbacks core_callbacks =
     86   {
     87     .find_elf = dwfl_build_id_find_elf,
     88     .find_debuginfo = dwfl_standard_find_debuginfo,
     89     .debuginfo_path = &debuginfo_path,
     90   };
     91 
     92 #ifdef USE_DEMANGLE
     93 static size_t demangle_buffer_len = 0;
     94 static char *demangle_buffer = NULL;
     95 #endif
     96 
     97 /* Whether any frames have been shown at all.  Determines exit status.  */
     98 static bool frames_shown = false;
     99 
    100 /* Program exit codes. All frames shown without any errors is GOOD.
    101    Some frames shown with some non-fatal errors is an ERROR.  A fatal
    102    error or no frames shown at all is BAD.  A command line USAGE exit
    103    is generated by argp_error.  */
    104 #define EXIT_OK     0
    105 #define EXIT_ERROR  1
    106 #define EXIT_BAD    2
    107 #define EXIT_USAGE 64
    108 
    109 static int
    110 get_addr_width (Dwfl_Module *mod)
    111 {
    112   // Try to find the address wide if possible.
    113   static int width = 0;
    114   if (width == 0 && mod)
    115     {
    116       Dwarf_Addr bias;
    117       Elf *elf = dwfl_module_getelf (mod, &bias);
    118       if (elf)
    119         {
    120 	  GElf_Ehdr ehdr_mem;
    121 	  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
    122 	  if (ehdr)
    123 	    width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
    124 	}
    125     }
    126   if (width == 0)
    127     width = 16;
    128 
    129   return width;
    130 }
    131 
    132 static int
    133 module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)),
    134 		 const char *name, Dwarf_Addr start,
    135 		 void *arg __attribute__((unused)))
    136 {
    137   /* Forces resolving of main elf and debug files. */
    138   Dwarf_Addr bias;
    139   Elf *elf = dwfl_module_getelf (mod, &bias);
    140   Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias);
    141 
    142   Dwarf_Addr end;
    143   const char *mainfile;
    144   const char *debugfile;
    145   const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL,
    146                                           NULL, &mainfile, &debugfile);
    147   assert (strcmp (modname, name) == 0);
    148 
    149   int width = get_addr_width (mod);
    150   printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n",
    151 	  width, start, width, end, basename (name));
    152 
    153   const unsigned char *id;
    154   GElf_Addr id_vaddr;
    155   int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
    156   if (id_len > 0)
    157     {
    158       printf ("  [");
    159       do
    160 	printf ("%02" PRIx8, *id++);
    161       while (--id_len > 0);
    162       printf ("]\n");
    163     }
    164 
    165   if (elf != NULL)
    166     printf ("  %s\n", mainfile != NULL ? mainfile : "-");
    167   if (dwarf != NULL)
    168     printf ("  %s\n", debugfile != NULL ? debugfile : "-");
    169 
    170   return DWARF_CB_OK;
    171 }
    172 
    173 static int
    174 frame_callback (Dwfl_Frame *state, void *arg)
    175 {
    176   struct frames *frames = (struct frames *) arg;
    177   int nr = frames->frames;
    178   if (! dwfl_frame_pc (state, &frames->frame[nr].pc,
    179 		       &frames->frame[nr].isactivation))
    180     return -1;
    181 
    182   frames->frames++;
    183   if (frames->frames == maxframes)
    184     return DWARF_CB_ABORT;
    185 
    186   if (frames->frames == frames->allocated)
    187     {
    188       frames->allocated *= 2;
    189       frames->frame = realloc (frames->frame,
    190 			       sizeof (struct frame) * frames->allocated);
    191       if (frames->frame == NULL)
    192 	error (EXIT_BAD, errno, "realloc frames.frame");
    193     }
    194 
    195   return DWARF_CB_OK;
    196 }
    197 
    198 static const char*
    199 die_name (Dwarf_Die *die)
    200 {
    201   Dwarf_Attribute attr;
    202   const char *name;
    203   name = dwarf_formstring (dwarf_attr_integrate (die,
    204 						 DW_AT_MIPS_linkage_name,
    205 						 &attr)
    206 			   ?: dwarf_attr_integrate (die,
    207 						    DW_AT_linkage_name,
    208 						    &attr));
    209   if (name == NULL)
    210     name = dwarf_diename (die);
    211 
    212   return name;
    213 }
    214 
    215 static void
    216 print_frame (int nr, Dwarf_Addr pc, bool isactivation,
    217 	     Dwarf_Addr pc_adjusted, Dwfl_Module *mod,
    218 	     const char *symname, Dwarf_Die *cudie,
    219 	     Dwarf_Die *die)
    220 {
    221   int width = get_addr_width (mod);
    222   printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc);
    223 
    224   if (show_activation)
    225     printf ("%4s", ! isactivation ? "- 1" : "");
    226 
    227   if (symname != NULL)
    228     {
    229 #ifdef USE_DEMANGLE
    230       // Require GNU v3 ABI by the "_Z" prefix.
    231       if (! show_raw && symname[0] == '_' && symname[1] == 'Z')
    232 	{
    233 	  int status = -1;
    234 	  char *dsymname = __cxa_demangle (symname, demangle_buffer,
    235 					   &demangle_buffer_len, &status);
    236 	  if (status == 0)
    237 	    symname = demangle_buffer = dsymname;
    238 	}
    239 #endif
    240       printf (" %s", symname);
    241     }
    242 
    243   const char* fname;
    244   Dwarf_Addr start;
    245   fname = dwfl_module_info(mod, NULL, &start,
    246 			   NULL, NULL, NULL, NULL, NULL);
    247   if (show_module)
    248     {
    249       if (fname != NULL)
    250 	printf (" - %s", fname);
    251     }
    252 
    253   if (show_build_id)
    254     {
    255       const unsigned char *id;
    256       GElf_Addr id_vaddr;
    257       int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
    258       if (id_len > 0)
    259 	{
    260 	  printf ("\n    [");
    261 	  do
    262 	    printf ("%02" PRIx8, *id++);
    263 	  while (--id_len > 0);
    264 	  printf ("]@0x%0" PRIx64 "+0x%" PRIx64,
    265 		  start, pc_adjusted - start);
    266 	}
    267     }
    268 
    269   if (show_source)
    270     {
    271       int line, col;
    272       const char* sname;
    273       line = col = -1;
    274       sname = NULL;
    275       if (die != NULL)
    276 	{
    277 	  Dwarf_Files *files;
    278 	  if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
    279 	    {
    280 	      Dwarf_Attribute attr;
    281 	      Dwarf_Word val;
    282 	      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, &attr),
    283 				   &val) == 0)
    284 		{
    285 		  sname = dwarf_filesrc (files, val, NULL, NULL);
    286 		  if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
    287 						   &attr), &val) == 0)
    288 		    {
    289 		      line = val;
    290 		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
    291 						       &attr), &val) == 0)
    292 			col = val;
    293 		    }
    294 		}
    295 	    }
    296 	}
    297       else
    298 	{
    299 	  Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
    300 	  if (lineobj)
    301 	    sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL);
    302 	}
    303 
    304       if (sname != NULL)
    305 	{
    306 	  printf ("\n    %s", sname);
    307 	  if (line > 0)
    308 	    {
    309 	      printf (":%d", line);
    310 	      if (col > 0)
    311 		printf (":%d", col);
    312 	    }
    313 	}
    314     }
    315   printf ("\n");
    316 }
    317 
    318 static void
    319 print_inline_frames (int *nr, Dwarf_Addr pc, bool isactivation,
    320 		     Dwarf_Addr pc_adjusted, Dwfl_Module *mod,
    321 		     const char *symname, Dwarf_Die *cudie, Dwarf_Die *die)
    322 {
    323   Dwarf_Die *scopes = NULL;
    324   int nscopes = dwarf_getscopes_die (die, &scopes);
    325   if (nscopes > 0)
    326     {
    327       /* scopes[0] == die, the lowest level, for which we already have
    328 	 the name.  This is the actual source location where it
    329 	 happened.  */
    330       print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname,
    331 		   NULL, NULL);
    332 
    333       /* last_scope is the source location where the next frame/function
    334 	 call was done. */
    335       Dwarf_Die *last_scope = &scopes[0];
    336       for (int i = 1; i < nscopes && (maxframes == 0 || *nr < maxframes); i++)
    337 	{
    338 	  Dwarf_Die *scope = &scopes[i];
    339 	  int tag = dwarf_tag (scope);
    340 	  if (tag != DW_TAG_inlined_subroutine
    341 	      && tag != DW_TAG_entry_point
    342 	      && tag != DW_TAG_subprogram)
    343 	    continue;
    344 
    345 	  symname = die_name (scope);
    346 	  print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname,
    347 		       cudie, last_scope);
    348 
    349 	  /* Found the "top-level" in which everything was inlined?  */
    350 	  if (tag == DW_TAG_subprogram)
    351 	    break;
    352 
    353 	  last_scope = scope;
    354 	}
    355     }
    356   free (scopes);
    357 }
    358 
    359 static void
    360 print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what)
    361 {
    362   if (frames->frames > 0)
    363     frames_shown = true;
    364 
    365   printf ("TID %d:\n", tid);
    366   int frame_nr = 0;
    367   for (int nr = 0; nr < frames->frames && (maxframes == 0
    368 					   || frame_nr < maxframes); nr++)
    369     {
    370       Dwarf_Addr pc = frames->frame[nr].pc;
    371       bool isactivation = frames->frame[nr].isactivation;
    372       Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
    373 
    374       /* Get PC->SYMNAME.  */
    375       Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
    376       const char *symname = NULL;
    377       Dwarf_Die die_mem;
    378       Dwarf_Die *die = NULL;
    379       Dwarf_Die *cudie = NULL;
    380       if (mod && ! show_quiet)
    381 	{
    382 	  if (show_debugname)
    383 	    {
    384 	      Dwarf_Addr bias = 0;
    385 	      Dwarf_Die *scopes = NULL;
    386 	      cudie = dwfl_module_addrdie (mod, pc_adjusted, &bias);
    387 	      int nscopes = dwarf_getscopes (cudie, pc_adjusted - bias,
    388 					     &scopes);
    389 
    390 	      /* Find the first function-like DIE with a name in scope.  */
    391 	      for (int i = 0; symname == NULL && i < nscopes; i++)
    392 		{
    393 		  Dwarf_Die *scope = &scopes[i];
    394 		  int tag = dwarf_tag (scope);
    395 		  if (tag == DW_TAG_subprogram
    396 		      || tag == DW_TAG_inlined_subroutine
    397 		      || tag == DW_TAG_entry_point)
    398 		    symname = die_name (scope);
    399 
    400 		  if (symname != NULL)
    401 		    {
    402 		      die_mem = *scope;
    403 		      die = &die_mem;
    404 		    }
    405 		}
    406 	      free (scopes);
    407 	    }
    408 
    409 	  if (symname == NULL)
    410 	    symname = dwfl_module_addrname (mod, pc_adjusted);
    411 	}
    412 
    413       if (show_inlines && die != NULL)
    414 	print_inline_frames (&frame_nr, pc, isactivation, pc_adjusted, mod,
    415 			     symname, cudie, die);
    416       else
    417 	print_frame (frame_nr++, pc, isactivation, pc_adjusted, mod, symname,
    418 		     NULL, NULL);
    419     }
    420 
    421   if (frames->frames > 0 && frame_nr == maxframes)
    422     error (0, 0, "tid %d: shown max number of frames "
    423 	   "(%d, use -n 0 for unlimited)", tid, maxframes);
    424   else if (dwflerr != 0)
    425     {
    426       if (frames->frames > 0)
    427 	{
    428 	  unsigned nr = frames->frames - 1;
    429 	  Dwarf_Addr pc = frames->frame[nr].pc;
    430 	  bool isactivation = frames->frame[nr].isactivation;
    431 	  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
    432 	  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
    433 	  const char *mainfile = NULL;
    434 	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL,
    435 						  NULL, &mainfile, NULL);
    436 	  if (modname == NULL || modname[0] == '\0')
    437 	    {
    438 	      if (mainfile != NULL)
    439 		modname = mainfile;
    440 	      else
    441 		modname = "<unknown>";
    442 	    }
    443 	  error (0, 0, "%s tid %d at 0x%" PRIx64 " in %s: %s", what, tid,
    444 		 pc_adjusted, modname, dwfl_errmsg (dwflerr));
    445 	}
    446       else
    447 	error (0, 0, "%s tid %d: %s", what, tid, dwfl_errmsg (dwflerr));
    448     }
    449 }
    450 
    451 static int
    452 thread_callback (Dwfl_Thread *thread, void *thread_arg)
    453 {
    454   struct frames *frames = (struct frames *) thread_arg;
    455   pid_t tid = dwfl_thread_tid (thread);
    456   int err = 0;
    457   frames->frames = 0;
    458   switch (dwfl_thread_getframes (thread, frame_callback, thread_arg))
    459     {
    460     case DWARF_CB_OK:
    461     case DWARF_CB_ABORT:
    462       break;
    463     case -1:
    464       err = dwfl_errno ();
    465       break;
    466     default:
    467       abort ();
    468     }
    469   print_frames (frames, tid, err, "dwfl_thread_getframes");
    470   return DWARF_CB_OK;
    471 }
    472 
    473 static void
    474 print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
    475 {
    476   fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
    477 }
    478 
    479 static error_t
    480 parse_opt (int key, char *arg __attribute__ ((unused)),
    481 	   struct argp_state *state)
    482 {
    483   switch (key)
    484     {
    485     case 'p':
    486       pid = atoi (arg);
    487       if (pid == 0)
    488 	argp_error (state, N_("-p PID should be a positive process id."));
    489       break;
    490 
    491     case OPT_COREFILE:
    492       core_fd = open (arg, O_RDONLY);
    493       if (core_fd < 0)
    494 	error (EXIT_BAD, errno, N_("Cannot open core file '%s'"), arg);
    495       elf_version (EV_CURRENT);
    496       core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
    497       if (core == NULL)
    498 	error (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1));
    499       break;
    500 
    501     case 'e':
    502       exec = arg;
    503       break;
    504 
    505     case OPT_DEBUGINFO:
    506       debuginfo_path = arg;
    507       break;
    508 
    509     case 'm':
    510       show_module = true;
    511       break;
    512 
    513     case 's':
    514       show_source = true;
    515       break;
    516 
    517     case 'a':
    518       show_activation = true;
    519       break;
    520 
    521     case 'd':
    522       show_debugname = true;
    523       break;
    524 
    525     case 'i':
    526       show_inlines = show_debugname = true;
    527       break;
    528 
    529     case 'v':
    530       show_activation = show_source = show_module = show_debugname = true;
    531       show_inlines = true;
    532       break;
    533 
    534     case 'b':
    535       show_build_id = true;
    536       break;
    537 
    538     case 'q':
    539       show_quiet = true;
    540       break;
    541 
    542     case 'r':
    543       show_raw = true;
    544       break;
    545 
    546     case '1':
    547       show_one_tid = true;
    548       break;
    549 
    550     case 'n':
    551       maxframes = atoi (arg);
    552       if (maxframes < 0)
    553 	{
    554 	  argp_error (state, N_("-n MAXFRAMES should be 0 or higher."));
    555 	  return EINVAL;
    556 	}
    557       break;
    558 
    559     case 'l':
    560       show_modules = true;
    561       break;
    562 
    563     case ARGP_KEY_END:
    564       if (core == NULL && exec != NULL)
    565 	argp_error (state,
    566 		    N_("-e EXEC needs a core given by --core."));
    567 
    568       if (pid == 0 && show_one_tid == true)
    569 	argp_error (state,
    570 		    N_("-1 needs a thread id given by -p."));
    571 
    572       if ((pid == 0 && core == NULL) || (pid != 0 && core != NULL))
    573 	argp_error (state,
    574 		    N_("One of -p PID or --core COREFILE should be given."));
    575 
    576       if (pid != 0)
    577 	{
    578 	  dwfl = dwfl_begin (&proc_callbacks);
    579 	  if (dwfl == NULL)
    580 	    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
    581 
    582 	  int err = dwfl_linux_proc_report (dwfl, pid);
    583 	  if (err < 0)
    584 	    error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %d: %s", pid,
    585 		   dwfl_errmsg (-1));
    586 	  else if (err > 0)
    587 	    error (EXIT_BAD, err, "dwfl_linux_proc_report pid %d", pid);
    588 	}
    589 
    590       if (core != NULL)
    591 	{
    592 	  dwfl = dwfl_begin (&core_callbacks);
    593 	  if (dwfl == NULL)
    594 	    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
    595 	  if (dwfl_core_file_report (dwfl, core, exec) < 0)
    596 	    error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
    597 	}
    598 
    599       if (dwfl_report_end (dwfl, NULL, NULL) != 0)
    600 	error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
    601 
    602       if (pid != 0)
    603 	{
    604 	  int err = dwfl_linux_proc_attach (dwfl, pid, false);
    605 	  if (err < 0)
    606 	    error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
    607 		   dwfl_errmsg (-1));
    608 	  else if (err > 0)
    609 	    error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid);
    610 	}
    611 
    612       if (core != NULL)
    613 	{
    614 	  if (dwfl_core_file_attach (dwfl, core) < 0)
    615 	    error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
    616 	}
    617 
    618       /* Makes sure we are properly attached.  */
    619       if (dwfl_pid (dwfl) < 0)
    620 	error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1));
    621       break;
    622 
    623     default:
    624       return ARGP_ERR_UNKNOWN;
    625     }
    626   return 0;
    627 }
    628 
    629 int
    630 main (int argc, char **argv)
    631 {
    632   /* We use no threads here which can interfere with handling a stream.  */
    633   __fsetlocking (stdin, FSETLOCKING_BYCALLER);
    634   __fsetlocking (stdout, FSETLOCKING_BYCALLER);
    635   __fsetlocking (stderr, FSETLOCKING_BYCALLER);
    636 
    637   /* Set locale.  */
    638   (void) setlocale (LC_ALL, "");
    639 
    640   const struct argp_option options[] =
    641     {
    642       { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
    643       { "pid", 'p', "PID", 0,
    644 	N_("Show stack of process PID"), 0 },
    645       { "core", OPT_COREFILE, "COREFILE", 0,
    646 	N_("Show stack found in COREFILE"), 0 },
    647       {  "executable", 'e', "EXEC", 0, N_("(optional) EXECUTABLE that produced COREFILE"), 0 },
    648       { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
    649 	N_("Search path for separate debuginfo files"), 0 },
    650 
    651       { NULL, 0, NULL, 0, N_("Output selection options:"), 0 },
    652       { "activation",  'a', NULL, 0,
    653 	N_("Additionally show frame activation"), 0 },
    654       { "debugname",  'd', NULL, 0,
    655 	N_("Additionally try to lookup DWARF debuginfo name for frame address"),
    656 	0 },
    657       { "inlines",  'i', NULL, 0,
    658 	N_("Additionally show inlined function frames using DWARF debuginfo if available (implies -d)"), 0 },
    659       { "module",  'm', NULL, 0,
    660 	N_("Additionally show module file information"), 0 },
    661       { "source",  's', NULL, 0,
    662 	N_("Additionally show source file information"), 0 },
    663       { "verbose", 'v', NULL, 0,
    664 	N_("Show all additional information (activation, debugname, inlines, module and source)"), 0 },
    665       { "quiet", 'q', NULL, 0,
    666 	N_("Do not resolve address to function symbol name"), 0 },
    667       { "raw", 'r', NULL, 0,
    668 	N_("Show raw function symbol names, do not try to demangle names"), 0 },
    669       { "build-id",  'b', NULL, 0,
    670 	N_("Show module build-id, load address and pc offset"), 0 },
    671       { NULL, '1', NULL, 0,
    672 	N_("Show the backtrace of only one thread"), 0 },
    673       { NULL, 'n', "MAXFRAMES", 0,
    674 	N_("Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"), 0 },
    675       { "list-modules", 'l', NULL, 0,
    676 	N_("Show module memory map with build-id, elf and debug files detected"), 0 },
    677       { NULL, 0, NULL, 0, NULL, 0 }
    678     };
    679 
    680   const struct argp argp =
    681     {
    682       .options = options,
    683       .parser = parse_opt,
    684       .doc = N_("Print a stack for each thread in a process or core file.\v\
    685 Program exits with return code 0 if all frames were shown without \
    686 any errors.  If some frames were shown, but there were some non-fatal \
    687 errors, possibly causing an incomplete backtrace, the program exits \
    688 with return code 1.  If no frames could be shown, or a fatal error \
    689 occured the program exits with return code 2.  If the program was \
    690 invoked with bad or missing arguments it will exit with return code 64.")
    691     };
    692 
    693   argp_parse (&argp, argc, argv, 0, NULL, NULL);
    694 
    695   if (show_modules)
    696     {
    697       printf ("PID %d - %s module memory map\n", dwfl_pid (dwfl),
    698 	      pid != 0 ? "process" : "core");
    699       if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0)
    700 	error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
    701     }
    702 
    703   struct frames frames;
    704   /* When maxframes is zero, then 2048 is just the initial allocation
    705      that will be increased using realloc in framecallback ().  */
    706   frames.allocated = maxframes == 0 ? 2048 : maxframes;
    707   frames.frames = 0;
    708   frames.frame = malloc (sizeof (struct frame) * frames.allocated);
    709   if (frames.frame == NULL)
    710     error (EXIT_BAD, errno, "malloc frames.frame");
    711 
    712   if (show_one_tid)
    713     {
    714       int err = 0;
    715       switch (dwfl_getthread_frames (dwfl, pid, frame_callback, &frames))
    716 	{
    717 	case DWARF_CB_OK:
    718 	case DWARF_CB_ABORT:
    719 	  break;
    720 	case -1:
    721 	  err = dwfl_errno ();
    722 	  break;
    723 	default:
    724 	  abort ();
    725 	}
    726       print_frames (&frames, pid, err, "dwfl_getthread_frames");
    727     }
    728   else
    729     {
    730       printf ("PID %d - %s\n", dwfl_pid (dwfl), pid != 0 ? "process" : "core");
    731       switch (dwfl_getthreads (dwfl, thread_callback, &frames))
    732 	{
    733 	case DWARF_CB_OK:
    734 	case DWARF_CB_ABORT:
    735 	  break;
    736 	case -1:
    737 	  error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
    738 	  break;
    739 	default:
    740 	  abort ();
    741 	}
    742     }
    743   free (frames.frame);
    744   dwfl_end (dwfl);
    745 
    746   if (core != NULL)
    747     elf_end (core);
    748 
    749   if (core_fd != -1)
    750     close (core_fd);
    751 
    752 #ifdef USE_DEMANGLE
    753   free (demangle_buffer);
    754 #endif
    755 
    756   if (! frames_shown)
    757     error (EXIT_BAD, 0, N_("Couldn't show any frames."));
    758 
    759   return error_message_count != 0 ? EXIT_ERROR : EXIT_OK;
    760 }
    761