hotspot-perfparser emits incorrect Symbol.relAddr while resolving correct symbol name/size/location
Disclaimer: This issue report was written by ChatGPT based on debugging performed together with me. I ran the diagnostics, reproduced the behavior, and verified the relevant addresses and symbol information locally.
Summary
Hotspot fails to disassemble some functions because the Symbol.relAddr emitted by hotspot-perfparser is incorrect, even though:
- the sampled instruction addresses are correct;
- the source locations are correct;
- the symbol name is correct;
- the symbol size is correct;
- direct disassembly with
llvm-objdump --disassemble-symbols=<symbol>works; perfitself resolves the samples to the correct symbol.
This results in Hotspot invoking objdump/llvm-objdump with an incorrect --start-address.
I initially suspected stale binaries, DWARF issues, or objdump incompatibility, but the parser debug log shows the wrong address is already present in the SymbolDefinition received by Hotspot.
Environment
- Hotspot: latest upstream build from source
- Environment: Fedora-based Qubes VM
- Kernel:
6.12.42-1.qubes.fc37.x86_64 - Kernel build:
#1 SMP PREEMPT_DYNAMIC Tue Aug 19 05:02:34 GMT 2025 - Perf binary:
/usr/bin/perf - Perf version:
7.0.11-100.fc43.x86_64 - Architecture:
x86_64 - CPU: Intel Core i7-12650H
- Compiler: Clang/LLVM
- Target executable: non-PIE ELF executable
- Disassemblers tested: GNU
objdumpand LLVMllvm-objdump
Reproduction
The affected function is:
lexing_process_next
The ELF symbol table reports:
lexing_process_next
start = 0x40ac20
size = 0x26dTherefore the correct function range is:
0x40ac20 .. 0x40ae8dThe Hotspot/perfparser debug log contains a correct root source location:
LocationDefinition{
address=0x40ac20,
...
}and then immediately emits:
SymbolDefinition{
name=lexing_process_next,
relAddr=4238368,
size=621,
...
}4238368 decimal is:
0x40abe0So the parser emits:
name = lexing_process_next
relAddr = 0x40abe0
size = 0x26dinstead of:
name = lexing_process_next
relAddr = 0x40ac20
size = 0x26dHotspot consequently invokes an objdump command equivalent to:
llvm-objdump -d -l -C \
--start-address 0x40abe0 \
--stop-address 0x40ae4d \
/path/to/testbedbut the correct range would be:
llvm-objdump -d -l -C \
--start-address 0x40ac20 \
--stop-address 0x40ae8d \
/path/to/testbedStrong indication that symbol association itself is correct
The parser correctly assigns sample IPs near the actual end of the function to lexing_process_next.
For example, the debug log contains a location at:
address = 0x40ae89which is still inside the real function range:
0x40ac20 .. 0x40ae8dYet the same symbol continues to be emitted as:
relAddr = 0x40abe0
size = 0x26dAccording to that emitted range, the function would end at:
0x40ae4dSo the parser correctly knows that an instruction at 0x40ae89 belongs to lexing_process_next, while simultaneously emitting a symbol range that does not contain that address.
That seems to indicate that symbol lookup/name/size resolution succeeds, but the wrong base/start address is attached to the resulting symbol.
Additional observation
The incorrect address is not random.
For this binary:
0x40abe0is the address of the preceding function:
logos_lexing_lexer_process_input_finishwhile:
0x40ac20is the actual start of:
lexing_process_nextThe emitted metadata therefore effectively combines:
address = preceding function
name = lexing_process_next
size = lexing_process_next sizeThis suggests a possible off-by-one / neighboring-symbol lookup issue in symbol-table handling.
It is not a constant relocation/base-address error: some other symbols in the same executable have correct relAddr values.
For example, main is emitted with a relAddr matching its actual ELF address.
What has already been ruled out
Stale executable / mismatched perf.data
The executable build ID matches the build ID associated with the recorded profile.
Objdump implementation
Both GNU objdump and LLVM objdump fail when Hotspot gives them the incorrect range.
However, LLVM correctly disassembles the function when addressed directly by symbol name:
llvm-objdump -d -l -C \
--disassemble-symbols=lexing_process_next \
/path/to/testbedTherefore the machine code and relevant debug information are available.
Perf symbolization
perf report / perf script correctly identify samples such as:
lexing_process_next+0x0
lexing_process_next+0xac
lexing_process_next+0xc6
lexing_process_next+0x269So perf itself appears to have the correct symbol boundaries.
Hotspot disassembly layer
The parser debug output already contains the incorrect:
Symbol.relAddr = 0x40abe0before the disassembly command is constructed.
This is why I believe the issue originates in hotspot-perfparser rather than the objdump integration.
Attachments
I am attaching:
symbol-proof.txthotspot-latest.log
symbol-proof.txt contains the relevant ELF symbol information together with the matching parser output.
The full perf.data file and executable are too large / inconvenient to attach through GitHub. If they are useful for reproducing the issue, I can provide them directly.
I can be reached on Discord at:
mr.hoornasp.learningexpert
and can share the exact binary and perf.data there if needed.
Expected behavior
For lexing_process_next, hotspot-perfparser should emit:
relAddr = 0x40ac20
size = 0x26dand Hotspot should request disassembly of:
0x40ac20 .. 0x40ae8dActual behavior
hotspot-perfparser emits:
relAddr = 0x40abe0
size = 0x26dcausing Hotspot to request:
0x40abe0 .. 0x40ae4dwhich starts in the preceding function and terminates before the actual end of lexing_process_next.
Suspected area
Based on the observed pattern, I suspect the issue is somewhere in the symbol-address lookup / symbol-table handling inside hotspot-perfparser, potentially where a containing or neighboring ELF/DWARF symbol is selected.
The most suspicious characteristic is that the parser obtains the correct symbol name and size while attaching the start address of the preceding symbol.
If there are additional diagnostics I can run without modifying Hotspot/perfparser source, I am happy to provide them.
ATTACHMENTS
Activity
0No activity yet.