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.
This commit is contained in:
parent
a2b1ea81ba
commit
61ab1364c7
@ -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
|
||||
|
114
binutils/dwarf.c
114
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.
|
||||
@ -11780,6 +11893,7 @@ struct dwarf_section_display debug_displays[] =
|
||||
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 },
|
||||
{ { ".note.gnu.build-id", "", "", NO_ABBREVS }, display_debug_not_supported, NULL, false },
|
||||
};
|
||||
|
||||
/* A static assertion. */
|
||||
|
@ -122,6 +122,7 @@ enum dwarf_section_display_enum
|
||||
gnu_debugaltlink,
|
||||
debug_sup,
|
||||
separate_debug_str,
|
||||
note_gnu_build_id,
|
||||
max
|
||||
};
|
||||
|
||||
|
@ -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)"
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user