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:
Nick Clifton 2021-12-16 14:05:40 +00:00
parent a2b1ea81ba
commit 61ab1364c7
4 changed files with 131 additions and 4 deletions

View File

@ -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

View File

@ -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. */

View File

@ -122,6 +122,7 @@ enum dwarf_section_display_enum
gnu_debugaltlink,
debug_sup,
separate_debug_str,
note_gnu_build_id,
max
};

View File

@ -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)"
}
}