Well it didn't take long for the SAFE_BYTE_GET assert to trigger.
PR 27860
* dwarf.c (display_debug_frames): Sanity check cie_off before
attempting to read cie.
* dwarf.c (process_extended_line_op): Don't bump data pointer past
end when strnlen doesn't find string terminator.
(decode_location_expression): Remove dead code.
(skip_attr_bytes): Remove const from end param. Ensure data
pointer doesn't pass end.
(get_type_signedness): Remove const from end param.
(read_and_display_attr_value): Ensure data pointer doesn't pass end.
(display_debug_lines_raw, display_debug_lines_decoded): Likewise.
(display_debug_pubnames_worker): Likewise.
(display_debug_pubnames_worker): Use SAFE_BYTE_GET_AND INC rather
than blindly incrementing data pointer.
(display_debug_addr, display_debug_str_offsets): Likewise. Don't
compare pointers, compare lengths.
This rearranges SAFE_BYTE_GET* macros, eliminating some duplication,
and making sure that the _INC variants never increment their PTR arg
past END. I've added an assertion that should show us places where we
use them improperly with user derived PTR args, which I'm sure the
fuzzers will find for us.
* dwarf.c (SAFE_BYTE_GET_INTERNAL): Define.
(SAFE_BYTE_GET, SAFE_BYTE_GET_AND_INC): Define using the above.
(SAFE_SIGNED_BYTE_GET, SAFE_SIGNED_BYTE_GET_AND_INC): Likewise.
(display_discr_list): Use SAFE_BYTE_GET_AND_INC rather than
SAFE_BYTE_GET followed by increment.
(process_debug_info): Likewise, and test bytes remaining before
incrementing section_begin rather than using pointer comparison.
(display_debug_names): Pass lvalue as SAFE_BYTE_GET PTR.
(process_cu_tu_index): Likewise for SAFE_BYTE_GET_AND_INC.
Not quite infinite but much longer than it need be. The problem is
triggered by read_and_display_attr_value incrementing "data" past
"end". read_and_display_attr_value shouldn't do that, but be
defensive.
PR 27853
* dwarf.c (display_formatted_table): Test for data >= end rather
than data == end.
(process_extended_line_op): Likewise.
(display_debug_lines_raw): Likewise.
(display_debug_lines_decoded): Likewise.
Building as ILP32 shows:
gcc -m32 -DHAVE_CONFIG_H -I. -I/checkout/binutils -I. -I/checkout/binutils -I../bfd -I/checkout/binutils/../bfd -I/checkout/binutils/../include -DLOCALEDIR="\"/usr/local/share/locale\"" -Dbin_dummy_emulation=bin_vanilla_emulation -W -Wall -Wstrict-prototypes -Wmissing-prototypes -Wshadow -Wstack-usage=262144 -Werror -I/checkout/binutils/../zlib -g -O2 -MT dwarf.o -MD -MP -MF $depbase.Tpo -c -o dwarf.o /checkout/binutils/dwarf.c &&\
mv -f $depbase.Tpo $depbase.Po
In file included from /checkout/binutils/sysdep.h:101:0,
from /checkout/binutils/dwarf.c:21:
/checkout/binutils/dwarf.c: In function 'process_abbrev_set':
/checkout/binutils/dwarf.c:1072:15: error: format '%lx' expects argument of type 'long unsigned int', but argument 2 has type 'dwarf_vma {aka long long unsigned int}' [-Werror=format=]
warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
^
/checkout/binutils/dwarf.c:1072:13: note: in expansion of macro '_'
warn (_("Debug info is corrupted, abbrev size (%lx) is larger than "
^
cc1: all warnings being treated as errors
Makefile:1101: recipe for target 'dwarf.o' failed
The recent commit, casting one of the terms, has an obvious
typo. To wit, the (non-cast) term abbrev_size is a
dwarf_vma and causes the whole expression to (still) be 64
bits.
binutils:
* dwarf.c (process_abbrev_set): Properly parenthesize before
casting to unsigned long.
PR 27845
* dwarf.c (process_abbrev_set): Replace start and end parameters
with section, abbrev_base, abbrev_size, abbrev_offset. Update
all callers. Sanity check parameters correctly and emit warnings
here rather than..
(process_debug_info): ..here.
PTR supplied to these macros can be read from user input, END is an
end of buffer pointer. It's safer to do arithmetic on END than on PTR.
* dwarf.c (SAFE_BYTE_GET): Check bounds by subtracting amount from
END rather than adding amount to PTR.
(SAFE_SIGNED_BYTE_GET, SAFE_BYTE_GET64): Likewise.
PR 27478
* objdump.c (process_links): New variable.
(usage): Add --process-links.
(long_options): Likewise.
(dump_bfd): Stop processing once the bfd has been loaded unless
this is the main file or process_links has been enabled.
(main): Handle the process-links option.
* readelf.c (process_links): New variable.
(struct filedata): Add is_separate field.
(options): Add --process-links.
(usage): Likewise.
(parse_args): Likewise.
(process_file_header): Include the filename when dumping
information for separate debuginfo files.
(process_program_headers): Likewise.
(process_section_headers): Likewise.
(process_section_groups): Likewise.
(process_relocs): Likewise.
(process_dynamic_section): Likewise.
(process_version_sections): Likewise.
(display_lto_symtab): Likewise.
(process_symbol_table): Likewise.
(process_syminfo): Likewise.
(initialise_dumps_by_name): Likewise.
(process_section_contents): Likewise.
(process_notes_at): Likewise.
(process_notes): Likewise.
(open_file): Add is_separate parameter. Use to initialise the
is_separate field in the filedata structure.
(open_deug): Update call to open_file.
(process_object): Add processing of the contents of separate
debuginfo files, gated by the process_links variable.
(process_archive): Update call to open_file.
(process_file): Initialise the is_separate field in the filedata
structure.
* dwarf.c (load_separate_debug_info_file): Only report the
loading of a separate file if debug links are being dumped.
* objcopy.c (keep_section_symbols): New variable.
(enum command_line_switch): Add OPTION_KEEP_SYMBOLS.
(strip_options): Add keep-section-symbols.
(copy_options): Likewise.
(copy_usage): Likewise.
(strip_usage): Likewise.
(copy_object): Keep section symbols if requested by command line
option.
(strip_main): Handle --keep-section-symbols.
(copy_main): Likewise.
* doc/binutils.texi: Document the new options.
* NEWS: Mention the new features.
* testsuite/binutils-all/compress.exp (test_gnu_debuglink):
Update options passed to objdump. Use diff rather than cmp to
compare the dumped data.
* testsuite/binutils-all/objdump.WK2: Update regexp.
* testsuite/binutils-all/objdump.WK3: Update regexp.
* testsuite/binutils-all/objdump.exp: Use --process-links
instead of --dwarf=follow-links.
* testsuite/binutils-all/readelf.exp (readelf_test): Include
readelf's output in the log when the test fails.
Add the -P option to the -wKis test.
* testsuite/binutils-all/readelf.wKis: Update expected output.
We shouldn't warn missing separate debug files when debug info isn't
needed.
PR binutils/27486
* dwarf.c (load_separate_debug_info): Issue warning only if
do_debug_links is set.
* testsuite/binutils-all/compress.exp: Run objdump and readelf
with missing debug file.
* 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.
There is a tiny error left in dwarf.c:read_leb128 after Nick fixed the
signed overflow problem in code I wrote. It's to do with sleb128
values that have unnecessary excess bytes. For example, -1 is
represented as 0x7f, the most efficient encoding, but also as
0xff,0x7f or 0xff,0xff,0x7f and so on. None of these sequences
overflow any size signed value, but read_leb128 will report an
overflow given enough excess bytes. This patch fixes that problem,
and since the proper test for signed values with excess bytes can
easily be adapted to also test a sleb byte with just some bits that
overflow the result, I changed the code to not use signed right
shifts. (The C standard ISO/IEC 9899:1999 6.5.7 says signed right
shifts of negative values have an implementation defined value. A
long time ago I even used a C compiler for a certain microprocessor
that always did unsigned right shifts. Mind you, it is very unlikely
to be compiling binutils with such a compiler.)
bfd/
* wasm-module.c: Guard include of limits.h.
(CHAR_BIT): Provide backup define.
(wasm_read_leb128): Use CHAR_BIT to size "result" in bits.
Correct signed overflow checking.
opcodes/
* wasm32-dis.c: Include limits.h.
(CHAR_BIT): Provide backup define.
(wasm_read_leb128): Use CHAR_BIT to size "result" in bits.
Correct signed overflow checking.
binutils/
* dwarf.c: Include limits.h.
(CHAR_BIT): Provide backup define.
(read_leb128): Use CHAR_BIT to size "result" in bits. Correct
signed overflow checking.
* testsuite/binutils-all/pr26548.s,
* testsuite/binutils-all/pr26548.d,
* testsuite/binutils-all/pr26548e.d: New tests.
* testsuite/binutils-all/readelf.exp: Run them.
(readelf_test): Drop unused "xfails" parameter. Update all uses.
* objdump.c (load_specific_debug_section): Don't call
bfd_cache_section_contents. Rearrange so that
bfd_get_full_section_contents is not called on path where
bfd_simple_get_relocated_section_contents is called.
Don't set section->user_data.
(free_debug_section): Always free section->start. Don't twiddle
section flags.
* readelf.c (load_specific_debug_section): Don't set user_data.
* dwarf.h (struct dwarf_section): Remove use_data field.
* dwarf.c (NO_ABBREVS, ABBREV): Adjust to suit.
* configure.ac (follow-debug-links): Add option to enable or
disable the following of debug links by default. Set the
default for the option to be 'follow'.
* dwarf.c (do_follow_links): Initialise with DEFAULT_FOR_FOLLOW_LINKS.
(dwarf_select_sections_by_names): Add no-follow-links option.
(dwarf_select_sections_by_letter): Add 'N' option.
* objdump.c (usage): Add conditional text describing the
follow links option.
(slurp_symtab): Ensure that there is a NULL entry at the end
of the symbol table.
(slurp_dynamic_symtab): Likewise.
(dump_bfd): When extending the symbol table, ensure that there
is still a NULL entry at the end.
* readelf.c (usage): Add conditional text describing the
follow links option.
* doc/binutils.texi: Update documentation for objcopy and
readelf.
* doc/debug.options.texi: Update documentation of the
follow-links option.
* config.in: Regenerate.
* configure: Regenerate.
* testsuite/binutils-all/compress.exp: Add the -WN option to
objdump command lines that are not expecting to follow links.
* testsuite/binutils-all/readelf.exp: Add the
--debug-dump=no-follow-links option to tests that are not
expecting to follow debug links.
gas * testsuite/gas/mach-o/sections-1.d: Stop automatic debug link
following.
* testsuite/gas/xgate/insns-dwarf2.d: Likewise.
ld * testsuite/ld-elf/sec64k.exp: Stop readelf from automatically
following debug links.
With exec:
...
$ clang -gdwarf-5 ./src/gdb/testsuite/gdb.dwarf2/fission-mix*.c
...
we have:
...
$ readelf -w a.out
...
Contents of the .debug_str_offsets section:
Length: 0x24
Version: 0x5
Index Offset [String]
0 1d0 clang version 10.0.1
1 1e6 src/gdb/testsuite/gdb.dwarf2/fission-mix-2.c
2 213 /home/vries/gdb_versions/devel
3 232 bar
4 236 x
5 61 int
6 238 s
7 23a func2
8 2c ild/BUILD/glibc-2.26/csu
9 5 sdeps/x86_64/start.S
10 1d0 clang version 10.0.1
11 240 src/gdb/testsuite/gdb.dwarf2/fission-mix.c
12 213 /home/vries/gdb_versions/devel
13 26b foo
14 236 x
15 61 int
16 238 s
17 26f func
18 274 main
19 279 arg
...
The section consists of two parts, one for each CU, each with a header, but
the printing only reads the first header as a header, and prints the second
header as:
...
8 2c ild/BUILD/glibc-2.26/csu
9 5 sdeps/x86_64/start.S
...
Fix this in display_debug_str_offsets such that we have:
...
6 238 s
7 23a func2
Length: 0x2c
Version: 0x5
Index Offset [String]
0 1d0 clang version 10.0.1
1 240 src/gdb/testsuite/gdb.dwarf2/fission-mix.c
...
binutils/ChangeLog:
2021-02-12 Tom de Vries <tdevries@suse.de>
* dwarf.c (display_debug_str_offsets): Handle multiple sets of
entries.
With exec:
...
$ gcc -gsplit-dwarf ~/hello.c -gdwarf-5
...
a dwarf-5 DW_UT_skeleton CU is generated, but the corresponding DWO ID is not
printed by readelf -wi.
Add this, such that we have:
....
Compilation Unit @ offset 0xc7:
Length: 0x31 (32-bit)
Version: 5
Unit Type: DW_UT_skeleton (4)
Abbrev Offset: 0x64
Pointer Size: 8
+ DWO ID: 0x4756ae3ac4348f21
<0><db>: Abbrev Number: 1 (DW_TAG_skeleton_unit)
...
binutils/ChangeLog:
2021-02-12 Tom de Vries <tdevries@suse.de>
* dwarf.c (process_debug_info): Print DWO ID.
With an exec:
...
$ pwd
/home/vries/tmp
$ gcc /home/vries/tmp/src/hello.c -gsplit-dwarf -c \
-o /home/vries/tmp/obj/hello.o
...
I get:
...
$ readelf -w obj/hello.o > READELF
readelf: Warning: Unable to load dwo file: \
/home/vries/tmp//home/vries/tmp/obj/hello.dwo
...
The dwo file name is listed here:
...
<20> DW_AT_GNU_dwo_name: /home/vries/tmp/obj/hello.dwo
<24> DW_AT_comp_dir : /home/vries/tmp
...
The standard states about the DW_AT_dwo_name attribute:
...
value is a null-terminated string containing the full or relative path name
(relative to the value of the DW_AT_comp_dir attribute, see below) of the
object file that contains the full compilation unit.
...
So, readelf shouldn't try to prefix an absolute path with DW_AT_comp_dir.
Fix this in load_dwo_file by handling the absolute path case.
binutils/ChangeLog:
2021-02-10 Tom de Vries <tdevries@suse.de>
PR binutils/27391
* dwarf.c (load_dwo_file): Handle case that name is absolute path.
With exec:
...
$ g++ src/gdb/testsuite/gdb.cp/cpexprs.cc -gdwarf-5 -fdebug-types-section
...
I run into:
...
$ readelf -w a.out > READELF
readelf: Error: Invalid range list entry type 126
readelf: Error: Invalid range list entry type 60
...
The executable contains both a .debug_rnglists section (for CU
cpexprs.cc) and a .debug_ranges section (for other CUs, like crti.S). But
when executing display_debug_ranges for say, section .debug_rnglists it also
tries to use the range list references related to section .debug_ranges.
Fix this by filtering out the .debug_range references when handling
.debug_rnglists and vice versa.
binutils/ChangeLog:
2021-02-10 Tom de Vries <tdevries@suse.de>
PR binutils/27371
* dwarf.c (display_debug_ranges): Filter range lists according to
section.
When compiling an exec like this:
...
$ gcc -fdebug-types-section hello.c -gdwarf-5
...
we run into:
...
$ readelf -w a.out > READELF
readelf: Warning: Unexpected form 20 encountered whilst finding \
abbreviation for type
...
Fix this by handling DW_FORM_ref_sig8 conservatively in
get_type_abbrev_from_form.
binutils/ChangeLog:
2021-02-09 Tom de Vries <tdevries@suse.de>
PR binutils/27370
* dwarf.c (get_type_abbrev_from_form): Handle DW_FORM_ref_sig8.
With this exec:
...
$ gcc -gsplit-dwarf hello.c -gdwarf-5
...
we run into:
...
$ readelf -w a.out > READELF
readelf: Warning: CU at offset c7 contains corrupt or unsupported unit type: 4.
readelf: Warning: CU at offset c7 contains corrupt or unsupported unit type: 4.
...
Fix this by handling DW_UT_skeleton and DW_UT_split_compile in
process_debug_info.
Note that this just adds the parsing of DWO_id, but not yet any printing of
it.
Tested on x86_64-linux.
binutils/ChangeLog:
2021-02-09 Tom de Vries <tdevries@suse.de>
PR binutils/27386
* dwarf.c (process_debug_info): Handling DW_UT_skeleton and
DW_UT_split_compile.
This tidies some code used by readelf, hopefully fixing some
intermittent oss-fuzz bug reports that likely could only be reproduced
by feeding readelf two or more object files on the command line. The
second and subsequent file may see non-zero state in .bss variables,
and non-initial values in .data variables. This patch fixes some of
those, and moves some .data variables to .rodata.
* dwarf.c (frame_display_row): Do without static variable "sloc".
(cu_tu_indexes_read): Move to file scope.
(free_debug_memory): Reset it here, along with level_type_signed.
Free and clear a number of other static variables.
* readelf.c (arm_attr_public_tag <table>): Constify, updating..
(arm_attr_tag_*): ..all these uses.
(process_mips_specific): Free "rels" on error path.
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.
A .debug_abbrev section can have multiple CUs. When caching abbrev list,
we need to check abbrev base to support multiple CUs.
PR binutils/26808
* dwarf.c (abbrev_list): Add abbrev_base.
(new_abbrev_list): Add an abbrev_base argument and record it.
(find_abbrev_list_by_abbrev_offset): Add an abbrev_base argument
and match it.
(process_debug_info): Pass abbrev_base to new_abbrev_list and
find_abbrev_list_by_abbrev_offset.
(display_debug_abbrev): Pass 0 abbrev_base to new_abbrev_list
and find_abbrev_list_by_abbrev_offset.
* testsuite/binutils-all/x86-64/pr26808.dump: New file.
* testsuite/binutils-all/x86-64/pr26808.dwp.bz2: Likewise.
* testsuite/binutils-all/x86-64/x86-64.exp: Run PR binutils/26808
test.
* dwarf.c (struct abbrev_list): New structure. Used to collect
lists of abbreviation sets.
(struct abbrev_map): New structure. Used to map CU offsets to
abbreviation offsets.
(record_abbrev_list): New function. A new entry to an
abbreviation list.
(free_all_abbrevs): Update to free abbreviation lists.
(new_abbrev_list): New function. Start a new abbreviation
list.
(find_abbrev_list_by_abbrev_offset): New function.
(find_abbrev_map_by_offset): New function.
(add_abbrev): Add abbrev_list parameter.
(add_abbrev_attr): Likewise.
(process_abbrev_section): Rename to process_abbrev_set and add
list parameter.
(get_type_abbrev_from_form): New function. Attempts to decode the
forms used by DW_AT_type attributes.
(get_type_signedness): Display type names if operating in wide
mode. Use get_type_abbrev_from_form.
(read_and_display_attr_value): Use get_type_abbrev_from_form.
(process_debug_info): Pre-parse the CU headers to collate all the
abbrevs before starting the main scan.
(process_debug_abbrev): Do not free any loaded abbrevs.
(free_debug_memory): Free the abbrev maps.
* dwarf.c (skip_attr_bytes): Accept DWARF versions higher than 4
when processing the DW_FORM_ref_addr form.
Skip bytes in DW_FORM_block and DW_FORM_exprloc forms.
Handle DW_FORM_indirect.
(get_type_signedness): Allow a limited amount of recursion.
Do not attempt to decode types that use the DW_FORM_ref_addr form.
(read_and_display_attr_value): Do not attempt to decode types
that use the DW_FORM_ref_addr form.
display_loclists_list only handled DW_LLE_offset_pair as bounded
location description. Also handle DW_LLE_start_end and DW_LLE_start_lenght.
These don't use the base_address.
binutils/ChangeLog:
* dwarf.c (display_loclists_list): Handle DW_LLE_start_end and
DW_LLE_start_length. Only add base_address for DW_LLE_offset_pair.
dwz in DWARF5 mode might produce DW_UT_partial unit types, which are
the same as DW_UT_compile unit types (but start with a DW_TAG_partial_unit)
and it might produce DW_FORM_ref_addr to create a reference between
units. Accept both constructs.
binutils/ChangeLog:
* dwarf.c (read_and_display_attr_value): Handle DW_FORM_ref_addr
for dwarf_version 5 just as version 3 and 4 (only 2 is different).
(process_debug_info): Allow DW_UT_partial.
PR 26595
* dwarf.c (load_separate_debug_info): Return NULL rather than
FALSE in error situations.
(load_separate_debug_file): Move code to load debug links to ...
(check_for_and_load_links): ... here. New function. Load
separate debug information pointed to by debuglink and
debugaltlink sections. Recursively scan newly loaded debug
information for more links and load them too.