Fix readelf's and objdump's dislplay of DWO links when multiple links are present.
PR 26829 * dwarf.c (struct dwo_info): Add cu_offset field. (add_dwo_info): Add cu_offset parameter. Record in new dwo_info struct. (add_dwo_name): Add cu_offset field. (add_dwo_dir): Add cu_offset field. (add_dwo_id): Add cu_offset field. (read_and_display_attr_value): Pass cu_offset to dwo recording functions. (load_separate_debug_files): Accumulate name, dir and id values and display once for each CU. * testsuite/binutils-all/dwo.sL Use a separate CU for the second dwo link. * testsuite/binutils-all/readelf.k2: Update expected output.
This commit is contained in:
parent
5a7cf52794
commit
50ea087755
4 changed files with 87 additions and 40 deletions
|
@ -1,3 +1,20 @@
|
||||||
|
2020-11-13 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
PR 26829
|
||||||
|
* dwarf.c (struct dwo_info): Add cu_offset field.
|
||||||
|
(add_dwo_info): Add cu_offset parameter. Record in new dwo_info
|
||||||
|
struct.
|
||||||
|
(add_dwo_name): Add cu_offset field.
|
||||||
|
(add_dwo_dir): Add cu_offset field.
|
||||||
|
(add_dwo_id): Add cu_offset field.
|
||||||
|
(read_and_display_attr_value): Pass cu_offset to dwo recording
|
||||||
|
functions.
|
||||||
|
(load_separate_debug_files): Accumulate name, dir and id values
|
||||||
|
and display once for each CU.
|
||||||
|
* testsuite/binutils-all/dwo.sL Use a separate CU for the second
|
||||||
|
dwo link.
|
||||||
|
* testsuite/binutils-all/readelf.k2: Update expected output.
|
||||||
|
|
||||||
2020-11-11 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
2020-11-11 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||||
|
|
||||||
* dwarf.c (display_debug_rnglists_list): Only bias the
|
* dwarf.c (display_debug_rnglists_list): Only bias the
|
||||||
|
|
|
@ -67,6 +67,7 @@ typedef struct dwo_info
|
||||||
{
|
{
|
||||||
dwo_type type;
|
dwo_type type;
|
||||||
const char * value;
|
const char * value;
|
||||||
|
dwarf_vma cu_offset;
|
||||||
struct dwo_info * next;
|
struct dwo_info * next;
|
||||||
} dwo_info;
|
} dwo_info;
|
||||||
|
|
||||||
|
@ -1892,32 +1893,33 @@ get_AT_name (unsigned long attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_dwo_info (const char * field, dwo_type type)
|
add_dwo_info (const char * value, dwarf_vma cu_offset, dwo_type type)
|
||||||
{
|
{
|
||||||
dwo_info * dwinfo = xmalloc (sizeof * dwinfo);
|
dwo_info * dwinfo = xmalloc (sizeof * dwinfo);
|
||||||
|
|
||||||
dwinfo->type = type;
|
dwinfo->type = type;
|
||||||
dwinfo->value = field;
|
dwinfo->value = value;
|
||||||
dwinfo->next = first_dwo_info;
|
dwinfo->cu_offset = cu_offset;
|
||||||
|
dwinfo->next = first_dwo_info;
|
||||||
first_dwo_info = dwinfo;
|
first_dwo_info = dwinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_dwo_name (const char * name)
|
add_dwo_name (const char * name, dwarf_vma cu_offset)
|
||||||
{
|
{
|
||||||
add_dwo_info (name, DWO_NAME);
|
add_dwo_info (name, cu_offset, DWO_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_dwo_dir (const char * dir)
|
add_dwo_dir (const char * dir, dwarf_vma cu_offset)
|
||||||
{
|
{
|
||||||
add_dwo_info (dir, DWO_DIR);
|
add_dwo_info (dir, cu_offset, DWO_DIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_dwo_id (const char * id)
|
add_dwo_id (const char * id, dwarf_vma cu_offset)
|
||||||
{
|
{
|
||||||
add_dwo_info (id, DWO_ID);
|
add_dwo_info (id, cu_offset, DWO_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2876,16 +2878,16 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
switch (form)
|
switch (form)
|
||||||
{
|
{
|
||||||
case DW_FORM_strp:
|
case DW_FORM_strp:
|
||||||
add_dwo_name ((const char *) fetch_indirect_string (uvalue));
|
add_dwo_name ((const char *) fetch_indirect_string (uvalue), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_GNU_strp_alt:
|
case DW_FORM_GNU_strp_alt:
|
||||||
add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue));
|
add_dwo_name ((const char *) fetch_alt_indirect_string (uvalue), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_GNU_str_index:
|
case DW_FORM_GNU_str_index:
|
||||||
add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
|
add_dwo_name (fetch_indexed_string (uvalue, this_set, offset_size, FALSE), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_string:
|
case DW_FORM_string:
|
||||||
add_dwo_name ((const char *) orig_data);
|
add_dwo_name ((const char *) orig_data, cu_offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn (_("Unsupported form (%s) for attribute %s\n"),
|
warn (_("Unsupported form (%s) for attribute %s\n"),
|
||||||
|
@ -2900,19 +2902,19 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
switch (form)
|
switch (form)
|
||||||
{
|
{
|
||||||
case DW_FORM_strp:
|
case DW_FORM_strp:
|
||||||
add_dwo_dir ((const char *) fetch_indirect_string (uvalue));
|
add_dwo_dir ((const char *) fetch_indirect_string (uvalue), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_GNU_strp_alt:
|
case DW_FORM_GNU_strp_alt:
|
||||||
add_dwo_dir (fetch_alt_indirect_string (uvalue));
|
add_dwo_dir (fetch_alt_indirect_string (uvalue), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_line_strp:
|
case DW_FORM_line_strp:
|
||||||
add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue));
|
add_dwo_dir ((const char *) fetch_indirect_line_string (uvalue), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_GNU_str_index:
|
case DW_FORM_GNU_str_index:
|
||||||
add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE));
|
add_dwo_dir (fetch_indexed_string (uvalue, this_set, offset_size, FALSE), cu_offset);
|
||||||
break;
|
break;
|
||||||
case DW_FORM_string:
|
case DW_FORM_string:
|
||||||
add_dwo_dir ((const char *) orig_data);
|
add_dwo_dir ((const char *) orig_data, cu_offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn (_("Unsupported form (%s) for attribute %s\n"),
|
warn (_("Unsupported form (%s) for attribute %s\n"),
|
||||||
|
@ -2927,7 +2929,7 @@ read_and_display_attr_value (unsigned long attribute,
|
||||||
{
|
{
|
||||||
case DW_FORM_data8:
|
case DW_FORM_data8:
|
||||||
/* FIXME: Record the length of the ID as well ? */
|
/* FIXME: Record the length of the ID as well ? */
|
||||||
add_dwo_id ((const char *) (data - 8));
|
add_dwo_id ((const char *) (data - 8), cu_offset);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
warn (_("Unsupported form (%s) for attribute %s\n"),
|
warn (_("Unsupported form (%s) for attribute %s\n"),
|
||||||
|
@ -11148,18 +11150,50 @@ load_separate_debug_files (void * file, const char * filename)
|
||||||
{
|
{
|
||||||
free_dwo_info ();
|
free_dwo_info ();
|
||||||
|
|
||||||
if (process_debug_info (& debug_displays[info].section, file, abbrev, TRUE, FALSE))
|
if (process_debug_info (& debug_displays[info].section, file, abbrev,
|
||||||
|
TRUE, FALSE))
|
||||||
{
|
{
|
||||||
bfd_boolean introduced = FALSE;
|
bfd_boolean introduced = FALSE;
|
||||||
dwo_info * dwinfo;
|
dwo_info * dwinfo;
|
||||||
const char * dir = NULL;
|
const char * dir = NULL;
|
||||||
const char * id = NULL;
|
const char * id = NULL;
|
||||||
|
const char * name = NULL;
|
||||||
|
|
||||||
for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = dwinfo->next)
|
for (dwinfo = first_dwo_info; dwinfo != NULL; dwinfo = dwinfo->next)
|
||||||
{
|
{
|
||||||
|
/* Accumulate NAME, DIR and ID fields. */
|
||||||
switch (dwinfo->type)
|
switch (dwinfo->type)
|
||||||
{
|
{
|
||||||
case DWO_NAME:
|
case DWO_NAME:
|
||||||
|
if (name != NULL)
|
||||||
|
warn (_("Multiple DWO_NAMEs encountered for the same CU\n"));
|
||||||
|
name = dwinfo->value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DWO_DIR:
|
||||||
|
/* There can be multiple DW_AT_comp_dir entries in a CU,
|
||||||
|
so do not complain. */
|
||||||
|
dir = dwinfo->value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DWO_ID:
|
||||||
|
if (id != NULL)
|
||||||
|
warn (_("multiple DWO_IDs encountered for the same CU\n"));
|
||||||
|
id = dwinfo->value;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error (_("Unexpected DWO INFO type"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have reached the end of our list, or we are changing
|
||||||
|
CUs, then display the information that we have accumulated
|
||||||
|
so far. */
|
||||||
|
if (name != NULL
|
||||||
|
&& (dwinfo->next == NULL
|
||||||
|
|| dwinfo->next->cu_offset != dwinfo->cu_offset))
|
||||||
|
{
|
||||||
if (do_debug_links)
|
if (do_debug_links)
|
||||||
{
|
{
|
||||||
if (! introduced)
|
if (! introduced)
|
||||||
|
@ -11169,30 +11203,19 @@ load_separate_debug_files (void * file, const char * filename)
|
||||||
introduced = TRUE;
|
introduced = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf (_(" Name: %s\n"), dwinfo->value);
|
printf (_(" Name: %s\n"), name);
|
||||||
printf (_(" Directory: %s\n"), dir ? dir : _("<not-found>"));
|
printf (_(" Directory: %s\n"), dir ? dir : _("<not-found>"));
|
||||||
if (id != NULL)
|
if (id != NULL)
|
||||||
display_data (printf (_(" ID: ")), (unsigned char *) id, 8);
|
display_data (printf (_(" ID: ")), (unsigned char *) id, 8);
|
||||||
else
|
else
|
||||||
printf (_(" ID: <unknown>\n"));
|
printf (_(" ID: <not specified>\n"));
|
||||||
printf ("\n\n");
|
printf ("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_follow_links)
|
if (do_follow_links)
|
||||||
load_dwo_file (filename, dwinfo->value, dir, id);
|
load_dwo_file (filename, name, dir, id);
|
||||||
break;
|
|
||||||
|
|
||||||
case DWO_DIR:
|
name = dir = id = NULL;
|
||||||
dir = dwinfo->value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DWO_ID:
|
|
||||||
id = dwinfo->value;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
error (_("Unexpected DWO INFO type"));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,8 +34,8 @@ string_end:
|
||||||
/* Create a .debug_info section that contains the dwo links. */
|
/* Create a .debug_info section that contains the dwo links. */
|
||||||
|
|
||||||
.section .debug_info,"",%progbits
|
.section .debug_info,"",%progbits
|
||||||
.4byte debugE - debugS ;# Length of Compilation Unit Info
|
.4byte debugE1 - debugS1 ;# Length of Compilation Unit Info
|
||||||
debugS:
|
debugS1:
|
||||||
.short 0x4 ;# DWARF version number.
|
.short 0x4 ;# DWARF version number.
|
||||||
.4byte 0x0 ;# Offset into .debug_abbrev section.
|
.4byte 0x0 ;# Offset into .debug_abbrev section.
|
||||||
.byte 0x4 ;# Pointer Size (in bytes).
|
.byte 0x4 ;# Pointer Size (in bytes).
|
||||||
|
@ -43,6 +43,13 @@ debugS:
|
||||||
.uleb128 0x1 ;# Use abbrev #1. This needs strings from the .debug_str section.
|
.uleb128 0x1 ;# Use abbrev #1. This needs strings from the .debug_str section.
|
||||||
.4byte string1
|
.4byte string1
|
||||||
.4byte string2
|
.4byte string2
|
||||||
|
debugE1:
|
||||||
|
|
||||||
|
.4byte debugE2 - debugS2 ;# Length of Compilation Unit Info
|
||||||
|
debugS2:
|
||||||
|
.short 0x4 ;# DWARF version number.
|
||||||
|
.4byte 0x0 ;# Offset into .debug_abbrev section.
|
||||||
|
.byte 0x4 ;# Pointer Size (in bytes).
|
||||||
|
|
||||||
.uleb128 0x2 ;# Use abbrev #2.
|
.uleb128 0x2 ;# Use abbrev #2.
|
||||||
.asciz "file.dwo"
|
.asciz "file.dwo"
|
||||||
|
@ -52,7 +59,7 @@ debugS:
|
||||||
;# Minimal section alignment on alpha-* is 2, so ensure no new invalid CU
|
;# Minimal section alignment on alpha-* is 2, so ensure no new invalid CU
|
||||||
;# will be started.
|
;# will be started.
|
||||||
.balign 2, 0
|
.balign 2, 0
|
||||||
debugE:
|
debugE2:
|
||||||
|
|
||||||
.section .debug_abbrev,"",%progbits
|
.section .debug_abbrev,"",%progbits
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@ The \.debug_info section contains link\(s\) to dwo file\(s\):
|
||||||
|
|
||||||
Name: debugfile\.dwo
|
Name: debugfile\.dwo
|
||||||
Directory: /path/to/dwo/files
|
Directory: /path/to/dwo/files
|
||||||
ID: (12|dd) (34|cc) (56|bb) (78|aa) (78|aa) (56|bb) (34|cc) (12|dd)
|
ID: <not specified>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue