]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
2005-12-22 Roland McGrath <roland@redhat.com>
authorRoland McGrath <roland@redhat.com>
Fri, 23 Dec 2005 01:49:50 +0000 (01:49 +0000)
committerRoland McGrath <roland@redhat.com>
Fri, 23 Dec 2005 01:49:50 +0000 (01:49 +0000)
* argp-std.c (parse_opt): Call dwfl_end in failure cases.

* linux-proc-maps.c (proc_maps_report): New function, broken out of ...
(dwfl_linux_proc_report): ... here.  Call it.
(dwfl_linux_proc_maps_report): New function.
* libdwfl.h: Declare it.
* libdwflP.h: Add INTDECL.
* argp-std.c (options, parse_opt): Grok -M/--linux-process-map.

libdwfl/ChangeLog
libdwfl/argp-std.c
libdwfl/libdwfl.h
libdwfl/libdwflP.h
libdwfl/linux-proc-maps.c

index ed52f44d0e101d8dbd421098d766eb406f25cec1..8615f0cda845bb7fd7b51d143f6f52c4bf934c7a 100644 (file)
@@ -1,5 +1,14 @@
 2005-12-22  Roland McGrath  <roland@redhat.com>
 
+       * argp-std.c (parse_opt): Call dwfl_end in failure cases.
+
+       * linux-proc-maps.c (proc_maps_report): New function, broken out of ...
+       (dwfl_linux_proc_report): ... here.  Call it.
+       (dwfl_linux_proc_maps_report): New function.
+       * libdwfl.h: Declare it.
+       * libdwflP.h: Add INTDECL.
+       * argp-std.c (options, parse_opt): Grok -M/--linux-process-map.
+
        * dwfl_nextcu.c (dwfl_nextcu): Don't fail when dwfl_module_getdwarf
        failed with DWFL_E_NO_DWARF.
 
index 4a6e1607f0f1d259edff7c67ea7b519910f66bda..4ee5ce16f30861467dae27397931bf7befb00b26 100644 (file)
@@ -29,6 +29,9 @@ static const struct argp_option options[] =
   { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
   { "pid", 'p', "PID", 0,
     N_("Find addresses in files mapped into process PID"), 0 },
+  { "linux-process-map", 'M', "FILE", 0,
+    N_("Find addresses in files mapped as read from FILE"
+       " in Linux /proc/PID/maps format"), 0 },
   { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
   { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
     N_("Kernel with all modules"), 0 },
@@ -67,17 +70,19 @@ static const Dwfl_Callbacks kernel_callbacks =
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
-  inline void failure (int errnum, const char *msg)
+  inline void failure (Dwfl *dwfl, int errnum, const char *msg)
     {
       if (errnum == -1)
        argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
                      msg, INTUSE(dwfl_errmsg) (-1));
       else
        argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
+      if (dwfl != NULL)
+       dwfl_end (dwfl);
     }
-  inline error_t fail (int errnum, const char *msg)
+  inline error_t fail (Dwfl *dwfl, int errnum, const char *msg)
     {
-      failure (errnum, msg);
+      failure (dwfl, errnum, msg);
       return errnum == -1 ? EIO : errnum;
     }
 
@@ -94,13 +99,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
          {
            dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
            if (dwfl == NULL)
-             return fail (-1, arg);
+             return fail (dwfl, -1, arg);
            state->hook = dwfl;
          }
        if (dwfl->callbacks == &offline_callbacks)
          {
            if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
-             return fail (-1, arg);
+             return fail (dwfl, -1, arg);
            state->hook = dwfl;
          }
        else
@@ -119,7 +124,29 @@ parse_opt (int key, char *arg, struct argp_state *state)
          Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
          int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
          if (result != 0)
-           return fail (result, arg);
+           return fail (dwfl, result, arg);
+         state->hook = dwfl;
+       }
+      else
+       goto toomany;
+      break;
+
+    case 'M':
+      if (state->hook == NULL)
+       {
+         FILE *f = fopen (arg, "r");
+         if (f == NULL)
+           {
+             int code = errno;
+             argp_failure (state, EXIT_FAILURE, code,
+                           "cannot open '%s'", arg);
+             return code;
+           }
+         Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
+         int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
+         fclose (f);
+         if (result != 0)
+           return fail (dwfl, result, arg);
          state->hook = dwfl;
        }
       else
@@ -132,11 +159,11 @@ parse_opt (int key, char *arg, struct argp_state *state)
          Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
          int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
          if (result != 0)
-           return fail (result, _("cannot load kernel symbols"));
+           return fail (dwfl, result, _("cannot load kernel symbols"));
          result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
          if (result != 0)
            /* Non-fatal to have no modules since we do have the kernel.  */
-           failure (result, _("cannot find kernel modules"));
+           failure (dwfl, result, _("cannot find kernel modules"));
          state->hook = dwfl;
        }
       else
@@ -150,7 +177,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
          int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
                                                                 NULL);
          if (result != 0)
-           return fail (result, _("cannot find kernel or modules"));
+           return fail (dwfl, result, _("cannot find kernel or modules"));
          state->hook = dwfl;
        }
       else
@@ -167,7 +194,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
            arg = "a.out";
            dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
            if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
-             return fail (-1, arg);
+             return fail (dwfl, -1, arg);
            state->hook = dwfl;
          }
 
index f46528097ee914d682929c6afd1356029a982230..4135fc3de5f559ef79d16b276e054946172b41d7 100644 (file)
@@ -15,6 +15,7 @@
 #define _LIBDWFL_H     1
 
 #include "libdw.h"
+#include <stdio.h>
 
 /* Handle for a session using the library.  */
 typedef struct Dwfl Dwfl;
@@ -213,6 +214,10 @@ extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
    or an errno code if opening the kernel binary failed.  */
 extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid);
 
+/* Similar, but reads an input stream in the format of Linux /proc/PID/maps
+   files giving module layout, not the file for a live process.  */
+extern int dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *);
+
 /* Trivial find_elf callback for use with dwfl_linux_proc_report.
    This uses the module name as a file name directly and tries to open it
    if it begin with a slash, or handles the magic string "[vdso]".  */
index a0d88d115c8f4908d01f1a983ff75ff6988274cb..904cd55e2d1d05ba1f1f4eba3ae48c36c5230695 100644 (file)
@@ -244,6 +244,7 @@ INTDECL (dwfl_standard_find_debuginfo)
 INTDECL (dwfl_linux_kernel_find_elf)
 INTDECL (dwfl_linux_kernel_module_section_address)
 INTDECL (dwfl_linux_proc_report)
+INTDECL (dwfl_linux_proc_maps_report)
 INTDECL (dwfl_linux_proc_find_elf)
 INTDECL (dwfl_linux_kernel_report_kernel)
 INTDECL (dwfl_linux_kernel_report_modules)
index 2611c73a42323dfbf840389527063bfa0b638e6d..fc1619ce42685e44089e2c0ec83beca5b46e3fa0 100644 (file)
@@ -91,30 +91,9 @@ find_sysinfo_ehdr (pid_t pid, GElf_Addr *sysinfo_ehdr)
   return nread < 0 ? errno : 0;
 }
 
-int
-dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
+static int
+proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
 {
-  if (dwfl == NULL)
-    return -1;
-
-  /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it.  */
-  GElf_Addr sysinfo_ehdr = 0;
-  int result = find_sysinfo_ehdr (pid, &sysinfo_ehdr);
-  if (result != 0)
-    return result;
-
-  char *fname = NULL;
-  asprintf (&fname, PROCMAPSFMT, pid);
-  if (fname == NULL)
-    return ENOMEM;
-
-  FILE *f = fopen (fname, "r");
-  free (fname);
-  if (f == NULL)
-    return errno;
-
-  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
-
   unsigned int last_dmajor = -1, last_dminor = -1;
   uint64_t last_ino = -1;
   char *last_file = NULL;
@@ -201,16 +180,52 @@ dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
     }
   free (line);
 
-  result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
-  fclose (f);
+  int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
 
   /* Report the final one.  */
   bool lose = report ();
 
   return result != 0 ? result : lose ? -1 : 0;
 }
-INTDEF (dwfl_linux_proc_report)
 
+int
+dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f)
+{
+  return proc_maps_report (dwfl, f, 0, 0);
+}
+INTDEF (dwfl_linux_proc_maps_report)
+
+int
+dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
+{
+  if (dwfl == NULL)
+    return -1;
+
+  /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it.  */
+  GElf_Addr sysinfo_ehdr = 0;
+  int result = find_sysinfo_ehdr (pid, &sysinfo_ehdr);
+  if (result != 0)
+    return result;
+
+  char *fname = NULL;
+  asprintf (&fname, PROCMAPSFMT, pid);
+  if (fname == NULL)
+    return ENOMEM;
+
+  FILE *f = fopen (fname, "r");
+  free (fname);
+  if (f == NULL)
+    return errno;
+
+  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
+
+  result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid);
+
+  fclose (f);
+
+  return result;
+}
+INTDEF (dwfl_linux_proc_report)
 
 static ssize_t
 read_proc_memory (void *arg, void *data, GElf_Addr address,