From: Mark Wielaard Date: Sat, 28 Dec 2013 22:25:54 +0000 (+0100) Subject: stack: Add -l, --list-modules. Show module memory map, build-id and files. X-Git-Tag: elfutils-0.158~15 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a6141d27691a68a4af5eb48ab10d27e74d3c2a6b;p=thirdparty%2Felfutils.git stack: Add -l, --list-modules. Show module memory map, build-id and files. Use to list modules detected for process or core file by stack program and to see build-ids and which main elf and debug files were recognized by libdwfl callbacks. Signed-off-by: Mark Wielaard --- diff --git a/src/ChangeLog b/src/ChangeLog index 79112362f..cb9c8151b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2013-12-28 Mark Wielaard + + * stack.c (print_frames): Remove address width code and use... + (get_addr_width): ...this new function. + (show_modules): New static boolean. + (module_callback): New static function. + (parse_opt): Handle '-l'. + (main): Add 'l' to options. If show_modules then use dwfl_getmodules + with module_callback to show all detected modules and possible + build_id, elf and dwarf files. + 2013-12-27 Mark Wielaard * stack.c (frames_shown): New static boolean. diff --git a/src/stack.c b/src/stack.c index d71d669ab..156455c05 100644 --- a/src/stack.c +++ b/src/stack.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include ELFUTILS_HEADER(dwfl) @@ -49,6 +50,7 @@ static bool show_quiet = false; #ifdef USE_DEMANGLE static bool show_raw = false; #endif +static bool show_modules = false; static unsigned maxframes = 64; @@ -102,6 +104,70 @@ static bool frames_shown = false; #define EXIT_BAD 2 #define EXIT_USAGE 64 +static int +get_addr_width (Dwfl_Module *mod) +{ + // Try to find the address wide if possible. + static int width = 0; + if (width == 0 && mod) + { + Dwarf_Addr bias; + Elf *elf = dwfl_module_getelf (mod, &bias); + if (elf) + { + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr) + width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16; + } + } + if (width == 0) + width = 16; + + return width; +} + +static int +module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)), + const char *name, Dwarf_Addr start, + void *arg __attribute__((unused))) +{ + /* Forces resolving of main elf and debug files. */ + Dwarf_Addr bias; + Elf *elf = dwfl_module_getelf (mod, &bias); + Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias); + + Dwarf_Addr end; + const char *mainfile; + const char *debugfile; + const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL, + NULL, &mainfile, &debugfile); + assert (strcmp (modname, name) == 0); + + int width = get_addr_width (mod); + printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n", + width, start, width, end, basename (name)); + + const unsigned char *id; + GElf_Addr id_vaddr; + int id_len = dwfl_module_build_id (mod, &id, &id_vaddr); + if (id_len > 0) + { + printf (" ["); + do + printf ("%02" PRIx8, *id++); + while (--id_len > 0); + printf ("]\n"); + } + + if (elf != NULL) + printf (" %s\n", mainfile != NULL ? mainfile : "-"); + if (dwarf != NULL) + printf (" %s\n", debugfile != NULL ? debugfile : "-"); + + return DWARF_CB_OK; +} + static int frame_callback (Dwfl_Frame *state, void *arg) { @@ -137,23 +203,7 @@ print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what) if (mod && ! show_quiet) symname = dwfl_module_addrname (mod, pc_adjusted); - // Try to find the address wide if possible. - static int width = 0; - if (width == 0 && mod) - { - Dwarf_Addr bias; - Elf *elf = dwfl_module_getelf (mod, &bias); - if (elf) - { - GElf_Ehdr ehdr_mem; - GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem); - if (ehdr) - width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16; - } - } - if (width == 0) - width = 16; - + int width = get_addr_width (mod); printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc); if (show_activation) @@ -350,6 +400,10 @@ parse_opt (int key, char *arg __attribute__ ((unused)), } break; + case 'l': + show_modules = true; + break; + case ARGP_KEY_END: if (core == NULL && exec != NULL) argp_error (state, @@ -443,6 +497,8 @@ main (int argc, char **argv) N_("Show the backtrace of only one thread"), 0 }, { NULL, 'n', "MAXFRAMES", 0, N_("Show at most MAXFRAMES per thread (default 64)"), 0 }, + { "list-modules", 'l', NULL, 0, + N_("Show module memory map with build-id, elf and debug files detected"), 0 }, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -461,6 +517,14 @@ invoked with bad or missing arguments it will exit with return code 64.") argp_parse (&argp, argc, argv, 0, NULL, NULL); + if (show_modules) + { + printf ("PID %d - %s module memory map\n", dwfl_pid (dwfl), + pid != 0 ? "process" : "core"); + if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0) + error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1)); + } + struct frames *frames = malloc (sizeof (struct frames) + sizeof (struct frame) * maxframes); frames->frames = 0;