如何从ELF文件提取编译器优化新增常量的地址?
Great question—this is a common pain point when building code size analysis tools, since DWARF debug info only tracks constants explicitly tied to your source code, not the implicit ones generated by optimizations like constant folding, string pooling, or jump table creation. Here’s how you can tackle this:
1. Use Command-Line Tools to Audit .rodata Directly
If you need to inspect these constants manually or script the extraction, lean on ELF-focused utilities:
- First, map the .rodata segment boundaries:
Runreadelf -S your_binary.elf | grep .rodatato get the virtual address (Addr), file offset (Offset), and total size (Size) of the .rodata section. This gives you the full address range to scan. - Dump the complete .rodata content with addresses:
Useobjdump -s -j .rodata your_binary.elf—this prints every byte in .rodata along with its virtual address. You’ll see all constants here, including the ones missing from DWARF. - Filter out DWARF-documented constants:
Extract all constant addresses from your DWARF info (parsereadelf --debug-dump=infofor entries taggedDW_TAG_constant, which useDW_AT_locationorDW_AT_const_valueattributes). Compare this list against the full .rodata address range—any addresses not in the DWARF list are the optimization-generated constants.
2. Programmatic Extraction with ELF/DWARF Libraries
Since you’re building a custom tool, use these libraries to automate the workflow:
- Libelf (for raw ELF parsing):
Open the ELF file, retrieve the.rodatasection header, then read the section’s content. Traverse the address range using your target architecture’s alignment rules (e.g., 4-byte alignment for 32-bit integers, 8-byte for 64-bit) to identify individual constants. Track their start addresses as you iterate. - Libdw (for DWARF + ELF integration):
Use libdw to first collect all source-linked constant addresses from DWARF. Then, iterate over the.rodatasection’s address range, excluding any addresses that match the DWARF-collected list. For anonymous constants (like merged string literals), detect boundaries using clues like null terminators for strings or alignment gaps for numeric constants.
3. Supplement with nm (for Named Constants)
Run nm -A your_binary.elf | grep -E ' [Rr] ' to list all read-only data symbols. While this won’t catch anonymous optimization-generated constants (they have no symbol names), it’s a quick way to cross-reference named constants that might be missing from DWARF.
Key Notes to Keep in Mind
- Alignment Matters: Compilers align constants in .rodata to match the target architecture’s requirements. Make sure your tool respects this when splitting the section into individual constants.
- Optimization Types: Be aware of what optimizations generate these implicit constants—flags like
-O2/-O3enable string pooling, constant folding, and jump table generation, all of which add data to .rodata without DWARF entries. - Boundary Detection: For strings, look for null terminators; for numeric constants, use alignment and typical type sizes (4 bytes for
int, 8 fordouble, etc.) to infer where one constant ends and the next begins.
内容的提问来源于stack exchange,提问作者ramsis

