Inspect GCC 13 LTO Objects with lto-dump
lto-dump looks inside a link-time optimisation object and tells you what GCC actually saw: symbols, sections, even a call graph. Everything here is read-only, it will not rewrite the object or relink your program.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes if you already have an object compiled with -flto. You need the GCC 13 toolchain and a readable LTO object. The examples use Ubuntu's installed GCC 13.3.0 packages and the command x86_64-linux-gnu-lto-dump-13.
Checkpoint
This tool examines compiler intermediate data, not an ordinary executable or a normal non-LTO object. If it reports an input error, first confirm how that file was built.
1. Confirm the installed command
Start with ordinary, unprivileged checks. No sudo needed unless the object sits in a directory you cannot read:
$ command -v x86_64-linux-gnu-lto-dump-13
/usr/bin/x86_64-linux-gnu-lto-dump-13
$ dpkg-query -W -f='${Package} ${Version}\n' gcc-13 gcc-13-x86-64-linux-gnu gcc-x86-64-linux-gnu
gcc-13 13.3.0-6ubuntu2~24.04.1
gcc-13-x86-64-linux-gnu 13.3.0-6ubuntu2~24.04.1
gcc-x86-64-linux-gnu 4:13.2.0-7ubuntu1
The version shown is what was on the machine used for this guide. The executable does not print a useful string for --version, so note the package version instead when you need a reproducible diagnostic.
Ask the binary for its own option summary:
$ x86_64-linux-gnu-lto-dump-13 -help
Usage: lto-dump [OPTION]... SUB_COMMAND [OPTION]...
LTO dump tool command line options.
Use the target-prefixed command when you want to be explicit about the architecture. The unprefixed alias lto-dump-13 is also installed on this system.
2. Produce a small LTO object for a safe test
Already have the object you need to inspect? Skip to the next step. Otherwise create a temporary source file and compile it without elevated privileges:
$ workdir=$(mktemp -d /tmp/lto-dump-example.XXXXXX)
$ printf '%s\n' 'int answer(void) { return 42; }' > "$workdir/sample.c"
$ gcc-13 -O2 -flto -c "$workdir/sample.c" -o "$workdir/sample.o"
$ file "$workdir/sample.o"
/tmp/lto-dump-example.XXXXXX/sample.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
The random directory suffix and exact file wording vary. What matters is a relocatable object built with -flto. Nothing here installed a service or touched a system setting.
Recovery
The example writes only below /tmp. Remove that temporary directory once you have finished with rm -r -- "$workdir". Do not substitute a broad or unreviewed path into a removal command.
3. List the functions and variables
-list is the best first look. It prints a table with the symbol type, visibility, size and name:
$ x86_64-linux-gnu-lto-dump-13 -list "$workdir/sample.o"
Type Visibility Size Name
function default 3 answer
Real objects contain far more entries than this. Use -defined-only to drop symbols not defined in the object, and -demangle when the input holds C++ names. Both are sub-options of -list:
$ x86_64-linux-gnu-lto-dump-13 -list -defined-only -demangle "$workdir/sample.o"
$ x86_64-linux-gnu-lto-dump-13 -list -name-sort "$workdir/sample.o"
$ x86_64-linux-gnu-lto-dump-13 -list -size-sort "$workdir/sample.o"
$ x86_64-linux-gnu-lto-dump-13 -list -reverse-sort "$workdir/sample.o"
Sorting only changes presentation, the object itself stays put. -print-value adds initial variable values when the dump data has them.
One version trap worth remembering: the installed GCC 13.3.0 binary rejects -no-sort, even though the installed manpage lists it. Trust the executable's own help over the manpage, and test the exact command on the host where a script will run before you build automation around a documented option.
4. Inspect one symbol in detail
Once -list gives you a name, pass it to -symbol=. Keep the value attached to the option:
$ x86_64-linux-gnu-lto-dump-13 -symbol=answer "$workdir/sample.o"
answer/0 (answer)
Type: function definition analyzed
Visibility: externally_visible semantic_interposition public
References:
Referring:
Read from file: /tmp/lto-dump-example.XXXXXX/sample.o
Availability: available
Unit id: 1
Function flags: count:1073741824 (estimated locally)
Called by:
Calls:
Symbol: answer
Paths, unit identifiers and estimates are input-dependent, treat the output as compiler analysis, not a promise that the function survives unchanged into the final executable. If the name comes back missing, rerun -list and copy an exact symbol name rather than guessing a mangled spelling.
5. See the LTO object sections
-objects reports the LTO objects and the sections stored inside them:
$ x86_64-linux-gnu-lto-dump-13 -objects "$workdir/sample.o"
LTO Object Name: /tmp/lto-dump-example.XXXXXX/sample.o
No. Offset Size Section Name
1 64 15 .gnu.lto_.profile.983b7ac5fa8de62
2 79 26 .gnu.lto_.icf.983b7ac5fa8de62
3 105 22 .gnu.lto_.ipa_sra.983b7ac5fa8de62
...
The section names and offsets tell you what LTO data is present and where it lives. That is handy when comparing compiler outputs or chasing a toolchain problem, but it is not a substitute for readelf or objdump when you need general ELF headers or machine code.
6. Request statistics or a call graph
The installed command also accepts analysis subcommands for type, tree and GIMPLE statistics. For example:
$ x86_64-linux-gnu-lto-dump-13 -type-stats "$workdir/sample.o"
Type Frequency Percentage
function_type 1 100.00
On this build, -tree-stats and -gimple-stats can warn that the binary was not configured with detailed memory statistics. That is a build-capability note, not evidence the object is broken.
-callgraph shows up in the installed help and emits Graphviz format, but it is missing from the installed manpage, so treat it as a feature of this binary rather than a portable GCC 13 interface. Save output to a new file if you want to render it:
$ x86_64-linux-gnu-lto-dump-13 -callgraph "$workdir/sample.o" > "$workdir/callgraph.dot"
$ head -n 1 "$workdir/callgraph.dot"
digraph symtab {
Warning
Redirection with > truncates an existing destination before the command even runs. Use a new path, as above, or make a deliberate backup first. If the command fails, remove only the incomplete new file, the input object is untouched.
7. Keep failures in proportion
A normal inspection needs no elevated privileges. If the input will not open, check its path and permissions first:
$ ls -l /path/to/object.o
$ test -r /path/to/object.o && echo readable
Reach for sudo only when that read check actually points to an access requirement and your local policy allows it. Root will not turn a non-LTO object into an LTO object. If the file is an executable or an ordinary object built without -flto, use tools built for that format instead.
- Capture the version. Record the package version, the exact command, the input path and the exit status for a repeatable report.
- Do not panic at empty output. Empty sections, missing symbols or an empty call graph are not automatically failures, check how the object was compiled and which subcommand you picked first.
Done means
- Confirmed the toolchain. You verified the installed GCC 13 package and command path.
- Listed the symbols. You inspected an object built with
-fltousing-list. - Named the symbol exactly. You used exact symbol names with
-symbol=when deeper detail was needed. - Trusted the right source. You distinguished the installed binary's help from the older or broader manpage option list.
- Protected the input. You kept output redirection pointed at new files and left the input object untouched.
- Stayed unprivileged. You used no elevated privileges unless filesystem permissions actually required them.