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