[libbacktrace] Read .gnu_debugaltlink
authorTom de Vries <tdevries@suse.de>
Thu, 17 Jan 2019 00:07:21 +0000 (00:07 +0000)
committerTom de Vries <vries@gcc.gnu.org>
Thu, 17 Jan 2019 00:07:21 +0000 (00:07 +0000)
Read the elf file pointed at by the .gnu_debugaltlink section, and verify that
the build id matches.

2019-01-17  Tom de Vries  <tdevries@suse.de>

* elf.c (elf_add): Add and handle with_buildid_data and
with_buildid_size parameters.  Handle .gnu_debugaltlink section.
(phdr_callback, backtrace_initialize): Add arguments to elf_add calls.

From-SVN: r267992

libbacktrace/ChangeLog
libbacktrace/Makefile.in
libbacktrace/elf.c

index cc8bb74d083169395515203fa406268d5d50f682..d76341ac70e2dbe9040a7567d8b21b9719cd9234 100644 (file)
@@ -1,3 +1,9 @@
+2019-01-17  Tom de Vries  <tdevries@suse.de>
+
+       * elf.c (elf_add): Add and handle with_buildid_data and
+       with_buildid_size parameters.  Handle .gnu_debugaltlink section.
+       (phdr_callback, backtrace_initialize): Add arguments to elf_add calls.
+
 2019-01-16  Tom de Vries  <tdevries@suse.de>
 
        * dwarf.c (read_referenced_name_from_attr): New function.  Factor out
index c595a8b4a3e1473c73f167f21cc8fa2fab74b2cf..17e7ea868792c58a19ed4047cf5151705fbee082 100644 (file)
@@ -15,7 +15,7 @@
 @SET_MAKE@
 
 # Makefile.am -- Backtrace Makefile.
-# Copyright (C) 2012-2018 Free Software Foundation, Inc.
+# Copyright (C) 2012-2019 Free Software Foundation, Inc.
 
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions are
index 85a323c5876a00f6f3d453d1effe691fca5f86f1..abe4cded5e9c021188268b8f4f24311c427df682 100644 (file)
@@ -2638,7 +2638,8 @@ static int
 elf_add (struct backtrace_state *state, const char *filename, int descriptor,
         uintptr_t base_address, backtrace_error_callback error_callback,
         void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
-        int exe, int debuginfo)
+        int exe, int debuginfo, const char *with_buildid_data,
+        uint32_t with_buildid_size)
 {
   struct backtrace_view ehdr_view;
   b_elf_ehdr ehdr;
@@ -2670,6 +2671,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
   int debuglink_view_valid;
   const char *debuglink_name;
   uint32_t debuglink_crc;
+  struct backtrace_view debugaltlink_view;
+  int debugaltlink_view_valid;
+  const char *debugaltlink_name;
+  const char *debugaltlink_buildid_data;
+  uint32_t debugaltlink_buildid_size;
   off_t min_offset;
   off_t max_offset;
   struct backtrace_view debug_view;
@@ -2694,6 +2700,10 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
   debuglink_view_valid = 0;
   debuglink_name = NULL;
   debuglink_crc = 0;
+  debugaltlink_view_valid = 0;
+  debugaltlink_name = NULL;
+  debugaltlink_buildid_data = NULL;
+  debugaltlink_buildid_size = 0;
   debug_view_valid = 0;
   opd = NULL;
 
@@ -2873,6 +2883,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
              buildid_data = &note->name[0] + ((note->namesz + 3) & ~ 3);
              buildid_size = note->descsz;
            }
+
+         if (with_buildid_size != 0)
+           {
+             if (buildid_size != with_buildid_size)
+               goto fail;
+
+             if (memcmp (buildid_data, with_buildid_data, buildid_size) != 0)
+               goto fail;
+           }
        }
 
       /* Read the debuglink file if present.  */
@@ -2899,6 +2918,32 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
            }
        }
 
+      if (!debugaltlink_view_valid
+         && strcmp (name, ".gnu_debugaltlink") == 0)
+       {
+         const char *debugaltlink_data;
+         size_t debugaltlink_name_len;
+
+         if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
+                                  shdr->sh_size, error_callback, data,
+                                  &debugaltlink_view))
+           goto fail;
+
+         debugaltlink_view_valid = 1;
+         debugaltlink_data = (const char *) debugaltlink_view.data;
+         debugaltlink_name = debugaltlink_data;
+         debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
+         if (debugaltlink_name_len < shdr->sh_size)
+           {
+             /* Include terminating zero.  */
+             debugaltlink_name_len =+ 1;
+
+             debugaltlink_buildid_data
+               = debugaltlink_data + debugaltlink_name_len;
+             debugaltlink_buildid_size = shdr->sh_size - debugaltlink_name_len;
+           }
+       }
+
       /* Read the .opd section on PowerPC64 ELFv1.  */
       if (ehdr.e_machine == EM_PPC64
          && (ehdr.e_flags & EF_PPC64_ABI) < 2
@@ -2993,8 +3038,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
          if (debuglink_view_valid)
            backtrace_release_view (state, &debuglink_view, error_callback,
                                    data);
+         if (debugaltlink_view_valid)
+           backtrace_release_view (state, &debugaltlink_view, error_callback,
+                                   data);
          ret = elf_add (state, NULL, d, base_address, error_callback, data,
-                        fileline_fn, found_sym, found_dwarf, 0, 1);
+                        fileline_fn, found_sym, found_dwarf, 0, 1, NULL, 0);
          if (ret < 0)
            backtrace_close (d, error_callback, data);
          else
@@ -3028,8 +3076,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
 
          backtrace_release_view (state, &debuglink_view, error_callback,
                                  data);
+         if (debugaltlink_view_valid)
+           backtrace_release_view (state, &debugaltlink_view, error_callback,
+                                   data);
          ret = elf_add (state, NULL, d, base_address, error_callback, data,
-                        fileline_fn, found_sym, found_dwarf, 0, 1);
+                        fileline_fn, found_sym, found_dwarf, 0, 1, NULL, 0);
          if (ret < 0)
            backtrace_close (d, error_callback, data);
          else
@@ -3044,6 +3095,36 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
       debuglink_view_valid = 0;
     }
 
+  if (debugaltlink_name != NULL)
+    {
+      int d;
+
+      d = elf_open_debugfile_by_debuglink (state, filename, debugaltlink_name,
+                                          0, error_callback, data);
+      if (d >= 0)
+       {
+         int ret;
+
+         ret = elf_add (state, filename, d, base_address, error_callback, data,
+                        fileline_fn, found_sym, found_dwarf, 0, 1,
+                        debugaltlink_buildid_data, debugaltlink_buildid_size);
+         backtrace_release_view (state, &debugaltlink_view, error_callback,
+                                 data);
+         debugaltlink_view_valid = 0;
+         if (ret < 0)
+           {
+             backtrace_close (d, error_callback, data);
+             return ret;
+           }
+       }
+    }
+
+  if (debugaltlink_view_valid)
+    {
+      backtrace_release_view (state, &debugaltlink_view, error_callback, data);
+      debugaltlink_view_valid = 0;
+    }
+
   /* Read all the debug sections in a single view, since they are
      probably adjacent in the file.  We never release this view.  */
 
@@ -3199,6 +3280,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
     backtrace_release_view (state, &strtab_view, error_callback, data);
   if (debuglink_view_valid)
     backtrace_release_view (state, &debuglink_view, error_callback, data);
+  if (debugaltlink_view_valid)
+    backtrace_release_view (state, &debugaltlink_view, error_callback, data);
   if (buildid_view_valid)
     backtrace_release_view (state, &buildid_view, error_callback, data);
   if (debug_view_valid)
@@ -3269,7 +3352,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
 
   if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
               pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
-              &found_dwarf, 0, 0))
+              &found_dwarf, 0, 0, NULL, 0))
     {
       if (found_dwarf)
        {
@@ -3297,7 +3380,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
   struct phdr_data pd;
 
   ret = elf_add (state, filename, descriptor, 0, error_callback, data,
-                &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0);
+                &elf_fileline_fn, &found_sym, &found_dwarf, 1, 0, NULL, 0);
   if (!ret)
     return 0;