https://sourceware.org/bugzilla/show_bug.cgi?id=34490
Bug ID: 34490
Summary: RISC-V:objdump -d -l/-S OOM (exponential trie split)
on 32-bit ELF with .debug_ranges base-address sentinel
Product: binutils
Version: 2.46
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: binutils
Assignee: unassigned at sourceware dot org
Reporter: bigmagicreadsun at gmail dot com
Target Milestone: ---
Created attachment 16908
--> https://sourceware.org/bugzilla/attachment.cgi?id=16908&action=edit
rv32
Description of problem:
`objdump -d -l` or `objdump -d -S` on a 32-bit ELF whose .debug_ranges uses
the base-address-selection entry exhausts memory (observed up to ~50GB) or
segfaults. `objdump -d` (without -l/-S) works fine. The trigger is the line-
number/source lookup path.
Root cause:
In bfd/dwarf2.c, read_ranges() detects the DWARF base-address-selection
sentinel by comparing the read value against the *host-word-width* sentinel:
if (low_pc == (bfd_vma) -1 && high_pc != (bfd_vma) -1)
base_address = high_pc;
(bfd_vma) -1 is 0xFFFFFFFFFFFFFFFF on a 64-bit host. However, on a 32-bit
target (addr_size == 4) whose backend does not set sign_extend_vma (e.g.
RISC-V), read_address() reads the 4-byte sentinel 0xFFFFFFFF via
bfd_get_32() and returns it ZERO-EXTENDED to 0x00000000FFFFFFFF, which
never equals the 64-bit (bfd_vma)-1.
Consequently the sentinel (0xFFFFFFFF, 0) is misread as the inverted,
invalid range [0xFFFFFFFF, 0) (low_pc > high_pc) and passed to
arange_add() -> insert_arange_in_trie(). The inverted range spans every
bucket at every level of the shared address->CU trie (from_ch == 0x00,
to_ch == 0xff due to (high_pc - 1) underflow), so the trie is split
exhaustively across all 8 VMA levels (~256^8 nodes), exhausting memory.
With ~30 CUs each contributing one such inverted range to the shared trie,
the leaf (capacity TRIE_LEAF_SIZE == 16) repeatedly fills and splits,
making the blowup deterministic.
Note: backends that DO set sign_extend_vma (e.g. 32-bit ARM/x86) are
unaffected because sign-extension turns 0xFFFFFFFF into
0xFFFFFFFFFFFFFFFF, which coincidentally equals (bfd_vma)-1 and thus
masks the bug.
Reproduction:
ulimit -v 4000000
riscv64-unknown-elf-objdump -d -S test.elf
80000100 <_start>:
riscv64-unknown-elf-objdump: out of memory allocating 259 bytes after a total
of 4082536448 bytes
--
You are receiving this mail because:
You are on the CC list for the bug.