Skip to content

symbolize: consume the full DW_FORM_addrx operand - #266

Open
anatasluo wants to merge 1 commit into
google:masterfrom
anatasluo:master
Open

symbolize: consume the full DW_FORM_addrx operand#266
anatasluo wants to merge 1 commit into
google:masterfrom
anatasluo:master

Conversation

@anatasluo

@anatasluo anatasluo commented Aug 28, 2026

Copy link
Copy Markdown

CompilationUnit::ProcessAttribute() advances the DIE cursor by exactly one byte for every supported address-index form. This is correct only for DW_FORM_addrx1 and one-byte ULEB128 operands. DW_FORM_addrx2, DW_FORM_addrx3, and DW_FORM_addrx4 leave the cursor 1, 2, and 3 bytes short, respectively. The ULEB128 forms, DW_FORM_addrx and DW_FORM_GNU_addr_index, leave it short whenever the encoded index requires more than one byte.

The DW_FORM_addrx2 branch also declares a local addr_index that shadows the outer variable, causing the decoded address to be read from entry 0 of .debug_addr.

Reproduction

With GCC 16.1.1, a generated translation unit containing 200 noinline,used functions and a main function that calls all of them was built with:

gcc -O2 -gdwarf-5 -gsplit-dwarf repro.c -o repro

The resulting .dwo contains 201 DW_TAG_subprogram DIEs whose DW_AT_low_pc uses DW_FORM_addrx. Of those indices, 67 use a one-byte ULEB128 encoding and 134 use a multi-byte encoding; the maximum index is 397.

Tracing the reader through the same Google3Addr2line::Prepare() path used by create_gcov gives:

Observation Before After
Correct high_pc after one-byte addrx 67/67 67/67
Correct high_pc after multi-byte addrx 0/134 134/134
Subprograms rejected by FindBadSubprograms() 133 0
Reader result success, no warning success

For example, fn_0199 uses address index 178. llvm-dwarfdump and nm -S report its high_pc / size as 0xc. The old reader reports 0xc01, while the patched reader reports 0xc.

As a one-byte control, main uses address index 68. Both readers report its correct high_pc of 0xa49.

The old reader therefore succeeds silently in this layout, but the corrupted high_pc values produce oversized, overlapping function ranges. FindBadSubprograms() removes 133 affected subprograms, preventing samples from being attributed to their intended functions. The hand-built regression fixtures also demonstrate a harder failure mode in which the shifted cursor causes an out-of-range abbreviation lookup.

Fix

Track and return the complete decoded operand width, initialize the width used by the fixed-size forms, and remove the shadowing declaration in the DW_FORM_addrx2 branch.

The new DWARF 4 and DWARF 5 regression tests cover addrx1, addrx2, addrx3, addrx4, one- and two-byte addrx, and DW_FORM_GNU_addr_index. Both tests fail before this change and pass after it with GCC- and Clang-built test binaries.

Advance the DIE cursor by the decoded operand width for fixed-width and
ULEB128 addrx forms. Also initialize the operand length and avoid shadowing
the decoded addrx2 index.

Add DWARF 4 and DWARF 5 regression tests covering all supported addrx forms.

Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
@google-cla

google-cla Bot commented Aug 28, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@anatasluo

Copy link
Copy Markdown
Author

Hi @snehasish , could you approve the CI run and help find a reviewer for this fix? The CLA check is now passing, but the workflow is still waiting for maintainer approval.

The patch fixes incorrect parsing of DWARF address-index operands and includes regression tests.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant