A debugger that steps wrong or shows the wrong value often traces back to debug info, and llvm-debuginfo-analyzer-20 reads it directly. By the end of this guide you can inspect the logical debug view of an object file, narrow it to a symbol or type, record non-fatal debug warnings, and compare two compiler outputs. The examples use llvm-debuginfo-analyzer-20 from Ubuntu's llvm-20 package, verified here as LLVM 20.1.8. Allow about 15 minutes if Clang and GCC are already installed. The tool reads files; it does not modify them, and none of these commands needs elevated privileges.
You need an ELF object file with debug information and the versioned analyser on your PATH. A source file compiled without -g can still be accepted, but it will not give you a useful source-level view. Work in a scratch directory so generated objects and reports do not get mixed with a build you care about.
command -v llvm-debuginfo-analyzer-20
llvm-debuginfo-analyzer-20 --version
On the machine used for this guide, the second command reports Ubuntu LLVM version 20.1.8. Your patch level may differ while the command remains part of the LLVM 20 package.
Save this as debuginfo-demo.c in a temporary directory, then compile it with Clang. The -O0 choice keeps the example easy to follow; it is not a requirement of the analyser.
#include <stdio.h>
static int twice(int value) {
return value * 2;
}
int main(void) {
int answer = twice(21);
printf("answer=%d\n", answer);
return 0;
}
clang-20 -O0 -g -c debuginfo-demo.c -o debuginfo-demo.o
test -s debuginfo-demo.o
The result is an object file, not a runnable program. That is enough for the analyser. If clang-20 is absent, use another installed Clang and keep the analyser command versioned. Do not add -gline-tables-only for this first pass: full debug information gives the types, scopes and symbols used below.
Print the main logical elements and useful identifying attributes:
llvm-debuginfo-analyzer-20 \
--attribute=level,format,producer \
--print=scopes,symbols,types,lines \
debuginfo-demo.o
The output is a tree-like logical view rather than a raw DWARF dump. It should identify the ELF format and compilation unit, then show entries such as twice, main, the value parameter and the answer variable. The level attribute is the lexical scope level. The producer attribute records the compiler recorded in the object.
The default view is deliberately broad. Use --output-file=report.txt when you want a saved report, or pipe standard output to a file yourself. The analyser supports text output here. Its documented JSON output is not implemented in this installed tool, so do not build a workflow around --output=json.
Reduce the report to a named symbol and ask for a table layout:
llvm-debuginfo-analyzer-20 \
--attribute=level \
--select=answer \
--report=list \
--print=symbols,summary \
debuginfo-demo.o
The output should contain a Variable entry for answer, followed by a count table. A selection without an explicit report uses the list layout by default, but stating --report=list makes a script and its output easier to understand.
--select matches element names or line numbers. It is case-sensitive unless you add --select-nocase. Add --select-regex when the pattern is a regular expression, for example:
llvm-debuginfo-analyzer-20 \
--select-regex --select-nocase --select='main|twice' \
--report=list --print=scopes,symbols \
debuginfo-demo.o
For less ambiguous results, target a category directly. The analyser accepts kinds such as Function for --select-scopes, Variable for --select-symbols, and Typedef for --select-types. These names describe debug information kinds, so check llvm-debuginfo-analyzer-20 --help before putting a narrow kind into automation.
Request the analyser's non-fatal warnings separately from ordinary output:
llvm-debuginfo-analyzer-20 \
--warning=all \
--print=warnings,summary \
debuginfo-demo.o
Warnings cover invalid symbol coverage or locations, invalid code ranges, and zero debug line values. A warning does not necessarily prevent a logical view from being produced. Treat it as a reason to inspect the compiler, linker or input object, not as proof that the source is wrong. The command returns zero when parsing and printing succeed, and one otherwise.
Build a second object, then compare selected logical elements:
gcc -O0 -g -c debuginfo-demo.c -o debuginfo-demo-gcc.o
llvm-debuginfo-analyzer-20 \
--attribute=level \
--compare=types,symbols \
--report=list \
--print=symbols,types,summary \
debuginfo-demo.o debuginfo-demo-gcc.o
The first file is the reference and the second is the target. The report labels elements as missing or added, and internally performs the comparison in both directions so each side is visible. The list report compares individual elements without requiring identical parents. Use --report=view when the enclosing parent and child relationships are the thing you need to diagnose.
Do not treat a difference as automatically a compiler defect. Clang and GCC can emit different but valid debug representations, and one format can contain more detail than another. Compare the same source, compiler settings and target architecture first. If you need to remove unstable line numbers from an external comparison, the manpage documents the advanced --internal=none option; use it only when that trade-off is intentional.
a.out, then fails if that file is absent. Name the object explicitly.-g and confirm the object path.--print=elements is broad. It is a convenience for instructions, lines, scopes, symbols and types, and can be much larger than a targeted report.--print=sizes is ELF-specific. Do not assume it describes Mach-O, WebAssembly, PDB or COFF inputs in the same way.--output=split is used with --output-folder. Choose a new scratch folder first so existing reports are not mixed in or replaced.There is no service to restart and no persistent configuration to undo. To recover from a confusing run, delete only the temporary object and report files you created, then rebuild the object with the desired compiler flags. Avoid broad cleanup commands in a directory containing other build artefacts.
llvm-debuginfo-analyzer-20 --version identifies the installed LLVM 20 build.-g object produces a logical view with scopes, symbols, types or lines.