Add ability to follow dwo links to readelf/objdump.

* dwarf.c (dwo_name, dwo_dir, dwo_id, dwo_id_len): New variables.
	(read_and_display_attr_value): Record dwo variables if requested.
	(display_augmentation_data): Rename to display_data and make
	generic.
	(load_dwo_file): New function.  Loads a separate dwarf object
	file.
	(load_separate_debug_file): Add reporting and loading of separate
	dwarf objet files.
	* readelf.c (process_section_headers): Add do_debug_links to list
	of flags requiring a debug dump.
	(display_debug_section): Tidy up code.
	* doc/debug.options.texi: Add note that dwo links will also be
	followed.
	* testsuite/binutils-all/debuglink.s: Tidy code.
	* testsuite/binutils-all/dwo.s: New test file.
	* testsuite/binutils-all/readelf.wk2: New file - expected output
	from readelf.
	* testsuite/binutils-all/readelf.exp: Run the new test.
This commit is contained in:
Nick Clifton 2017-11-21 13:12:04 +00:00
parent 0fc7642151
commit d85bf2ba86
8 changed files with 399 additions and 140 deletions

View File

@ -1,3 +1,24 @@
2017-11-21 Nick Clifton <nickc@redhat.com>
* dwarf.c (dwo_name, dwo_dir, dwo_id, dwo_id_len): New variables.
(read_and_display_attr_value): Record dwo variables if requested.
(display_augmentation_data): Rename to display_data and make
generic.
(load_dwo_file): New function. Loads a separate dwarf object
file.
(load_separate_debug_file): Add reporting and loading of separate
dwarf objet files.
* readelf.c (process_section_headers): Add do_debug_links to list
of flags requiring a debug dump.
(display_debug_section): Tidy up code.
* doc/debug.options.texi: Add note that dwo links will also be
followed.
* testsuite/binutils-all/debuglink.s: Tidy code.
* testsuite/binutils-all/dwo.s: New test file.
* testsuite/binutils-all/readelf.wk2: New file - expected output
from readelf.
* testsuite/binutils-all/readelf.exp: Run the new test.
2017-11-18 Alan Modra <amodra@gmail.com>
PR 22443

View File

@ -45,7 +45,10 @@ output from this option can also be restricted by the use of the
@item k
@itemx =links
Displays the contents of the @samp{.gnu_debuglink} and/or
@samp{.gnu_debugaltlink} sections.
@samp{.gnu_debugaltlink} sections. Also displays the link to a
separate dwarf object file (dwo), if one is specified by the
DW_AT_GNU_dwo_name or DW_AT_dwo_name attributes in the
@samp{.debug_info} section.
@item K
@itemx =follow-links
@ -55,9 +58,9 @@ versions of the same debug section being displayed if both the main
file and the separate debug info file contain sections with the same
name.
When displaying other debug information, if a link is encountered to
a separate debug info file, then attempt to follow the link and
display the referenced contents.
In addition, when displaying DWARF attributes, if a form is found that
references the separate debug info file, then the referenced contents
will also be displayed.
@item l
@itemx =rawline

View File

@ -48,6 +48,12 @@ static debug_info *debug_information = NULL;
that the .debug_info section could not be loaded/parsed. */
#define DEBUG_INFO_UNAVAILABLE (unsigned int) -1
static const char * dwo_name;
static const char * dwo_dir;
static const unsigned char * dwo_id;
static bfd_size_type dwo_id_len;
static bfd_boolean need_dwo_info;
unsigned int eh_addr_size;
int do_debug_info;
@ -731,7 +737,7 @@ fetch_indirect_line_string (dwarf_vma offset)
static const char *
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
dwarf_vma offset_size, int dwo)
dwarf_vma offset_size, bfd_boolean dwo)
{
enum dwarf_section_display_enum str_sec_idx = dwo ? str_dwo : str;
enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
@ -1369,21 +1375,21 @@ decode_location_expression (unsigned char * data,
printf ("DW_OP_push_object_address");
break;
case DW_OP_call2:
/* XXX: Strictly speaking for 64-bit DWARF3 files
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
printf ("DW_OP_call2: <0x%s>",
dwarf_vmatoa ("x", svalue + cu_offset));
break;
case DW_OP_call4:
/* XXX: Strictly speaking for 64-bit DWARF3 files
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
printf ("DW_OP_call4: <0x%s>",
dwarf_vmatoa ("x", svalue + cu_offset));
break;
case DW_OP_call_ref:
/* XXX: Strictly speaking for 64-bit DWARF3 files
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
if (dwarf_version == -1)
{
@ -1452,7 +1458,7 @@ decode_location_expression (unsigned char * data,
break;
case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
/* XXX: Strictly speaking for 64-bit DWARF3 files
/* FIXME: Strictly speaking for 64-bit DWARF3 files
this ought to be an 8-byte wide computation. */
if (dwarf_version == -1)
{
@ -1713,6 +1719,32 @@ fetch_alt_indirect_string (dwarf_vma offset)
return ret;
}
static const char *
get_AT_name (unsigned long attribute)
{
const char *name;
if (attribute == 0)
return "DW_AT value: 0";
/* One value is shared by the MIPS and HP extensions: */
if (attribute == DW_AT_MIPS_fde)
return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
name = get_DW_AT_name (attribute);
if (name == NULL)
{
static char buffer[100];
snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
attribute);
return buffer;
}
return name;
}
static unsigned char *
read_and_display_attr_value (unsigned long attribute,
unsigned long form,
@ -2036,8 +2068,8 @@ read_and_display_attr_value (unsigned long attribute,
case DW_FORM_GNU_str_index:
if (!do_loc)
{
const char *suffix = strrchr (section->name, '.');
int dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? 1 : 0;
const char * suffix = strrchr (section->name, '.');
bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
printf (_("%c(indexed string: 0x%s): %s"), delimiter,
dwarf_vmatoa ("x", uvalue),
@ -2188,6 +2220,69 @@ read_and_display_attr_value (unsigned long attribute,
}
break;
case DW_AT_GNU_dwo_name:
case DW_AT_dwo_name:
if (need_dwo_info)
switch (form)
{
case DW_FORM_strp:
dwo_name = (const char *) fetch_indirect_string (uvalue);
break;
case DW_FORM_GNU_str_index:
dwo_name = fetch_indexed_string (uvalue, this_set, offset_size, FALSE);
break;
case DW_FORM_string:
dwo_name = (const char *) orig_data;
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
get_FORM_name (form), get_AT_name (attribute));
dwo_name = _("<unknown>");
break;
}
break;
case DW_AT_comp_dir:
/* FIXME: Also extract a build-id in a CU/TU. */
if (need_dwo_info)
switch (form)
{
case DW_FORM_strp:
dwo_dir = (const char *) fetch_indirect_string (uvalue);
break;
case DW_FORM_line_strp:
dwo_dir = (const char *) fetch_indirect_line_string (uvalue);
break;
case DW_FORM_GNU_str_index:
dwo_dir = fetch_indexed_string (uvalue, this_set, offset_size, FALSE);
break;
case DW_FORM_string:
dwo_dir = (const char *) orig_data;
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
get_FORM_name (form), get_AT_name (attribute));
dwo_dir = _("<unknown>");
break;
}
break;
case DW_AT_GNU_dwo_id:
if (need_dwo_info)
switch (form)
{
case DW_FORM_data8:
dwo_id = data - 8;
dwo_id_len = 8;
break;
default:
warn (_("Unsupported form (%s) for attribute %s\n"),
get_FORM_name (form), get_AT_name (attribute));
dwo_id = NULL;
break;
}
break;
default:
break;
}
@ -2540,32 +2635,6 @@ read_and_display_attr_value (unsigned long attribute,
return data;
}
static const char *
get_AT_name (unsigned long attribute)
{
const char *name;
if (attribute == 0)
return "DW_AT value: 0";
/* One value is shared by the MIPS and HP extensions: */
if (attribute == DW_AT_MIPS_fde)
return "DW_AT_MIPS_fde or DW_AT_HP_unmodifiable";
name = get_DW_AT_name (attribute);
if (name == NULL)
{
static char buffer[100];
snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
attribute);
return buffer;
}
return name;
}
static unsigned char *
read_and_display_attr (unsigned long attribute,
unsigned long form,
@ -2642,17 +2711,22 @@ introduce (struct dwarf_section * section, bfd_boolean raw)
}
}
/* Process the contents of a .debug_info section. If do_loc is non-zero
then we are scanning for location lists and we do not want to display
anything to the user. If do_types is non-zero, we are processing
a .debug_types section instead of a .debug_info section. */
/* Process the contents of a .debug_info section.
If do_loc is TRUE then we are scanning for location lists and dwo tags
and we do not want to display anything to the user.
If do_types is TRUE, we are processing a .debug_types section instead of
a .debug_info section.
The information displayed is restricted by the values in DWARF_START_DIE
and DWARF_CUTOFF_LEVEL.
Returns TRUE upon success. Otherwise an error or warning message is
printed and FALSE is returned. */
static int
process_debug_info (struct dwarf_section *section,
void *file,
enum dwarf_section_display_enum abbrev_sec,
int do_loc,
int do_types)
static bfd_boolean
process_debug_info (struct dwarf_section * section,
void * file,
enum dwarf_section_display_enum abbrev_sec,
bfd_boolean do_loc,
bfd_boolean do_types)
{
unsigned char *start = section->start;
unsigned char *end = start + section->size;
@ -2684,7 +2758,7 @@ process_debug_info (struct dwarf_section *section,
{
warn (_("Reserved length value (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
return 0;
return FALSE;
}
else
section_begin += length + 4;
@ -2696,14 +2770,14 @@ process_debug_info (struct dwarf_section *section,
{
warn (_("Corrupt unit length (0x%s) found in section %s\n"),
dwarf_vmatoa ("x", length), section->name);
return 0;
return FALSE;
}
}
if (num_units == 0)
{
error (_("No comp units in %s section ?\n"), section->name);
return 0;
return FALSE;
}
/* Then allocate an array to hold the information. */
@ -2714,8 +2788,9 @@ process_debug_info (struct dwarf_section *section,
error (_("Not enough memory for a debug info array of %u entries\n"),
num_units);
alloc_num_debug_info_entries = num_debug_info_entries = 0;
return 0;
return FALSE;
}
/* PR 17531: file: 92ca3797.
We cannot rely upon the debug_information array being initialised
before it is used. A corrupt file could easily contain references
@ -2741,7 +2816,7 @@ process_debug_info (struct dwarf_section *section,
{
warn (_("Unable to locate %s section!\n"),
debug_displays [abbrev_sec].section.uncompressed_name);
return 0;
return FALSE;
}
if (!do_loc && dwarf_start_die == 0)
@ -3008,7 +3083,7 @@ process_debug_info (struct dwarf_section *section,
}
}
if (dwarf_start_die != 0 && level < saved_level)
return 1;
return TRUE;
continue;
}
@ -3048,7 +3123,7 @@ process_debug_info (struct dwarf_section *section,
}
warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
die_offset, abbrev_number);
return 0;
return FALSE;
}
if (!do_loc && do_printing)
@ -3060,7 +3135,8 @@ process_debug_info (struct dwarf_section *section,
need_base_address = 0;
break;
case DW_TAG_compile_unit:
need_base_address = 1;
need_base_address = 1;
need_dwo_info = do_loc;
break;
case DW_TAG_entry_point:
case DW_TAG_subprogram:
@ -3146,7 +3222,7 @@ process_debug_info (struct dwarf_section *section,
if (!do_loc)
printf ("\n");
return 1;
return TRUE;
}
/* Locate and scan the .debug_info section in the file and record the pointer
@ -3171,12 +3247,12 @@ load_debug_info (void * file)
(void) load_cu_tu_indexes (file);
if (load_debug_section_with_follow (info, file)
&& process_debug_info (&debug_displays [info].section, file, abbrev, 1, 0))
&& process_debug_info (&debug_displays [info].section, file, abbrev, TRUE, FALSE))
return num_debug_info_entries;
if (load_debug_section_with_follow (info_dwo, file)
&& process_debug_info (&debug_displays [info_dwo].section, file,
abbrev_dwo, 1, 0))
abbrev_dwo, TRUE, FALSE))
return num_debug_info_entries;
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
@ -6161,19 +6237,19 @@ display_debug_str (struct dwarf_section *section,
static int
display_debug_info (struct dwarf_section *section, void *file)
{
return process_debug_info (section, file, section->abbrev_sec, 0, 0);
return process_debug_info (section, file, section->abbrev_sec, FALSE, FALSE);
}
static int
display_debug_types (struct dwarf_section *section, void *file)
{
return process_debug_info (section, file, section->abbrev_sec, 0, 1);
return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
}
static int
display_trace_info (struct dwarf_section *section, void *file)
{
return process_debug_info (section, file, section->abbrev_sec, 0, 0);
return process_debug_info (section, file, section->abbrev_sec, FALSE, TRUE);
}
static int
@ -7227,6 +7303,30 @@ read_cie (unsigned char *start, unsigned char *end,
return start;
}
/* Prints out the contents on the DATA array formatted as unsigned bytes.
If do_wide is not enabled, then formats the output to fit into 80 columns.
PRINTED contains the number of characters already written to the current
output line. */
static void
display_data (bfd_size_type printed,
const unsigned char * data,
const bfd_size_type len)
{
if (do_wide || len < ((80 - printed) / 3))
for (printed = 0; printed < len; ++printed)
printf (" %02x", data[printed]);
else
{
for (printed = 0; printed < len; ++printed)
{
if (printed % (80 / 3) == 0)
putchar ('\n');
printf (" %02x", data[printed]);
}
}
}
/* Prints out the contents on the augmentation data array.
If do_wide is not enabled, then formats the output to fit into 80 columns. */
@ -7236,20 +7336,7 @@ display_augmentation_data (const unsigned char * data, const bfd_size_type len)
bfd_size_type i;
i = printf (_(" Augmentation data: "));
if (do_wide || len < ((80 - i) / 3))
for (i = 0; i < len; ++i)
printf (" %02x", data[i]);
else
{
for (i = 0; i < len; ++i)
{
if (i % (80 / 3) == 0)
putchar ('\n');
printf (" %02x", data[i]);
}
}
putchar ('\n');
display_data (i, data, len);
}
static int
@ -8550,8 +8637,8 @@ display_debug_names (struct dwarf_section *section, void *file)
}
static int
display_debug_links (struct dwarf_section * section,
void * file ATTRIBUTE_UNUSED)
display_debug_links (struct dwarf_section * section,
void * file ATTRIBUTE_UNUSED)
{
const unsigned char * filename;
unsigned int filelen;
@ -8615,19 +8702,7 @@ display_debug_links (struct dwarf_section * section,
}
printed = printf (_(" Build-ID (%#lx bytes):"), (long) build_id_len);
if (do_wide || build_id_len < ((80 - printed) / 3))
for (printed = 0; printed < build_id_len; ++printed)
printf (" %02x", build_id[printed]);
else
{
for (printed = 0; printed < build_id_len; ++printed)
{
if (printed % (80 / 3) == 0)
putchar ('\n');
printf (" %02x", build_id[printed]);
}
}
display_data (printed, build_id, build_id_len);
putchar ('\n');
}
@ -9723,21 +9798,84 @@ load_separate_debug_info (const char * main_filename,
return separate_debug_file;
}
/* Attempt to load a separate dwarf object file. */
static void *
load_dwo_file (const char * main_filename)
{
char * filename;
/* FIXME: Skip adding / if dwo_dir ends in /. */
filename = concat (dwo_dir, "/", dwo_name, NULL);
if (filename == NULL)
{
warn (_("Out of memory allocating dwo filename\n"));
return NULL;
}
if ((separate_debug_file = open_debug_file (filename)) == NULL)
{
warn (_("Unable to load dwo file: %s\n"), filename);
free (filename);
return NULL;
}
/* FIXME: We should check the dwo_id. */
printf (_("%s: Found separate debug object file: %s\n\n"), main_filename, filename);
separate_debug_filename = filename;
return separate_debug_file;
}
/* Load a separate debug info file, if it exists.
Returns the data pointer that is the result of calling open_debug_file
on the separate debug info file. */
on the separate debug info file, or NULL if there were problems or there
is no such file. */
void *
load_separate_debug_file (void * file, const char * filename)
{
/* See if there is a dwo link. */
if (load_debug_section (str, file)
&& load_debug_section (abbrev, file)
&& load_debug_section (info, file))
{
dwo_name = dwo_dir = NULL;
dwo_id = NULL;
dwo_id_len = 0;
if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE))
{
if (dwo_name != NULL)
{
if (do_debug_links)
{
printf (_("The %s section contains a link to a dwo file:\n"),
debug_displays [info].section.uncompressed_name);
printf (_(" Name: %s\n"), dwo_name);
printf (_(" Directory: %s\n"), dwo_dir ? dwo_dir : _("<not-found>"));
if (dwo_id != NULL)
display_data (printf (_(" ID: ")), dwo_id, dwo_id_len);
else
printf (_(" ID: <unknown>\n"));
printf ("\n\n");
}
/* FIXME: We do not check to see if there are any more dwo links in the file... */
if (do_follow_links)
return load_dwo_file (filename);
}
}
}
if (! do_follow_links)
return NULL;
/* FIXME: We do not check for the presence of both link sections in the same file. */
/* FIXME: We do not check the separate debug info file to see if it too contains debuglinks. */
/* FIXME: We do not check for the presence of multiple, same-name debuglink sections. */
/* FIXME: We do not check for the presence of a dwo link as well as a debuglink. */
/* We try the alt version first as that is blessed by the DWARF5 standard. */
if (load_debug_section (gnu_debugaltlink, file))
{
Build_id_data * build_id_data;

View File

@ -6084,7 +6084,7 @@ process_section_headers (Filedata * filedata)
|| do_debug_lines || do_debug_pubnames || do_debug_pubtypes
|| do_debug_aranges || do_debug_frames || do_debug_macinfo
|| do_debug_str || do_debug_loc || do_debug_ranges
|| do_debug_addr || do_debug_cu_index)
|| do_debug_addr || do_debug_cu_index || do_debug_links)
&& (const_strneq (name, ".debug_")
|| const_strneq (name, ".zdebug_")))
{
@ -13658,40 +13658,43 @@ display_debug_section (int shndx, Elf_Internal_Shdr * section, Filedata * fileda
/* See if we know how to display the contents of this section. */
for (i = 0; i < max; i++)
if (streq (debug_displays[i].section.uncompressed_name, name)
|| (i == line && const_strneq (name, ".debug_line."))
|| streq (debug_displays[i].section.compressed_name, name))
{
struct dwarf_section * sec = &debug_displays [i].section;
int secondary = (section != find_section (filedata, name));
{
enum dwarf_section_display_enum id = (enum dwarf_section_display_enum) i;
struct dwarf_section_display * display = debug_displays + i;
struct dwarf_section * sec = & display->section;
if (secondary)
free_debug_section ((enum dwarf_section_display_enum) i);
if (streq (sec->uncompressed_name, name)
|| (id == line && const_strneq (name, ".debug_line."))
|| streq (sec->compressed_name, name))
{
bfd_boolean secondary = (section != find_section (filedata, name));
if (i == line && const_strneq (name, ".debug_line."))
sec->name = name;
else if (streq (sec->uncompressed_name, name))
sec->name = sec->uncompressed_name;
else
sec->name = sec->compressed_name;
if (secondary)
free_debug_section (id);
if (load_specific_debug_section ((enum dwarf_section_display_enum) i,
section, filedata))
{
/* If this debug section is part of a CU/TU set in a .dwp file,
restrict load_debug_section to the sections in that set. */
section_subset = find_cu_tu_set (filedata, shndx);
if (i == line && const_strneq (name, ".debug_line."))
sec->name = name;
else if (streq (sec->uncompressed_name, name))
sec->name = sec->uncompressed_name;
else
sec->name = sec->compressed_name;
result &= debug_displays[i].display (sec, filedata);
if (load_specific_debug_section (id, section, filedata))
{
/* If this debug section is part of a CU/TU set in a .dwp file,
restrict load_debug_section to the sections in that set. */
section_subset = find_cu_tu_set (filedata, shndx);
section_subset = NULL;
result &= display->display (sec, filedata);
if (secondary || (i != info && i != abbrev))
free_debug_section ((enum dwarf_section_display_enum) i);
}
section_subset = NULL;
break;
}
if (secondary || (id != info && id != abbrev))
free_debug_section (id);
}
break;
}
}
if (i == max)
{

View File

@ -17,14 +17,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Create a fake .gnu_debuglink section. */
/* Create a fake .gnu_debuglink section. */
.section .gnu_debuglink,"",%progbits
.asciz "this_is_a_debuglink.debug"
.balign 4
.4byte 0x12345678
/* Create a fake .gnu_debugaltlink section. */
/* Create a fake .gnu_debugaltlink section. */
.section .gnu_debugaltlink,"",%progbits
.asciz "linkdebug.debug"
@ -32,9 +32,9 @@
.dc.b 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
.dc.b 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
/* Create a .debug_str section for local use. This is also to check
the ability to dump the same section twice, if it exists in
both the main file and the separate debug info file. */
/* Create a .debug_str section for local use. This is also to check
the ability to dump the same section twice, if it exists in
both the main file and the separate debug info file. */
.section .debug_str,"MS",%progbits,1
string1:
@ -43,9 +43,9 @@ string1:
.balign 2
string_end:
/* Create a .debug_info section that contains strings references into the
separate debug info file. Plus the abbreviations are stored in the
separate file too... */
/* Create a .debug_info section that contains string references into
the separate debug info file. Plus the abbreviations are stored
in the separate file too... */
.section .debug_info,"",%progbits
.4byte debugE - debugS ;# Length of Compilation Unit Info

View File

@ -0,0 +1,84 @@
/* Assembler source used to create an object file for testing readelf's
and objdump's ability to process separate dwarf object files.
Copyright (C) 2017 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Create a .debug_str section for local use. This is also to check
the ability to dump the same section twice, if it exists in
both the main file and the separate debug info file. */
.section .debug_str,"MS",%progbits,1
string1:
.asciz "debugfile.dwo"
string2:
.asciz "/path/to/dwo/files"
string3:
.asciz "/another/path/"
.balign 2
string_end:
/* Create a .debug_info section that contains the dwo links. */
.section .debug_info,"",%progbits
.4byte debugE - debugS ;# Length of Compilation Unit Info
debugS:
.short 0x4 ;# DWARF version number.
.4byte 0x0 ;# Offset into .debug_abbrev section.
.byte 0x4 ;# Pointer Size (in bytes).
.uleb128 0x1 ;# Use abbrev #1. This needs strings from the .debug_str section.
.4byte string1
.4byte string2
.uleb128 0x2 ;# Use abbrev #2.
.asciz "file.dwo"
.4byte string3
.8byte 0x12345678aabbccdd
;# Minimal section alignment on alpha-* is 2, so ensure no new invalid CU
;# will be started.
.balign 2, 0
debugE:
.section .debug_abbrev,"",%progbits
/* Create an abbrev containing a DWARF5 style dwo link. */
.uleb128 0x01 ;# Abbrev code.
.uleb128 0x11 ;# DW_TAG_compile_unit
.byte 0x00 ;# DW_children_no
.uleb128 0x76 ;# DW_AT_dwo_name
.uleb128 0x0e ;# DW_FORM_strp
.uleb128 0x1b ;# DW_AT_comp_dir
.uleb128 0x0e ;# DW_FORM_strp
.byte 0x00 ;# End of abbrev
.byte 0x00
/* Create an abbrev containing a GNU style dwo link. */
.uleb128 0x02 ;# Abbrev code.
.uleb128 0x11 ;# DW_TAG_compile_unit
.byte 0x00 ;# DW_children_no
.uleb128 0x2130 ;# DW_AT_GNU_dwo_name
.uleb128 0x08 ;# DW_FORM_string
.uleb128 0x1b ;# DW_AT_comp_dir
.uleb128 0x0e ;# DW_FORM_strp
.uleb128 0x2131 ;# DW_AT_GNU_dwo_id
.uleb128 0x07 ;# DW_FORM_data8
.byte 0x00 ;# End of abbrev
.byte 0x00
.byte 0x0 ;# Abbrevs terminator

View File

@ -469,7 +469,7 @@ if {![binutils_assemble_flags $srcdir/$subdir/dwarf-attributes.S tmpdir/dwarf-at
# Check that debug link sections can be dumped.
if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
unresolved "readelf --debug-dump=links (failed to assemble)"
unresolved "readelf --debug-dump=links (failed to assemble debuglink.s)"
} else {
if ![is_remote host] {
set tempfile tmpdir/debuglink.o
@ -478,23 +478,29 @@ if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
}
readelf_test {--debug-dump=links} $tempfile readelf.k {}
}
# Check that debug link sections can be followed.
if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
unresolved "readelf --debug-dump=follow-links (failed to assemble1)"
} else {
# Check that debug link sections can be followed.
if {![binutils_assemble $srcdir/$subdir/linkdebug.s tmpdir/linkdebug.debug]} then {
unresolved "readelf --debug-dump=follow-links (failed to assemble2)"
unresolved "readelf --debug-dump=follow-links (failed to assemble linkdebug.s)"
} else {
if ![is_remote host] {
set tempfile tmpdir/debuglink.o
} else {
set tempfile [remote_download host tmpdir/linkdebug.debug]
set tempfile [remote_download host tmpdir/debuglink.o]
if [is_remote host] {
set tempfile2 [remote_download host tmpdir/linkdebug.debug]
}
readelf_test {-wKis} $tempfile objdump.WK2 {}
}
}
if {![binutils_assemble $srcdir/$subdir/dwo.s tmpdir/dwo.o]} then {
unresolved "readelf --debug-dump=links (failed to assemble dwo.s)"
} else {
if ![is_remote host] {
set tempfile tmpdir/dwo.o
} else {
set tempfile [remote_download host tmpdir/dwo.o]
}
readelf_test {--debug-dump=links} $tempfile readelf.k2 {}
}

View File

@ -0,0 +1,4 @@
The \.debug_info section contains a link to a dwo file:
Name: file\.dwo
Directory: /another/path/
ID: (12|dd) (34|cc) (56|bb) (78|aa) (78|aa) (56|bb) (34|cc) (12|dd)