diff options
Diffstat (limited to 'binutils/dwarf.c')
-rw-r--r-- | binutils/dwarf.c | 116 |
1 files changed, 115 insertions, 1 deletions
diff --git a/binutils/dwarf.c b/binutils/dwarf.c index eeef98d4a18..12c5b0a8fa2 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. */ |