Add Build IDs to a perf.data Stream with perf inject
perf inject writes a second perf.data file with build ID records added, so symbols still resolve later without ever touching your original capture. Allow about fifteen minutes, plus time to process a large recording. You need the Linux perf tools that match the running kernel and a readable perf.data file produced by perf record.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide describes the perf-inject(1) installed with linux-tools-common version 6.8.0-142.142. The local manual is dated 1 September 2026. On this machine, the perf wrapper also reports that the kernel-specific binary for 6.8.0-139 is missing, so the example commands cannot be executed here until the matching tools package is installed. That is a local packaging problem, not a reason to change the capture.
1. Check the input and the matching tool
Start with ordinary, read-only checks. Replace /path/to/perf.data with the capture you intend to process:
$ command -v perf
/usr/bin/perf
$ dpkg-query -W -f='${Package} ${Version}\n' linux-tools-common
linux-tools-common 6.8.0-142.142
$ test -r /path/to/perf.data && file /path/to/perf.data
/path/to/perf.data: data
The exact file description can vary. The useful checks are that the path exists and is readable. Confirm the tool before starting a long conversion:
$ perf inject --help
Usage: perf inject <options>
Checkpoint
If the command instead prints a warning that perf is not installed for the running kernel, stop here. Install or select the matching package through your normal system-management process, then rerun the check. Do not substitute a random version for a performance capture you need to trust.
2. Inject build IDs for sampled DSOs
The normal build-ID mode scans sample records, finds the dynamic shared objects reached by those samples, and adds their build IDs to the output stream. Write to a new path:
$ perf inject --input=/path/to/perf.data \
--output=/path/to/perf-with-buildids.data \
--build-ids
The short spelling is -i, -o and -b:
$ perf inject -i /path/to/perf.data \
-o /path/to/perf-with-buildids.data \
-b
$ printf 'exit status: %s\n' "$?"
exit status: 0
A zero status means the command completed successfully. It does not mean every symbol can be resolved later: a build ID identifies an object, while symbol names still depend on the object and its debug information being available to the consumer.
Checkpoint
Confirm that a new, non-empty file exists and that the source still exists:
$ test -s /path/to/perf-with-buildids.data && \
test -r /path/to/perf.data && \
ls -lh /path/to/perf.data /path/to/perf-with-buildids.data
There is no rollback command because this workflow does not alter the input. If the generated file is wrong or incomplete, keep the original and choose a different output path for the next attempt. Do not use --force merely to make an existing destination disappear.
3. Inject all DSO build IDs instead
Use --buildid-all when the output should contain build IDs for all DSOs in the recording, including objects that were not hit by samples:
$ perf inject -i /path/to/perf.data \
-o /path/to/perf-with-all-buildids.data \
--buildid-all
This mode skips SAMPLE processing, which is a meaningful difference from --build-ids, not just a longer spelling. Choose it when later processing needs the complete set of recorded objects; otherwise the sample-driven mode usually keeps the result narrower.
Do not confuse a DSO with a source file. The option concerns the binary objects referenced by the event stream. It does not collect source code, install debuginfo or make an unavailable library available.
4. Use an explicit build-ID list when paths need overriding
--known-build-ids= accepts comma-separated build-ID and path pairs. It also accepts file://filename, so a list generated by perf buildid-list can be supplied as a file:
$ perf inject -i /path/to/perf.data \
-o /path/to/perf-with-known-buildids.data \
--known-build-ids=file:///path/to/buildids.txt
Warning
Treat the list as input data, not as a shell script. Quote a path containing spaces, and inspect the file before passing it to perf. Do not paste build IDs or paths from an untrusted source into a command line without checking them. If you do not have a verified list, omit this option and use one of the two automatic modes above.
5. Make the output easier to diagnose
Input and output default to standard input and standard output. That makes a pipeline possible, but named files are easier to audit and less likely to be mixed up with diagnostic text:
$ perf inject --build-ids \
< /path/to/perf.data \
> /path/to/perf-with-buildids.data
Use --verbose when you need additional diagnostics:
$ perf inject --verbose --build-ids \
-i /path/to/perf.data \
-o /path/to/perf-with-buildids.data
Keep standard output reserved for the event stream when using a pipeline. For a repeatable job, prefer --input and --output, then record the command and its exit status alongside the profiling result.
6. Keep specialised modes separate
--sched-statmerges scheduler sleep duration records with scheduler switch records. Useful for analysing where and how long tasks slept, but unrelated to build-ID injection. Add it only when that scheduler analysis is part of the question:$ perf inject -i /path/to/perf.data \ -o /path/to/perf-with-scheduler-data.data \ --sched-stat--itracedecodes instruction-tracing data into synthesised events, and--stripremoves non-synthesised events when used with it. These can materially change what later tools see. The manual documents a default set of decoded event types, period units, call-chain limits and branch-entry limits. Do not add--itraceto a build-ID job unless the input contains instruction tracing and you have decided which derived events you need.--jitprocesses jitdump files and generates ELF images for jitted functions. This can create additional files, so treat it as a deliberate output-producing operation.--vm-time-correlationupdates the input file in place for virtual-machine timestamp correlation and does not accept a separate output file. That is an overwrite operation: use itsdry-runform first when supported, take a backup, and do not include it in the safe copy-to-a-new-file workflow above.
Recover from common failures
- Input will not open. Check its path and permissions first.
- Output already exists. Choose a new name rather than adding
--forceby reflex. - Missing perf binary for the running kernel. Install the matching Linux tools package and rerun
perf inject --helpbefore processing the capture. - Missing symbols in a later report. A command that completes does not prove every later report will have symbols. Preserve the original perf.data file, the injected copy, the exact command line and the tool version, then compare search paths and available binaries with the build IDs recorded in the capture rather than regenerating the input destructively.
Done means
- Tool matches kernel: the installed perf tool matches the running kernel, or the mismatch is recorded as an unresolved prerequisite.
- Original untouched: the original
perf.datafile remains unchanged and readable. - New file created: a separate output file was created with
--build-idsor--buildid-all. - Success confirmed: the output is non-empty and the command returned status 0.
- List checked first: any known build-ID list was inspected before use.
- No accidental overwrite: you did not use the in-place virtual-machine timestamp mode by mistake.