perf-map parser silently rejects all entries when addresses are 0x-prefixed (JDK 25 `jcmd Compiler.perfmap` format) — all JIT frames become `Anonymous`

Open Beginner friendly
#560 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
cpp, java, linux

Research direction

Start in src/runtime_symbol_lookup.cc at the sscanf parsing and insert_or_replace() validity check, then reproduce with a JDK 25 perf map containing 0x-prefixed address and size fields. Update the parsing so both prefixed and bare-hex formats are accepted, and confirm the entries are retained and JIT frames no longer render as Anonymous.

Written by the indexing model from the issue text.

Description

Summary

ddprof fails to symbolicate any JIT frames from a /tmp/perf-<pid>.map file whose
address/size fields are 0x-prefixed — the format jcmd <pid> Compiler.perfmap emits
on OpenJDK 25. Every line of the map is rejected at parse time, the runtime symbol map
stays empty, and all JIT-compiled Java frames render as Anonymous in profiles. The
failure is silent above debug log level.

Environment

  • ddprof v0.26.0 (the parser is unchanged on current main)
  • OpenJDK 25 (java-25-openjdk), Linux container
  • ddprof in wrapper mode (ddprof --preset alloc_live_heap ... /usr/bin/java ...),
    JVM running with -XX:+PreserveFramePointer
  • Perf map regenerated every 300s via jcmd <pid> Compiler.perfmap

Reproduction

  1. Run a JVM under ddprof wrapper mode with any preset.

  2. Generate the map with jcmd <pid> Compiler.perfmap. On JDK 25 the file contains
    (captured from our production pod):

    0x00007f6cc9200100 0x0000000000000368 java.lang.Object jdk.internal.misc.Unsafe.getReferenceVolatile(java.lang.Object, long)
    0x00007f6cc9200580 0x0000000000000178 int jdk.internal.misc.Unsafe.getInt(java.lang.Object, long)
    
  3. Observe profiles: JIT regions never resolve; all such frames show as Anonymous.
    Rewriting the same file to bare hex (7f6cc9200100 368 <symbol>) makes
    symbolication work immediately.

Root cause

In src/runtime_symbol_lookup.cc, each line is parsed with:

sscanf(line, "%16s %8s %300[^\t\n]", address_buff, size_buff, buffer)

A 0x-prefixed 64-bit address token is 18 characters (0x + 16 hex digits):

  • %16s truncates the address to 0x00007f6cc92001 (corrupting it), and
  • %8s then consumes the leftover 00 of the address token as the size field,
    so the real size is never read and code_size parses to 0.

The subsequent validity check in insert_or_replace() (!address || !code_size)
rejects the entry. This happens for every line, so the map is 100% discarded.
Because a failed lookup only logs at debug, nothing surfaces at default/warn levels —
we confirmed 72h of profiles with zero resolved Java JIT frames before finding this.

Suggested fix

Widen the field buffers (e.g. %18s) and parse both fields with
strtoul(str, NULL, 16), which accepts the 0x prefix natively; the same code path
then handles both the classic bare-hex format and the JDK 25 output.

A warn-level log when a large fraction of perf-map lines is rejected would also make
this failure mode diagnosable.

Workaround

Post-process the JDK dump before ddprof reads it, publishing atomically:

jcmd "$pid" Compiler.perfmap "/tmp/perf-$pid.map.jvm" &&
gawk '{ a = strtonum($1 ~ /^0x/ ? $1 : "0x" $1);
        s = strtonum($2 ~ /^0x/ ? $2 : "0x" $2);
        $1 = ""; $2 = ""; sub(/^  */, "");
        printf "%x %x %s\n", a, s, $0 }' "/tmp/perf-$pid.map.jvm" \
  > "/tmp/perf-$pid.map.tmp" &&
mv "/tmp/perf-$pid.map.tmp" "/tmp/perf-$pid.map"
Dominant language
C++
Stars
62
Forks
15
PR merge metrics
No merged PRs in 30d

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from DataDog/ddprof

All issues in DataDog/ddprof

Similar issues

More C++ issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.