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:
parent
0fc7642151
commit
d85bf2ba86
8 changed files with 399 additions and 140 deletions
|
@ -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>
|
2017-11-18 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR 22443
|
PR 22443
|
||||||
|
|
|
@ -45,7 +45,10 @@ output from this option can also be restricted by the use of the
|
||||||
@item k
|
@item k
|
||||||
@itemx =links
|
@itemx =links
|
||||||
Displays the contents of the @samp{.gnu_debuglink} and/or
|
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
|
@item K
|
||||||
@itemx =follow-links
|
@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
|
file and the separate debug info file contain sections with the same
|
||||||
name.
|
name.
|
||||||
|
|
||||||
When displaying other debug information, if a link is encountered to
|
In addition, when displaying DWARF attributes, if a form is found that
|
||||||
a separate debug info file, then attempt to follow the link and
|
references the separate debug info file, then the referenced contents
|
||||||
display the referenced contents.
|
will also be displayed.
|
||||||
|
|
||||||
@item l
|
@item l
|
||||||
@itemx =rawline
|
@itemx =rawline
|
||||||
|
|
314
binutils/dwarf.c
314
binutils/dwarf.c
|
@ -48,6 +48,12 @@ static debug_info *debug_information = NULL;
|
||||||
that the .debug_info section could not be loaded/parsed. */
|
that the .debug_info section could not be loaded/parsed. */
|
||||||
#define DEBUG_INFO_UNAVAILABLE (unsigned int) -1
|
#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;
|
unsigned int eh_addr_size;
|
||||||
|
|
||||||
int do_debug_info;
|
int do_debug_info;
|
||||||
|
@ -731,7 +737,7 @@ fetch_indirect_line_string (dwarf_vma offset)
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
fetch_indexed_string (dwarf_vma idx, struct cu_tu_set *this_set,
|
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 str_sec_idx = dwo ? str_dwo : str;
|
||||||
enum dwarf_section_display_enum idx_sec_idx = dwo ? str_index_dwo : str_index;
|
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");
|
printf ("DW_OP_push_object_address");
|
||||||
break;
|
break;
|
||||||
case DW_OP_call2:
|
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. */
|
this ought to be an 8-byte wide computation. */
|
||||||
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
|
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 2, end);
|
||||||
printf ("DW_OP_call2: <0x%s>",
|
printf ("DW_OP_call2: <0x%s>",
|
||||||
dwarf_vmatoa ("x", svalue + cu_offset));
|
dwarf_vmatoa ("x", svalue + cu_offset));
|
||||||
break;
|
break;
|
||||||
case DW_OP_call4:
|
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. */
|
this ought to be an 8-byte wide computation. */
|
||||||
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
|
SAFE_SIGNED_BYTE_GET_AND_INC (svalue, data, 4, end);
|
||||||
printf ("DW_OP_call4: <0x%s>",
|
printf ("DW_OP_call4: <0x%s>",
|
||||||
dwarf_vmatoa ("x", svalue + cu_offset));
|
dwarf_vmatoa ("x", svalue + cu_offset));
|
||||||
break;
|
break;
|
||||||
case DW_OP_call_ref:
|
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. */
|
this ought to be an 8-byte wide computation. */
|
||||||
if (dwarf_version == -1)
|
if (dwarf_version == -1)
|
||||||
{
|
{
|
||||||
|
@ -1452,7 +1458,7 @@ decode_location_expression (unsigned char * data,
|
||||||
break;
|
break;
|
||||||
case DW_OP_implicit_pointer:
|
case DW_OP_implicit_pointer:
|
||||||
case DW_OP_GNU_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. */
|
this ought to be an 8-byte wide computation. */
|
||||||
if (dwarf_version == -1)
|
if (dwarf_version == -1)
|
||||||
{
|
{
|
||||||
|
@ -1713,6 +1719,32 @@ fetch_alt_indirect_string (dwarf_vma offset)
|
||||||
return ret;
|
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 *
|
static unsigned char *
|
||||||
read_and_display_attr_value (unsigned long attribute,
|
read_and_display_attr_value (unsigned long attribute,
|
||||||
unsigned long form,
|
unsigned long form,
|
||||||
|
@ -2036,8 +2068,8 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
case DW_FORM_GNU_str_index:
|
case DW_FORM_GNU_str_index:
|
||||||
if (!do_loc)
|
if (!do_loc)
|
||||||
{
|
{
|
||||||
const char *suffix = strrchr (section->name, '.');
|
const char * suffix = strrchr (section->name, '.');
|
||||||
int dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? 1 : 0;
|
bfd_boolean dwo = (suffix && strcmp (suffix, ".dwo") == 0) ? TRUE : FALSE;
|
||||||
|
|
||||||
printf (_("%c(indexed string: 0x%s): %s"), delimiter,
|
printf (_("%c(indexed string: 0x%s): %s"), delimiter,
|
||||||
dwarf_vmatoa ("x", uvalue),
|
dwarf_vmatoa ("x", uvalue),
|
||||||
|
@ -2188,6 +2220,69 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2540,32 +2635,6 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
return data;
|
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 *
|
static unsigned char *
|
||||||
read_and_display_attr (unsigned long attribute,
|
read_and_display_attr (unsigned long attribute,
|
||||||
unsigned long form,
|
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
|
/* Process the contents of a .debug_info section.
|
||||||
then we are scanning for location lists and we do not want to display
|
If do_loc is TRUE then we are scanning for location lists and dwo tags
|
||||||
anything to the user. If do_types is non-zero, we are processing
|
and we do not want to display anything to the user.
|
||||||
a .debug_types section instead of a .debug_info section. */
|
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
|
static bfd_boolean
|
||||||
process_debug_info (struct dwarf_section *section,
|
process_debug_info (struct dwarf_section * section,
|
||||||
void *file,
|
void * file,
|
||||||
enum dwarf_section_display_enum abbrev_sec,
|
enum dwarf_section_display_enum abbrev_sec,
|
||||||
int do_loc,
|
bfd_boolean do_loc,
|
||||||
int do_types)
|
bfd_boolean do_types)
|
||||||
{
|
{
|
||||||
unsigned char *start = section->start;
|
unsigned char *start = section->start;
|
||||||
unsigned char *end = start + section->size;
|
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"),
|
warn (_("Reserved length value (0x%s) found in section %s\n"),
|
||||||
dwarf_vmatoa ("x", length), section->name);
|
dwarf_vmatoa ("x", length), section->name);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
section_begin += length + 4;
|
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"),
|
warn (_("Corrupt unit length (0x%s) found in section %s\n"),
|
||||||
dwarf_vmatoa ("x", length), section->name);
|
dwarf_vmatoa ("x", length), section->name);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_units == 0)
|
if (num_units == 0)
|
||||||
{
|
{
|
||||||
error (_("No comp units in %s section ?\n"), section->name);
|
error (_("No comp units in %s section ?\n"), section->name);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Then allocate an array to hold the information. */
|
/* 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"),
|
error (_("Not enough memory for a debug info array of %u entries\n"),
|
||||||
num_units);
|
num_units);
|
||||||
alloc_num_debug_info_entries = num_debug_info_entries = 0;
|
alloc_num_debug_info_entries = num_debug_info_entries = 0;
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PR 17531: file: 92ca3797.
|
/* PR 17531: file: 92ca3797.
|
||||||
We cannot rely upon the debug_information array being initialised
|
We cannot rely upon the debug_information array being initialised
|
||||||
before it is used. A corrupt file could easily contain references
|
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"),
|
warn (_("Unable to locate %s section!\n"),
|
||||||
debug_displays [abbrev_sec].section.uncompressed_name);
|
debug_displays [abbrev_sec].section.uncompressed_name);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!do_loc && dwarf_start_die == 0)
|
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)
|
if (dwarf_start_die != 0 && level < saved_level)
|
||||||
return 1;
|
return TRUE;
|
||||||
continue;
|
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"),
|
warn (_("DIE at offset 0x%lx refers to abbreviation number %lu which does not exist\n"),
|
||||||
die_offset, abbrev_number);
|
die_offset, abbrev_number);
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!do_loc && do_printing)
|
if (!do_loc && do_printing)
|
||||||
|
@ -3060,7 +3135,8 @@ process_debug_info (struct dwarf_section *section,
|
||||||
need_base_address = 0;
|
need_base_address = 0;
|
||||||
break;
|
break;
|
||||||
case DW_TAG_compile_unit:
|
case DW_TAG_compile_unit:
|
||||||
need_base_address = 1;
|
need_base_address = 1;
|
||||||
|
need_dwo_info = do_loc;
|
||||||
break;
|
break;
|
||||||
case DW_TAG_entry_point:
|
case DW_TAG_entry_point:
|
||||||
case DW_TAG_subprogram:
|
case DW_TAG_subprogram:
|
||||||
|
@ -3146,7 +3222,7 @@ process_debug_info (struct dwarf_section *section,
|
||||||
if (!do_loc)
|
if (!do_loc)
|
||||||
printf ("\n");
|
printf ("\n");
|
||||||
|
|
||||||
return 1;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Locate and scan the .debug_info section in the file and record the pointer
|
/* 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);
|
(void) load_cu_tu_indexes (file);
|
||||||
|
|
||||||
if (load_debug_section_with_follow (info, 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;
|
return num_debug_info_entries;
|
||||||
|
|
||||||
if (load_debug_section_with_follow (info_dwo, file)
|
if (load_debug_section_with_follow (info_dwo, file)
|
||||||
&& process_debug_info (&debug_displays [info_dwo].section, file,
|
&& process_debug_info (&debug_displays [info_dwo].section, file,
|
||||||
abbrev_dwo, 1, 0))
|
abbrev_dwo, TRUE, FALSE))
|
||||||
return num_debug_info_entries;
|
return num_debug_info_entries;
|
||||||
|
|
||||||
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
|
num_debug_info_entries = DEBUG_INFO_UNAVAILABLE;
|
||||||
|
@ -6161,19 +6237,19 @@ display_debug_str (struct dwarf_section *section,
|
||||||
static int
|
static int
|
||||||
display_debug_info (struct dwarf_section *section, void *file)
|
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
|
static int
|
||||||
display_debug_types (struct dwarf_section *section, void *file)
|
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
|
static int
|
||||||
display_trace_info (struct dwarf_section *section, void *file)
|
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
|
static int
|
||||||
|
@ -7227,6 +7303,30 @@ read_cie (unsigned char *start, unsigned char *end,
|
||||||
return start;
|
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.
|
/* Prints out the contents on the augmentation data array.
|
||||||
If do_wide is not enabled, then formats the output to fit into 80 columns. */
|
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;
|
bfd_size_type i;
|
||||||
|
|
||||||
i = printf (_(" Augmentation data: "));
|
i = printf (_(" Augmentation data: "));
|
||||||
|
display_data (i, data, len);
|
||||||
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');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -8550,8 +8637,8 @@ display_debug_names (struct dwarf_section *section, void *file)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_debug_links (struct dwarf_section * section,
|
display_debug_links (struct dwarf_section * section,
|
||||||
void * file ATTRIBUTE_UNUSED)
|
void * file ATTRIBUTE_UNUSED)
|
||||||
{
|
{
|
||||||
const unsigned char * filename;
|
const unsigned char * filename;
|
||||||
unsigned int filelen;
|
unsigned int filelen;
|
||||||
|
@ -8615,19 +8702,7 @@ display_debug_links (struct dwarf_section * section,
|
||||||
}
|
}
|
||||||
|
|
||||||
printed = printf (_(" Build-ID (%#lx bytes):"), (long) build_id_len);
|
printed = printf (_(" Build-ID (%#lx bytes):"), (long) build_id_len);
|
||||||
|
display_data (printed, build_id, 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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9723,21 +9798,84 @@ load_separate_debug_info (const char * main_filename,
|
||||||
return separate_debug_file;
|
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.
|
/* Load a separate debug info file, if it exists.
|
||||||
Returns the data pointer that is the result of calling open_debug_file
|
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 *
|
void *
|
||||||
load_separate_debug_file (void * file, const char * filename)
|
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)
|
if (! do_follow_links)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* FIXME: We do not check for the presence of both link sections in the same file. */
|
/* 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 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 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))
|
if (load_debug_section (gnu_debugaltlink, file))
|
||||||
{
|
{
|
||||||
Build_id_data * build_id_data;
|
Build_id_data * build_id_data;
|
||||||
|
|
|
@ -6084,7 +6084,7 @@ process_section_headers (Filedata * filedata)
|
||||||
|| do_debug_lines || do_debug_pubnames || do_debug_pubtypes
|
|| do_debug_lines || do_debug_pubnames || do_debug_pubtypes
|
||||||
|| do_debug_aranges || do_debug_frames || do_debug_macinfo
|
|| do_debug_aranges || do_debug_frames || do_debug_macinfo
|
||||||
|| do_debug_str || do_debug_loc || do_debug_ranges
|
|| 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, ".debug_")
|
||||||
|| const_strneq (name, ".zdebug_")))
|
|| 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. */
|
/* See if we know how to display the contents of this section. */
|
||||||
for (i = 0; i < max; i++)
|
for (i = 0; i < max; i++)
|
||||||
if (streq (debug_displays[i].section.uncompressed_name, name)
|
{
|
||||||
|| (i == line && const_strneq (name, ".debug_line."))
|
enum dwarf_section_display_enum id = (enum dwarf_section_display_enum) i;
|
||||||
|| streq (debug_displays[i].section.compressed_name, name))
|
struct dwarf_section_display * display = debug_displays + i;
|
||||||
{
|
struct dwarf_section * sec = & display->section;
|
||||||
struct dwarf_section * sec = &debug_displays [i].section;
|
|
||||||
int secondary = (section != find_section (filedata, name));
|
|
||||||
|
|
||||||
if (secondary)
|
if (streq (sec->uncompressed_name, name)
|
||||||
free_debug_section ((enum dwarf_section_display_enum) i);
|
|| (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."))
|
if (secondary)
|
||||||
sec->name = name;
|
free_debug_section (id);
|
||||||
else if (streq (sec->uncompressed_name, name))
|
|
||||||
sec->name = sec->uncompressed_name;
|
|
||||||
else
|
|
||||||
sec->name = sec->compressed_name;
|
|
||||||
|
|
||||||
if (load_specific_debug_section ((enum dwarf_section_display_enum) i,
|
if (i == line && const_strneq (name, ".debug_line."))
|
||||||
section, filedata))
|
sec->name = name;
|
||||||
{
|
else if (streq (sec->uncompressed_name, name))
|
||||||
/* If this debug section is part of a CU/TU set in a .dwp file,
|
sec->name = sec->uncompressed_name;
|
||||||
restrict load_debug_section to the sections in that set. */
|
else
|
||||||
section_subset = find_cu_tu_set (filedata, shndx);
|
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))
|
section_subset = NULL;
|
||||||
free_debug_section ((enum dwarf_section_display_enum) i);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
if (secondary || (id != info && id != abbrev))
|
||||||
}
|
free_debug_section (id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (i == max)
|
if (i == max)
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
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
|
.section .gnu_debuglink,"",%progbits
|
||||||
.asciz "this_is_a_debuglink.debug"
|
.asciz "this_is_a_debuglink.debug"
|
||||||
.balign 4
|
.balign 4
|
||||||
.4byte 0x12345678
|
.4byte 0x12345678
|
||||||
|
|
||||||
/* Create a fake .gnu_debugaltlink section. */
|
/* Create a fake .gnu_debugaltlink section. */
|
||||||
|
|
||||||
.section .gnu_debugaltlink,"",%progbits
|
.section .gnu_debugaltlink,"",%progbits
|
||||||
.asciz "linkdebug.debug"
|
.asciz "linkdebug.debug"
|
||||||
|
@ -32,9 +32,9 @@
|
||||||
.dc.b 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
|
.dc.b 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
|
||||||
.dc.b 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
|
.dc.b 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef
|
||||||
|
|
||||||
/* Create a .debug_str section for local use. This is also to check
|
/* 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
|
the ability to dump the same section twice, if it exists in
|
||||||
both the main file and the separate debug info file. */
|
both the main file and the separate debug info file. */
|
||||||
|
|
||||||
.section .debug_str,"MS",%progbits,1
|
.section .debug_str,"MS",%progbits,1
|
||||||
string1:
|
string1:
|
||||||
|
@ -43,9 +43,9 @@ string1:
|
||||||
.balign 2
|
.balign 2
|
||||||
string_end:
|
string_end:
|
||||||
|
|
||||||
/* Create a .debug_info section that contains strings references into the
|
/* Create a .debug_info section that contains string references into
|
||||||
separate debug info file. Plus the abbreviations are stored in the
|
the separate debug info file. Plus the abbreviations are stored
|
||||||
separate file too... */
|
in the separate file too... */
|
||||||
|
|
||||||
.section .debug_info,"",%progbits
|
.section .debug_info,"",%progbits
|
||||||
.4byte debugE - debugS ;# Length of Compilation Unit Info
|
.4byte debugE - debugS ;# Length of Compilation Unit Info
|
||||||
|
|
84
binutils/testsuite/binutils-all/dwo.s
Normal file
84
binutils/testsuite/binutils-all/dwo.s
Normal 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
|
||||||
|
|
|
@ -469,7 +469,7 @@ if {![binutils_assemble_flags $srcdir/$subdir/dwarf-attributes.S tmpdir/dwarf-at
|
||||||
|
|
||||||
# Check that debug link sections can be dumped.
|
# Check that debug link sections can be dumped.
|
||||||
if {![binutils_assemble $srcdir/$subdir/debuglink.s tmpdir/debuglink.o]} then {
|
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 {
|
} else {
|
||||||
if ![is_remote host] {
|
if ![is_remote host] {
|
||||||
set tempfile tmpdir/debuglink.o
|
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 {}
|
readelf_test {--debug-dump=links} $tempfile readelf.k {}
|
||||||
}
|
|
||||||
|
|
||||||
# Check that debug link sections can be followed.
|
# 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 {
|
|
||||||
if {![binutils_assemble $srcdir/$subdir/linkdebug.s tmpdir/linkdebug.debug]} then {
|
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 {
|
} else {
|
||||||
if ![is_remote host] {
|
if [is_remote host] {
|
||||||
set tempfile tmpdir/debuglink.o
|
set tempfile2 [remote_download host tmpdir/linkdebug.debug]
|
||||||
} else {
|
|
||||||
set tempfile [remote_download host tmpdir/linkdebug.debug]
|
|
||||||
set tempfile [remote_download host tmpdir/debuglink.o]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
readelf_test {-wKis} $tempfile objdump.WK2 {}
|
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 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
4
binutils/testsuite/binutils-all/readelf.k2
Normal file
4
binutils/testsuite/binutils-all/readelf.k2
Normal 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)
|
Loading…
Add table
Add a link
Reference in a new issue