103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Unwinding of frames like gstack/pstack. 203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Copyright (C) 2013-2014 Red Hat, Inc. 303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is part of elfutils. 403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes This file is free software; you can redistribute it and/or modify 603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes it under the terms of the GNU General Public License as published by 703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the Free Software Foundation; either version 3 of the License, or 803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (at your option) any later version. 903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elfutils is distributed in the hope that it will be useful, but 1103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes WITHOUT ANY WARRANTY; without even the implied warranty of 1203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GNU General Public License for more details. 1403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes You should have received a copy of the GNU General Public License 1603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 1803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <config.h> 1903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <assert.h> 2003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <argp.h> 2103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <error.h> 2203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdlib.h> 2303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <inttypes.h> 2403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdio.h> 2503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <stdio_ext.h> 2603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <string.h> 2703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <locale.h> 2803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <fcntl.h> 2903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include ELFUTILS_HEADER(dwfl) 3003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <dwarf.h> 3203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#include <system.h> 3303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Name and version of program. */ 3503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void print_version (FILE *stream, struct argp_state *state); 3603333823c75a1c1887e923828113a1b0fd12020cElliott HughesARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 3703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 3803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Bug report address. */ 3903333823c75a1c1887e923828113a1b0fd12020cElliott HughesARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 4003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* non-printable argp options. */ 4203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define OPT_DEBUGINFO 0x100 4303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define OPT_COREFILE 0x101 4403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 4503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_activation = false; 4603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_module = false; 4703333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_build_id = false; 4803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_source = false; 4903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_one_tid = false; 5003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_quiet = false; 5103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_raw = false; 5203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_modules = false; 5303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_debugname = false; 5403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool show_inlines = false; 5503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int maxframes = 256; 5703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 5803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstruct frame 5903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 6003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc; 6103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool isactivation; 6203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}; 6303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 6403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstruct frames 6503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 6603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int frames; 6703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int allocated; 6803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct frame *frame; 6903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes}; 7003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic Dwfl *dwfl = NULL; 7203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic pid_t pid = 0; 7303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int core_fd = -1; 7403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic Elf *core = NULL; 7503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char *exec = NULL; 7603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic char *debuginfo_path = NULL; 7703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 7803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwfl_Callbacks proc_callbacks = 7903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 8003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .find_elf = dwfl_linux_proc_find_elf, 8103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .find_debuginfo = dwfl_standard_find_debuginfo, 8203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .debuginfo_path = &debuginfo_path, 8303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 8403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 8503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const Dwfl_Callbacks core_callbacks = 8603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 8703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .find_elf = dwfl_build_id_find_elf, 8803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .find_debuginfo = dwfl_standard_find_debuginfo, 8903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .debuginfo_path = &debuginfo_path, 9003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 9103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 9203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef USE_DEMANGLE 9303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic size_t demangle_buffer_len = 0; 9403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic char *demangle_buffer = NULL; 9503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 9603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 9703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Whether any frames have been shown at all. Determines exit status. */ 9803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic bool frames_shown = false; 9903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes/* Program exit codes. All frames shown without any errors is GOOD. 10103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Some frames shown with some non-fatal errors is an ERROR. A fatal 10203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error or no frames shown at all is BAD. A command line USAGE exit 10303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes is generated by argp_error. */ 10403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define EXIT_OK 0 10503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define EXIT_ERROR 1 10603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define EXIT_BAD 2 10703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#define EXIT_USAGE 64 10803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 10903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 11003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesget_addr_width (Dwfl_Module *mod) 11103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 11203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // Try to find the address wide if possible. 11303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes static int width = 0; 11403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (width == 0 && mod) 11503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 11603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr bias; 11703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *elf = dwfl_module_getelf (mod, &bias); 11803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf) 11903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 12003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Ehdr ehdr_mem; 12103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); 12203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (ehdr) 12303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16; 12403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 12503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 12603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (width == 0) 12703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes width = 16; 12803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 12903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return width; 13003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 13103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 13203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 13303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesmodule_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)), 13403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *name, Dwarf_Addr start, 13503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes void *arg __attribute__((unused))) 13603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 13703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Forces resolving of main elf and debug files. */ 13803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr bias; 13903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Elf *elf = dwfl_module_getelf (mod, &bias); 14003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias); 14103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 14203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr end; 14303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *mainfile; 14403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *debugfile; 14503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL, 14603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, &mainfile, &debugfile); 14703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes assert (strcmp (modname, name) == 0); 14803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 14903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int width = get_addr_width (mod); 15003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n", 15103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes width, start, width, end, basename (name)); 15203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 15303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const unsigned char *id; 15403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr id_vaddr; 15503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); 15603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (id_len > 0) 15703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 15803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (" ["); 15903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes do 16003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("%02" PRIx8, *id++); 16103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (--id_len > 0); 16203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("]\n"); 16303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 16403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 16503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (elf != NULL) 16603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (" %s\n", mainfile != NULL ? mainfile : "-"); 16703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf != NULL) 16803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (" %s\n", debugfile != NULL ? debugfile : "-"); 16903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 17003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return DWARF_CB_OK; 17103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 17203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 17303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 17403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesframe_callback (Dwfl_Frame *state, void *arg) 17503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 17603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct frames *frames = (struct frames *) arg; 17703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int nr = frames->frames; 17803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! dwfl_frame_pc (state, &frames->frame[nr].pc, 17903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &frames->frame[nr].isactivation)) 18003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return -1; 18103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 18203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames->frames++; 18303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frames == maxframes) 18403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return DWARF_CB_ABORT; 18503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 18603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frames == frames->allocated) 18703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 18803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames->allocated *= 2; 18903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames->frame = realloc (frames->frame, 19003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sizeof (struct frame) * frames->allocated); 19103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frame == NULL) 19203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, errno, "realloc frames.frame"); 19303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 19403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 19503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return DWARF_CB_OK; 19603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 19703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 19803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic const char* 19903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesdie_name (Dwarf_Die *die) 20003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 20103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr; 20203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *name; 20303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes name = dwarf_formstring (dwarf_attr_integrate (die, 20403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DW_AT_MIPS_linkage_name, 20503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr) 20603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes ?: dwarf_attr_integrate (die, 20703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes DW_AT_linkage_name, 20803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr)); 20903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (name == NULL) 21003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes name = dwarf_diename (die); 21103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 21203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return name; 21303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 21403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 21503333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void 21603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_frame (int nr, Dwarf_Addr pc, bool isactivation, 21703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc_adjusted, Dwfl_Module *mod, 21803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *symname, Dwarf_Die *cudie, 21903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *die) 22003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 22103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int width = get_addr_width (mod); 22203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc); 22303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 22403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_activation) 22503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("%4s", ! isactivation ? "- 1" : ""); 22603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 22703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (symname != NULL) 22803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 22903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef USE_DEMANGLE 23003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes // Require GNU v3 ABI by the "_Z" prefix. 23103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! show_raw && symname[0] == '_' && symname[1] == 'Z') 23203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 23303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int status = -1; 23403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes char *dsymname = __cxa_demangle (symname, demangle_buffer, 23503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &demangle_buffer_len, &status); 23603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (status == 0) 23703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes symname = demangle_buffer = dsymname; 23803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 23903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 24003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (" %s", symname); 24103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 24203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 24303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char* fname; 24403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr start; 24503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes fname = dwfl_module_info(mod, NULL, &start, 24603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, NULL, NULL, NULL, NULL); 24703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_module) 24803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 24903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (fname != NULL) 25003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (" - %s", fname); 25103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 25203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 25303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_build_id) 25403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 25503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const unsigned char *id; 25603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes GElf_Addr id_vaddr; 25703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); 25803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (id_len > 0) 25903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 26003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("\n ["); 26103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes do 26203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("%02" PRIx8, *id++); 26303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes while (--id_len > 0); 26403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("]@0x%0" PRIx64 "+0x%" PRIx64, 26503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes start, pc_adjusted - start); 26603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 26703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 26803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 26903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_source) 27003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 27103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int line, col; 27203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char* sname; 27303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes line = col = -1; 27403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sname = NULL; 27503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (die != NULL) 27603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 27703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Files *files; 27803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_getsrcfiles (cudie, &files, NULL) == 0) 27903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Attribute attr; 28103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Word val; 28203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, &attr), 28303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &val) == 0) 28403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sname = dwarf_filesrc (files, val, NULL, NULL); 28603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line, 28703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr), &val) == 0) 28803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 28903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes line = val; 29003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column, 29103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &attr), &val) == 0) 29203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes col = val; 29303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 29403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 29503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 29603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 29703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 29803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 29903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted); 30003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (lineobj) 30103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL); 30203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 30303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 30403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (sname != NULL) 30503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 30603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("\n %s", sname); 30703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (line > 0) 30803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 30903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (":%d", line); 31003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (col > 0) 31103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf (":%d", col); 31203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 31303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 31403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 31503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("\n"); 31603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 31703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 31803333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void 31903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_inline_frames (int *nr, Dwarf_Addr pc, bool isactivation, 32003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc_adjusted, Dwfl_Module *mod, 32103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *symname, Dwarf_Die *cudie, Dwarf_Die *die) 32203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 32303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *scopes = NULL; 32403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int nscopes = dwarf_getscopes_die (die, &scopes); 32503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (nscopes > 0) 32603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 32703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* scopes[0] == die, the lowest level, for which we already have 32803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes the name. This is the actual source location where it 32903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes happened. */ 33003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname, 33103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, NULL); 33203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 33303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* last_scope is the source location where the next frame/function 33403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes call was done. */ 33503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *last_scope = &scopes[0]; 33603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (int i = 1; i < nscopes && (maxframes == 0 || *nr < maxframes); i++) 33703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 33803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *scope = &scopes[i]; 33903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int tag = dwarf_tag (scope); 34003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag != DW_TAG_inlined_subroutine 34103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && tag != DW_TAG_entry_point 34203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes && tag != DW_TAG_subprogram) 34303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes continue; 34403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 34503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes symname = die_name (scope); 34603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname, 34703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes cudie, last_scope); 34803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 34903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Found the "top-level" in which everything was inlined? */ 35003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_subprogram) 35103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 35203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 35303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes last_scope = scope; 35403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 35503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 35603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (scopes); 35703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 35803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 35903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void 36003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what) 36103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 36203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frames > 0) 36303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames_shown = true; 36403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 36503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("TID %d:\n", tid); 36603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int frame_nr = 0; 36703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (int nr = 0; nr < frames->frames && (maxframes == 0 36803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || frame_nr < maxframes); nr++) 36903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 37003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc = frames->frame[nr].pc; 37103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool isactivation = frames->frame[nr].isactivation; 37203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); 37303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 37403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Get PC->SYMNAME. */ 37503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); 37603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *symname = NULL; 37703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die die_mem; 37803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *die = NULL; 37903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *cudie = NULL; 38003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (mod && ! show_quiet) 38103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 38203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_debugname) 38303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 38403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr bias = 0; 38503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *scopes = NULL; 38603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes cudie = dwfl_module_addrdie (mod, pc_adjusted, &bias); 38703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int nscopes = dwarf_getscopes (cudie, pc_adjusted - bias, 38803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes &scopes); 38903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 39003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Find the first function-like DIE with a name in scope. */ 39103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes for (int i = 0; symname == NULL && i < nscopes; i++) 39203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 39303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Die *scope = &scopes[i]; 39403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int tag = dwarf_tag (scope); 39503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (tag == DW_TAG_subprogram 39603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || tag == DW_TAG_inlined_subroutine 39703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes || tag == DW_TAG_entry_point) 39803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes symname = die_name (scope); 39903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 40003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (symname != NULL) 40103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 40203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes die_mem = *scope; 40303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes die = &die_mem; 40403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 40503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 40603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (scopes); 40703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 40803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 40903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (symname == NULL) 41003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes symname = dwfl_module_addrname (mod, pc_adjusted); 41103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 41203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 41303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_inlines && die != NULL) 41403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_inline_frames (&frame_nr, pc, isactivation, pc_adjusted, mod, 41503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes symname, cudie, die); 41603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 41703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_frame (frame_nr++, pc, isactivation, pc_adjusted, mod, symname, 41803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, NULL); 41903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 42003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 42103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frames > 0 && frame_nr == maxframes) 42203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (0, 0, "tid %d: shown max number of frames " 42303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes "(%d, use -n 0 for unlimited)", tid, maxframes); 42403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (dwflerr != 0) 42503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 42603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames->frames > 0) 42703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 42803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes unsigned nr = frames->frames - 1; 42903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc = frames->frame[nr].pc; 43003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes bool isactivation = frames->frame[nr].isactivation; 43103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1); 43203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted); 43303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *mainfile = NULL; 43403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL, 43503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes NULL, &mainfile, NULL); 43603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (modname == NULL || modname[0] == '\0') 43703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 43803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (mainfile != NULL) 43903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes modname = mainfile; 44003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 44103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes modname = "<unknown>"; 44203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 44303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (0, 0, "%s tid %d at 0x%" PRIx64 " in %s: %s", what, tid, 44403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pc_adjusted, modname, dwfl_errmsg (dwflerr)); 44503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 44603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 44703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (0, 0, "%s tid %d: %s", what, tid, dwfl_errmsg (dwflerr)); 44803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 44903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 45003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 45103333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic int 45203333823c75a1c1887e923828113a1b0fd12020cElliott Hughesthread_callback (Dwfl_Thread *thread, void *thread_arg) 45303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 45403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct frames *frames = (struct frames *) thread_arg; 45503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid_t tid = dwfl_thread_tid (thread); 45603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int err = 0; 45703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames->frames = 0; 45803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (dwfl_thread_getframes (thread, frame_callback, thread_arg)) 45903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 46003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_OK: 46103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_ABORT: 46203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 46303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case -1: 46403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes err = dwfl_errno (); 46503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 46603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 46703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes abort (); 46803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 46903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_frames (frames, tid, err, "dwfl_thread_getframes"); 47003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return DWARF_CB_OK; 47103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 47203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 47303333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic void 47403333823c75a1c1887e923828113a1b0fd12020cElliott Hughesprint_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) 47503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 47603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes fprintf (stream, "stack (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); 47703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 47803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 47903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesstatic error_t 48003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesparse_opt (int key, char *arg __attribute__ ((unused)), 48103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct argp_state *state) 48203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 48303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (key) 48403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 48503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'p': 48603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid = atoi (arg); 48703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid == 0) 48803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_error (state, N_("-p PID should be a positive process id.")); 48903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 49003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 49103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case OPT_COREFILE: 49203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes core_fd = open (arg, O_RDONLY); 49303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core_fd < 0) 49403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, errno, N_("Cannot open core file '%s'"), arg); 49503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_version (EV_CURRENT); 49603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL); 49703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core == NULL) 49803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1)); 49903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 50003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 50103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'e': 50203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes exec = arg; 50303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 50403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 50503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case OPT_DEBUGINFO: 50603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes debuginfo_path = arg; 50703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 50803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 50903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'm': 51003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_module = true; 51103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 51203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 51303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 's': 51403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_source = true; 51503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 51603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 51703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'a': 51803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_activation = true; 51903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 52003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 52103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'd': 52203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_debugname = true; 52303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 52403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 52503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'i': 52603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_inlines = show_debugname = true; 52703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 52803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 52903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'v': 53003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_activation = show_source = show_module = show_debugname = true; 53103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_inlines = true; 53203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 53303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 53403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'b': 53503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_build_id = true; 53603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 53703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 53803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'q': 53903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_quiet = true; 54003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 54103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 54203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'r': 54303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_raw = true; 54403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 54503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 54603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case '1': 54703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_one_tid = true; 54803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 54903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 55003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'n': 55103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes maxframes = atoi (arg); 55203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (maxframes < 0) 55303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 55403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_error (state, N_("-n MAXFRAMES should be 0 or higher.")); 55503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return EINVAL; 55603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 55703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 55803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 55903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case 'l': 56003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes show_modules = true; 56103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 56203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 56303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case ARGP_KEY_END: 56403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core == NULL && exec != NULL) 56503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_error (state, 56603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("-e EXEC needs a core given by --core.")); 56703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 56803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid == 0 && show_one_tid == true) 56903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_error (state, 57003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("-1 needs a thread id given by -p.")); 57103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 57203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if ((pid == 0 && core == NULL) || (pid != 0 && core != NULL)) 57303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_error (state, 57403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("One of -p PID or --core COREFILE should be given.")); 57503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 57603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid != 0) 57703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 57803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl = dwfl_begin (&proc_callbacks); 57903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl == NULL) 58003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); 58103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 58203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int err = dwfl_linux_proc_report (dwfl, pid); 58303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (err < 0) 58403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %d: %s", pid, 58503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl_errmsg (-1)); 58603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (err > 0) 58703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, err, "dwfl_linux_proc_report pid %d", pid); 58803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 58903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 59003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core != NULL) 59103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 59203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl = dwfl_begin (&core_callbacks); 59303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl == NULL) 59403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1)); 59503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl_core_file_report (dwfl, core, exec) < 0) 59603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1)); 59703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 59803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 59903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl_report_end (dwfl, NULL, NULL) != 0) 60003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1)); 60103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 60203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (pid != 0) 60303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 60403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int err = dwfl_linux_proc_attach (dwfl, pid, false); 60503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (err < 0) 60603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %d: %s", pid, 60703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl_errmsg (-1)); 60803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else if (err > 0) 60903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %d", pid); 61003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 61103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 61203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core != NULL) 61303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 61403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl_core_file_attach (dwfl, core) < 0) 61503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1)); 61603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 61703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 61803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Makes sure we are properly attached. */ 61903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl_pid (dwfl) < 0) 62003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1)); 62103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 62203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 62303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 62403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return ARGP_ERR_UNKNOWN; 62503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 62603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return 0; 62703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 62803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 62903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesint 63003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesmain (int argc, char **argv) 63103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes{ 63203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* We use no threads here which can interfere with handling a stream. */ 63303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __fsetlocking (stdin, FSETLOCKING_BYCALLER); 63403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __fsetlocking (stdout, FSETLOCKING_BYCALLER); 63503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes __fsetlocking (stderr, FSETLOCKING_BYCALLER); 63603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 63703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* Set locale. */ 63803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes (void) setlocale (LC_ALL, ""); 63903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 64003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const struct argp_option options[] = 64103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 64203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { NULL, 0, NULL, 0, N_("Input selection options:"), 0 }, 64303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "pid", 'p', "PID", 0, 64403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show stack of process PID"), 0 }, 64503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "core", OPT_COREFILE, "COREFILE", 0, 64603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show stack found in COREFILE"), 0 }, 64703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "executable", 'e', "EXEC", 0, N_("(optional) EXECUTABLE that produced COREFILE"), 0 }, 64803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0, 64903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Search path for separate debuginfo files"), 0 }, 65003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 65103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { NULL, 0, NULL, 0, N_("Output selection options:"), 0 }, 65203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "activation", 'a', NULL, 0, 65303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Additionally show frame activation"), 0 }, 65403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "debugname", 'd', NULL, 0, 65503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Additionally try to lookup DWARF debuginfo name for frame address"), 65603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 0 }, 65703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "inlines", 'i', NULL, 0, 65803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Additionally show inlined function frames using DWARF debuginfo if available (implies -d)"), 0 }, 65903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "module", 'm', NULL, 0, 66003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Additionally show module file information"), 0 }, 66103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "source", 's', NULL, 0, 66203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Additionally show source file information"), 0 }, 66303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "verbose", 'v', NULL, 0, 66403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show all additional information (activation, debugname, inlines, module and source)"), 0 }, 66503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "quiet", 'q', NULL, 0, 66603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Do not resolve address to function symbol name"), 0 }, 66703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "raw", 'r', NULL, 0, 66803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show raw function symbol names, do not try to demangle names"), 0 }, 66903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "build-id", 'b', NULL, 0, 67003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show module build-id, load address and pc offset"), 0 }, 67103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { NULL, '1', NULL, 0, 67203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show the backtrace of only one thread"), 0 }, 67303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { NULL, 'n', "MAXFRAMES", 0, 67403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"), 0 }, 67503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { "list-modules", 'l', NULL, 0, 67603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes N_("Show module memory map with build-id, elf and debug files detected"), 0 }, 67703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { NULL, 0, NULL, 0, NULL, 0 } 67803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 67903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 68003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes const struct argp argp = 68103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 68203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .options = options, 68303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .parser = parse_opt, 68403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes .doc = N_("Print a stack for each thread in a process or core file.\v\ 68503333823c75a1c1887e923828113a1b0fd12020cElliott HughesProgram exits with return code 0 if all frames were shown without \ 68603333823c75a1c1887e923828113a1b0fd12020cElliott Hughesany errors. If some frames were shown, but there were some non-fatal \ 68703333823c75a1c1887e923828113a1b0fd12020cElliott Hugheserrors, possibly causing an incomplete backtrace, the program exits \ 68803333823c75a1c1887e923828113a1b0fd12020cElliott Hugheswith return code 1. If no frames could be shown, or a fatal error \ 68903333823c75a1c1887e923828113a1b0fd12020cElliott Hughesoccured the program exits with return code 2. If the program was \ 69003333823c75a1c1887e923828113a1b0fd12020cElliott Hughesinvoked with bad or missing arguments it will exit with return code 64.") 69103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes }; 69203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 69303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes argp_parse (&argp, argc, argv, 0, NULL, NULL); 69403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 69503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_modules) 69603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 69703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("PID %d - %s module memory map\n", dwfl_pid (dwfl), 69803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes pid != 0 ? "process" : "core"); 69903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0) 70003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); 70103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 70203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 70303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes struct frames frames; 70403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes /* When maxframes is zero, then 2048 is just the initial allocation 70503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes that will be increased using realloc in framecallback (). */ 70603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames.allocated = maxframes == 0 ? 2048 : maxframes; 70703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames.frames = 0; 70803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes frames.frame = malloc (sizeof (struct frame) * frames.allocated); 70903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (frames.frame == NULL) 71003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, errno, "malloc frames.frame"); 71103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 71203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (show_one_tid) 71303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 71403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes int err = 0; 71503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (dwfl_getthread_frames (dwfl, pid, frame_callback, &frames)) 71603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 71703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_OK: 71803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_ABORT: 71903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 72003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case -1: 72103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes err = dwfl_errno (); 72203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 72303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 72403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes abort (); 72503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 72603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes print_frames (&frames, pid, err, "dwfl_getthread_frames"); 72703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 72803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes else 72903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 73003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes printf ("PID %d - %s\n", dwfl_pid (dwfl), pid != 0 ? "process" : "core"); 73103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes switch (dwfl_getthreads (dwfl, thread_callback, &frames)) 73203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes { 73303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_OK: 73403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case DWARF_CB_ABORT: 73503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 73603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes case -1: 73703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1)); 73803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes break; 73903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes default: 74003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes abort (); 74103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 74203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes } 74303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (frames.frame); 74403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes dwfl_end (dwfl); 74503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 74603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core != NULL) 74703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes elf_end (core); 74803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 74903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (core_fd != -1) 75003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes close (core_fd); 75103333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 75203333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#ifdef USE_DEMANGLE 75303333823c75a1c1887e923828113a1b0fd12020cElliott Hughes free (demangle_buffer); 75403333823c75a1c1887e923828113a1b0fd12020cElliott Hughes#endif 75503333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 75603333823c75a1c1887e923828113a1b0fd12020cElliott Hughes if (! frames_shown) 75703333823c75a1c1887e923828113a1b0fd12020cElliott Hughes error (EXIT_BAD, 0, N_("Couldn't show any frames.")); 75803333823c75a1c1887e923828113a1b0fd12020cElliott Hughes 75903333823c75a1c1887e923828113a1b0fd12020cElliott Hughes return error_message_count != 0 ? EXIT_ERROR : EXIT_OK; 76003333823c75a1c1887e923828113a1b0fd12020cElliott Hughes} 761