summaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2021-12-16 14:05:40 +0000
committerNick Clifton <nickc@redhat.com>2021-12-16 14:05:40 +0000
commit61ab1364c7efa3934e0ca62af444e6e6e34f219e (patch)
tree19c55de789643442ba201ef5772b9bce33097a4e /binutils
parenta2b1ea81bacc044a721092484c7cdcb600bcf9ce (diff)
When loading separate debug info files, also attempt to locate a file based upon the build-id.
PR 28697 * dwarf.c (load_build_id_debug_file): New function. (try_build_id_prefix): New function. (check_for_and_load_links): Call load_build_id_debug_file. (debug_displays): Add entry for .note.gnu.build-id. * dwarf.h (enum dwarf_section_display_enum): Add note_gnu_build_id. * testsuite/binutils-all/debuginfod.exp (test_fetch_debuglink): Fix regexp for loads via debuglink section.
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog12
-rw-r--r--binutils/dwarf.c116
-rw-r--r--binutils/dwarf.h1
-rw-r--r--binutils/testsuite/binutils-all/debuginfod.exp6
4 files changed, 131 insertions, 4 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 2bbcfcf54f..9ed85a93c5 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,15 @@
+2021-12-16 Nick Clifton <nickc@redhat.com>
+
+ PR 28697
+ * dwarf.c (load_build_id_debug_file): New function.
+ (try_build_id_prefix): New function.
+ (check_for_and_load_links): Call load_build_id_debug_file.
+ (debug_displays): Add entry for .note.gnu.build-id.
+ * dwarf.h (enum dwarf_section_display_enum): Add
+ note_gnu_build_id.
+ * testsuite/binutils-all/debuginfod.exp (test_fetch_debuglink):
+ Fix regexp for loads via debuglink section.
+
2021-12-03 Chenghua Xu <xuchenghua@loongson.cn>
* MAINTAINERS: Add myself and Zhensong Liu
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index eeef98d4a1..12c5b0a8fa 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -11292,6 +11292,117 @@ load_dwo_file (const char * main_filename, const char * name, const char * dir,
return separate_handle;
}
+static void *
+try_build_id_prefix (const char * prefix, char * filename, const unsigned char * data, unsigned long id_len)
+{
+ char * f = filename;
+
+ f += sprintf (f, prefix);
+ f += sprintf (f, ".build-id/%02x/", (unsigned) *data++);
+ id_len --;
+ while (id_len --)
+ f += sprintf (f, "%02x", (unsigned) *data++);
+ f += sprintf (f, ".debug");
+
+ return open_debug_file (filename);
+}
+
+/* Try to load a debug file based upon the build-id held in the .note.gnu.build-id section. */
+
+static void
+load_build_id_debug_file (const char * main_filename, void * main_file)
+{
+ if (! load_debug_section (note_gnu_build_id, main_file))
+ return; /* No .note.gnu.build-id section. */
+
+ struct dwarf_section * section = & debug_displays [note_gnu_build_id].section;
+ if (section == NULL)
+ {
+ warn (_("Unable to load the .note.gnu.build-id section\n"));
+ return;
+ }
+
+ if (section->start == NULL || section->size < 0x18)
+ {
+ warn (_(".note.gnu.build-id section is corrupt/empty\n"));
+ return;
+ }
+
+ /* In theory we should extract the contents of the section into
+ a note structure and then check the fields. For now though
+ just use hard coded offsets instead:
+
+ Field Bytes Contents
+ NSize 0...3 4
+ DSize 4...7 8+
+ Type 8..11 3 (NT_GNU_BUILD_ID)
+ Name 12.15 GNU\0
+ Data 16.... */
+
+ /* FIXME: Check the name size, name and type fields. */
+
+ unsigned long build_id_size;
+ build_id_size = byte_get (section->start + 4, 4);
+ if (build_id_size < 8)
+ {
+ warn (_(".note.gnu.build-id data size is too small\n"));
+ return;
+ }
+
+ if (build_id_size > (section->size - 16))
+ {
+ warn (_(".note.gnu.build-id data size is too bug\n"));
+ return;
+ }
+
+ char * filename;
+ filename = xmalloc (strlen (".build-id/")
+ + build_id_size * 2 + 2
+ + strlen (".debug")
+ /* The next string should be the same as the longest
+ name found in the prefixes[] array below. */
+ + strlen ("/usrlib64/debug/usr")
+ + 1);
+ void * handle;
+
+ static const char * prefixes[] =
+ {
+ "",
+ ".debug/",
+ "/usr/lib/debug/",
+ "/usr/lib/debug/usr/",
+ "/usr/lib64/debug/",
+ "/usr/lib64/debug/usr"
+ };
+ long unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE (prefixes); i++)
+ {
+ handle = try_build_id_prefix (prefixes[i], filename,
+ section->start + 16, build_id_size);
+ if (handle != NULL)
+ break;
+ }
+ /* FIXME: TYhe BFD library also tries a global debugfile directory prefix. */
+ if (handle == NULL)
+ {
+ /* Failed to find a debug file associated with the build-id.
+ This is not an error however, rather it just means that
+ the debug info has probably not been loaded on the system,
+ or that another method is being used to link to the debug
+ info. */
+ free (filename);
+ return;
+ }
+
+ printf (_("%s: Found build-id indexed debug file: %s\n\n"),
+ main_filename, filename);
+
+ add_separate_debug_file (filename, handle);
+}
+
+/* Try to load a debug file pointed to by the .debug_sup section. */
+
static void
load_debug_sup_file (const char * main_filename, void * file)
{
@@ -11409,6 +11520,8 @@ check_for_and_load_links (void * file, const char * filename)
}
load_debug_sup_file (filename, file);
+
+ load_build_id_debug_file (filename, file);
}
/* Load the separate debug info file(s) attached to FILE, if any exist.
@@ -11779,7 +11892,8 @@ struct dwarf_section_display debug_displays[] =
/* Separate debug info files can containt their own .debug_str section,
and this might be in *addition* to a .debug_str section already present
in the main file. Hence we need to have two entries for .debug_str. */
- { { ".debug_str", ".zdebug_str", "", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
+ { { ".debug_str", ".zdebug_str", "", NO_ABBREVS }, display_debug_str, &do_debug_str, false },
+ { { ".note.gnu.build-id", "", "", NO_ABBREVS }, display_debug_not_supported, NULL, false },
};
/* A static assertion. */
diff --git a/binutils/dwarf.h b/binutils/dwarf.h
index dd4f4c8251..1463d2027a 100644
--- a/binutils/dwarf.h
+++ b/binutils/dwarf.h
@@ -122,6 +122,7 @@ enum dwarf_section_display_enum
gnu_debugaltlink,
debug_sup,
separate_debug_str,
+ note_gnu_build_id,
max
};
diff --git a/binutils/testsuite/binutils-all/debuginfod.exp b/binutils/testsuite/binutils-all/debuginfod.exp
index caff955db3..514fa3d5b3 100644
--- a/binutils/testsuite/binutils-all/debuginfod.exp
+++ b/binutils/testsuite/binutils-all/debuginfod.exp
@@ -161,10 +161,10 @@ proc test_fetch_debuglink { prog progargs } {
set got [binutils_run $prog "$progargs tmpdir/testprog"]
- if { [regexp ".*Found separate debug info file.*Contents\[^\n\]*loaded from\[^\n\]*$cache.*" $got] } {
+ if { [regexp ".*Found separate debug info file.*Contents\[^\n\]*loaded from\[^\n\]*" $got] } {
pass "$test ($prog debuglink)"
} else {
- fail "$test ($prog debuglink)"
+ fail "$test ($prog did not find debuglink to cache $cache)"
}
}
@@ -180,7 +180,7 @@ proc test_fetch_debugaltlink { prog progargs } {
if { [regexp ".*Found separate debug info file\[^\n\]*$cache/$buildid" $got] } {
pass "$test ($prog debugaltlink)"
} else {
- fail "$test ($prog debugaltlink)"
+ fail "$test ($prog could not load debugaltlink)"
}
}