Add initial support for .debug_sup sections.
* dwarf.c (get_type_abbrev_from_form): Accept but ignore sup forms. (read_and_display_attr_value): Handle sup forms. (display_debug_sup): New function. Displays the contents of a .debug_sup section. (load_debug_sup_file): New function. Loads the contents of a file referenced by a .debug_sup section. (check_for_and_load_links): Call load_debug_sup_file. (debug_displays): Add entry for .debug_sup. * dwarf.h (enum dwarf_section_display_enum): Add debug_sup. * readelf.c (process_section_headers): Add support for debug_sup. * doc/debug.options.texi: Note that the =links option will display the contents of .debug_sup sections. * NEWS: Mention the new support.
This commit is contained in:
parent
d4ff3cbfdb
commit
e38332c286
@ -1,3 +1,20 @@
|
|||||||
|
2021-02-25 Nick Clifton <nickc@redhat.com>
|
||||||
|
|
||||||
|
* dwarf.c (get_type_abbrev_from_form): Accept but ignore sup
|
||||||
|
forms.
|
||||||
|
(read_and_display_attr_value): Handle sup forms.
|
||||||
|
(display_debug_sup): New function. Displays the contents of a
|
||||||
|
.debug_sup section.
|
||||||
|
(load_debug_sup_file): New function. Loads the contents of a file
|
||||||
|
referenced by a .debug_sup section.
|
||||||
|
(check_for_and_load_links): Call load_debug_sup_file.
|
||||||
|
(debug_displays): Add entry for .debug_sup.
|
||||||
|
* dwarf.h (enum dwarf_section_display_enum): Add debug_sup.
|
||||||
|
* readelf.c (process_section_headers): Add support for debug_sup.
|
||||||
|
* doc/debug.options.texi: Note that the =links option will display
|
||||||
|
the contents of .debug_sup sections.
|
||||||
|
* NEWS: Mention the new support.
|
||||||
|
|
||||||
2021-02-25 Alan Modra <amodra@gmail.com>
|
2021-02-25 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR 27456
|
PR 27456
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
-*- text -*-
|
-*- text -*-
|
||||||
|
|
||||||
|
* Readelf and objdump can now display and use the contents of .debug_sup
|
||||||
|
sections.
|
||||||
|
|
||||||
* Readelf and objdump will now follow links to separate debug info files by
|
* Readelf and objdump will now follow links to separate debug info files by
|
||||||
default. This behaviour can be stopped via the use of the new -wN or
|
default. This behaviour can be stopped via the use of the new -wN or
|
||||||
--debug-dump=no-follow-links options for readelf and the -WN or
|
--debug-dump=no-follow-links options for readelf and the -WN or
|
||||||
|
@ -44,11 +44,11 @@ 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},
|
||||||
@samp{.gnu_debugaltlink} sections. Also displays any links to
|
@samp{.gnu_debugaltlink} and @samp{.debug_sup} sections, if any of
|
||||||
separate dwarf object files (dwo), if they are specified by the
|
them are present. Also displays any links to separate dwarf object
|
||||||
DW_AT_GNU_dwo_name or DW_AT_dwo_name attributes in the
|
files (dwo), if they are specified by the DW_AT_GNU_dwo_name or
|
||||||
@samp{.debug_info} section.
|
DW_AT_dwo_name attributes in the @samp{.debug_info} section.
|
||||||
|
|
||||||
@item K
|
@item K
|
||||||
@itemx =follow-links
|
@itemx =follow-links
|
||||||
|
150
binutils/dwarf.c
150
binutils/dwarf.c
@ -2131,6 +2131,10 @@ get_type_abbrev_from_form (unsigned long form,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref_sup4:
|
||||||
|
case DW_FORM_ref_sup8:
|
||||||
|
break;
|
||||||
|
|
||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
case DW_FORM_ref2:
|
case DW_FORM_ref2:
|
||||||
case DW_FORM_ref4:
|
case DW_FORM_ref4:
|
||||||
@ -2387,7 +2391,7 @@ display_discr_list (unsigned long form,
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
printf ("<corrupt>\n");
|
printf ("<corrupt>\n");
|
||||||
warn (_("corrupt discr_list - unrecognised discriminant byte %#x\n"),
|
warn (_("corrupt discr_list - unrecognized discriminant byte %#x\n"),
|
||||||
discriminant);
|
discriminant);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2460,6 +2464,7 @@ read_and_display_attr_value (unsigned long attribute,
|
|||||||
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
|
SAFE_BYTE_GET_AND_INC (uvalue, data, pointer_size, end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_strp_sup:
|
||||||
case DW_FORM_strp:
|
case DW_FORM_strp:
|
||||||
case DW_FORM_line_strp:
|
case DW_FORM_line_strp:
|
||||||
case DW_FORM_sec_offset:
|
case DW_FORM_sec_offset:
|
||||||
@ -2483,6 +2488,7 @@ read_and_display_attr_value (unsigned long attribute,
|
|||||||
SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
|
SAFE_BYTE_GET_AND_INC (uvalue, data, 2, end);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref_sup4:
|
||||||
case DW_FORM_ref4:
|
case DW_FORM_ref4:
|
||||||
case DW_FORM_data4:
|
case DW_FORM_data4:
|
||||||
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
|
SAFE_BYTE_GET_AND_INC (uvalue, data, 4, end);
|
||||||
@ -2536,6 +2542,7 @@ read_and_display_attr_value (unsigned long attribute,
|
|||||||
case DW_FORM_ref1:
|
case DW_FORM_ref1:
|
||||||
case DW_FORM_ref2:
|
case DW_FORM_ref2:
|
||||||
case DW_FORM_ref4:
|
case DW_FORM_ref4:
|
||||||
|
case DW_FORM_ref_sup4:
|
||||||
case DW_FORM_ref_udata:
|
case DW_FORM_ref_udata:
|
||||||
if (!do_loc)
|
if (!do_loc)
|
||||||
printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
|
printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
|
||||||
@ -2563,6 +2570,7 @@ read_and_display_attr_value (unsigned long attribute,
|
|||||||
printf ("%c%s", delimiter, dwarf_vmatoa ("d", implicit_const));
|
printf ("%c%s", delimiter, dwarf_vmatoa ("d", implicit_const));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_ref_sup8:
|
||||||
case DW_FORM_ref8:
|
case DW_FORM_ref8:
|
||||||
case DW_FORM_data8:
|
case DW_FORM_data8:
|
||||||
if (!do_loc)
|
if (!do_loc)
|
||||||
@ -2755,8 +2763,13 @@ read_and_display_attr_value (unsigned long attribute,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DW_FORM_strp_sup:
|
||||||
|
if (!do_loc)
|
||||||
|
printf ("%c<0x%s>", delimiter, dwarf_vmatoa ("x", uvalue + cu_offset));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
warn (_("Unrecognized form: %lu\n"), form);
|
warn (_("Unrecognized form: 0x%lx\n"), form);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4334,6 +4347,81 @@ display_formatted_table (unsigned char * data,
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
display_debug_sup (struct dwarf_section * section,
|
||||||
|
void * file ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
unsigned char * start = section->start;
|
||||||
|
unsigned char * end = section->start + section->size;
|
||||||
|
unsigned int version;
|
||||||
|
char is_supplementary;
|
||||||
|
const unsigned char * sup_filename;
|
||||||
|
size_t sup_filename_len;
|
||||||
|
unsigned int num_read;
|
||||||
|
int status;
|
||||||
|
dwarf_vma checksum_len;
|
||||||
|
|
||||||
|
|
||||||
|
introduce (section, TRUE);
|
||||||
|
if (section->size < 4)
|
||||||
|
{
|
||||||
|
error (_("corrupt .debug_sup section: size is too small\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read the data. */
|
||||||
|
SAFE_BYTE_GET_AND_INC (version, start, 2, end);
|
||||||
|
if (version < 5)
|
||||||
|
warn (_("corrupt .debug_sup section: version < 5"));
|
||||||
|
|
||||||
|
SAFE_BYTE_GET_AND_INC (is_supplementary, start, 1, end);
|
||||||
|
if (is_supplementary != 0 && is_supplementary != 1)
|
||||||
|
warn (_("corrupt .debug_sup section: is_supplementary not 0 or 1\n"));
|
||||||
|
|
||||||
|
sup_filename = start;
|
||||||
|
if (is_supplementary && sup_filename[0] != 0)
|
||||||
|
warn (_("corrupt .debug_sup section: filename not empty in supplementary section\n"));
|
||||||
|
|
||||||
|
sup_filename_len = strnlen ((const char *) start, end - start);
|
||||||
|
if (sup_filename_len == (size_t) (end - start))
|
||||||
|
{
|
||||||
|
error (_("corrupt .debug_sup section: filename is not NUL terminated\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
start += sup_filename_len + 1;
|
||||||
|
|
||||||
|
checksum_len = read_leb128 (start, end, FALSE /* unsigned */, & num_read, & status);
|
||||||
|
if (status)
|
||||||
|
{
|
||||||
|
error (_("corrupt .debug_sup section: bad LEB128 field for checksum length\n"));
|
||||||
|
checksum_len = 0;
|
||||||
|
}
|
||||||
|
start += num_read;
|
||||||
|
if (checksum_len > (dwarf_vma) (end - start))
|
||||||
|
{
|
||||||
|
error (_("corrupt .debug_sup section: checksum length is longer than the remaining section length\n"));
|
||||||
|
checksum_len = end - start;
|
||||||
|
}
|
||||||
|
else if (checksum_len < (dwarf_vma) (end - start))
|
||||||
|
{
|
||||||
|
warn (_("corrupt .debug_sup section: there are 0x%lx extra, unused bytes at the end of the section\n"),
|
||||||
|
(long) ((end - start) - checksum_len));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf (_(" Version: %u\n"), version);
|
||||||
|
printf (_(" Is Supp: %u\n"), is_supplementary);
|
||||||
|
printf (_(" Filename: %s\n"), sup_filename);
|
||||||
|
printf (_(" Checksum Len: %lu\n"), (long) checksum_len);
|
||||||
|
if (checksum_len > 0)
|
||||||
|
{
|
||||||
|
printf (_(" Checksum: "));
|
||||||
|
while (checksum_len--)
|
||||||
|
printf ("0x%x ", * start++ );
|
||||||
|
printf ("\n");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
display_debug_lines_raw (struct dwarf_section * section,
|
display_debug_lines_raw (struct dwarf_section * section,
|
||||||
unsigned char * data,
|
unsigned char * data,
|
||||||
@ -11131,9 +11219,62 @@ load_dwo_file (const char * main_filename, const char * name, const char * dir,
|
|||||||
return separate_handle;
|
return separate_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
load_debug_sup_file (const char * main_filename, void * file)
|
||||||
|
{
|
||||||
|
if (! load_debug_section (debug_sup, file))
|
||||||
|
return; /* No .debug_sup section. */
|
||||||
|
|
||||||
|
struct dwarf_section * section;
|
||||||
|
section = & debug_displays [debug_sup].section;
|
||||||
|
assert (section != NULL);
|
||||||
|
|
||||||
|
if (section->start == NULL || section->size < 5)
|
||||||
|
{
|
||||||
|
warn (_(".debug_sup section is corrupt/empty\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (section->start[2] != 0)
|
||||||
|
return; /* This is a supplementary file. */
|
||||||
|
|
||||||
|
const char * filename = (const char *) section->start + 3;
|
||||||
|
if (strnlen (filename, section->size - 3) == section->size - 3)
|
||||||
|
{
|
||||||
|
warn (_("filename in .debug_sup section is corrupt\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename[0] != '/' && strchr (main_filename, '/'))
|
||||||
|
{
|
||||||
|
char * new_name;
|
||||||
|
if (asprintf (& new_name, "%.*s/%s",
|
||||||
|
(int) (strrchr (main_filename, '/') - main_filename),
|
||||||
|
main_filename,
|
||||||
|
filename) < 3)
|
||||||
|
warn (_("unable to construct path for supplementary debug file"));
|
||||||
|
else
|
||||||
|
filename = new_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * handle;
|
||||||
|
handle = open_debug_file (filename);
|
||||||
|
if (handle == NULL)
|
||||||
|
{
|
||||||
|
warn (_("unable to open file '%s' referenced from .debug_sup section\n"), filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf (_("%s: Found supplementary debug file: %s\n\n"), main_filename, filename);
|
||||||
|
|
||||||
|
/* FIXME: Compare the checksums, if present. */
|
||||||
|
add_separate_debug_file (filename, handle);
|
||||||
|
}
|
||||||
|
|
||||||
/* Load a debuglink section and/or a debugaltlink section, if either are present.
|
/* Load a debuglink section and/or a debugaltlink section, if either are present.
|
||||||
Recursively check the loaded files for more of these sections.
|
Recursively check the loaded files for more of these sections.
|
||||||
FIXME: Should also check for DWO_* entries in the newlu loaded files. */
|
Also follow any links in .debug_sup sections.
|
||||||
|
FIXME: Should also check for DWO_* entries in the newly loaded files. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
check_for_and_load_links (void * file, const char * filename)
|
check_for_and_load_links (void * file, const char * filename)
|
||||||
@ -11175,6 +11316,8 @@ check_for_and_load_links (void * file, const char * filename)
|
|||||||
first_separate_info->filename);
|
first_separate_info->filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
load_debug_sup_file (filename, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load the separate debug info file(s) attached to FILE, if any exist.
|
/* Load the separate debug info file(s) attached to FILE, if any exist.
|
||||||
@ -11541,6 +11684,7 @@ struct dwarf_section_display debug_displays[] =
|
|||||||
{ { ".debug_tu_index", "", NO_ABBREVS }, display_cu_index, &do_debug_cu_index, FALSE },
|
{ { ".debug_tu_index", "", NO_ABBREVS }, display_cu_index, &do_debug_cu_index, FALSE },
|
||||||
{ { ".gnu_debuglink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
|
{ { ".gnu_debuglink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
|
||||||
{ { ".gnu_debugaltlink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
|
{ { ".gnu_debugaltlink", "", NO_ABBREVS }, display_debug_links, &do_debug_links, FALSE },
|
||||||
|
{ { ".debug_sup", "", NO_ABBREVS }, display_debug_sup, &do_debug_links, FALSE },
|
||||||
/* Separate debug info files can containt their own .debug_str section,
|
/* Separate debug info files can containt their own .debug_str section,
|
||||||
and this might be in *addition* to a .debug_str section already present
|
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. */
|
in the main file. Hence we need to have two entries for .debug_str. */
|
||||||
|
@ -120,6 +120,7 @@ enum dwarf_section_display_enum
|
|||||||
dwp_tu_index,
|
dwp_tu_index,
|
||||||
gnu_debuglink,
|
gnu_debuglink,
|
||||||
gnu_debugaltlink,
|
gnu_debugaltlink,
|
||||||
|
debug_sup,
|
||||||
separate_debug_str,
|
separate_debug_str,
|
||||||
max
|
max
|
||||||
};
|
};
|
||||||
|
@ -6556,7 +6556,8 @@ process_section_headers (Filedata * filedata)
|
|||||||
if ((do_debugging || do_debug_info || do_debug_abbrevs
|
if ((do_debugging || do_debug_info || do_debug_abbrevs
|
||||||
|| 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_str_offsets || do_debug_loc || do_debug_ranges
|
|| do_debug_str || do_debug_str_offsets || do_debug_loc
|
||||||
|
|| do_debug_ranges
|
||||||
|| do_debug_addr || do_debug_cu_index || do_debug_links)
|
|| 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_")))
|
||||||
@ -6583,6 +6584,7 @@ process_section_headers (Filedata * filedata)
|
|||||||
|| (do_debug_macinfo && const_strneq (name, "macinfo"))
|
|| (do_debug_macinfo && const_strneq (name, "macinfo"))
|
||||||
|| (do_debug_macinfo && const_strneq (name, "macro"))
|
|| (do_debug_macinfo && const_strneq (name, "macro"))
|
||||||
|| (do_debug_str && const_strneq (name, "str"))
|
|| (do_debug_str && const_strneq (name, "str"))
|
||||||
|
|| (do_debug_links && const_strneq (name, "sup"))
|
||||||
|| (do_debug_str_offsets && const_strneq (name, "str_offsets"))
|
|| (do_debug_str_offsets && const_strneq (name, "str_offsets"))
|
||||||
|| (do_debug_loc && const_strneq (name, "loc"))
|
|| (do_debug_loc && const_strneq (name, "loc"))
|
||||||
|| (do_debug_loc && const_strneq (name, "loclists"))
|
|| (do_debug_loc && const_strneq (name, "loclists"))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user