[PATCH] stack: Add -l, --list-modules. Show module memory map, build-id and files.

Mark Wielaard mjw at redhat.com
Sat Dec 28 22:31:44 UTC 2013


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 <mjw at redhat.com>
---
 src/ChangeLog | 11 +++++++
 src/stack.c   | 98 ++++++++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 92 insertions(+), 17 deletions(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 7911236..cb9c815 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,14 @@
+2013-12-28  Mark Wielaard  <mjw at redhat.com>
+
+	* 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  <mjw at redhat.com>
 
 	* stack.c (frames_shown): New static boolean.
diff --git a/src/stack.c b/src/stack.c
index d71d669..156455c 100644
--- a/src/stack.c
+++ b/src/stack.c
@@ -23,6 +23,7 @@
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdio_ext.h>
+#include <string.h>
 #include <locale.h>
 #include <fcntl.h>
 #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;
 
@@ -103,6 +105,70 @@ static bool frames_shown = false;
 #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)
 {
   struct frames *frames = (struct frames *) 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;
-- 
1.8.4.2



More information about the elfutils-devel mailing list