Merge and Inspect LLVM CodeGen Data with llvm-cgdata

llvm-cgdata merges the raw CodeGen Data that Clang embeds in an object file into one indexed .cgdata file you can inspect or convert to text. Allow about fifteen minutes if LLVM is already installed. The examples use llvm-cgdata-20 from Debian package llvm-20 version 1:20.1.8~++20250804090239+87f0227cb601-1~exp1~20250804210352.139.

This is an ordinary, unprivileged workflow. You need a shell, clang-20, llvm-cgdata-20, and a writable working directory. The tool reads object files and writes a new data file; it does not install anything, alter the compiler, or modify the input objects.

1. Check the installed interface

Confirm the executable and the LLVM version before relying on option details:

$ command -v llvm-cgdata-20
/usr/bin/llvm-cgdata-20
$ llvm-cgdata-20 --version
Ubuntu LLVM version 20.1.8
  Optimized build.
$ llvm-cgdata-20 --help

Checkpoint: Do not confuse --version, which reports the LLVM build, with --cgdata-version, which concerns the data format. The latter is an option to the tool's data actions, not a replacement for an action.

2. Generate an object containing raw CodeGen Data

llvm-cgdata does not create raw records from an ordinary executable by itself. The compiler must emit them into custom sections first. Use Clang's documented -fcodegen-data-generate option when producing an object:

$ cat > /tmp/cgdata-example.c <<'EOF'
static int helper(int x) { return x + 1; }
int main(void) { return helper(41) != 42; }
EOF
$ clang-20 -c -Oz -fcodegen-data-generate \
    -o cgdata-example.o /tmp/cgdata-example.c
$ file cgdata-example.o
cgdata-example.o: ELF 64-bit LSB relocatable, ...

The shortened file line is intentional: architecture wording varies. The useful check is that the result is an object file, not that it has one exact description. This compilation does not link or run the program.

Tip: Keep the source and object until you have checked the merged file. If the object is no longer needed, remove it only after verification; deletion is irreversible unless you can recreate it.

3. Merge objects into an indexed file

Pass one or more compiler-generated objects to --merge and choose a new output path:

$ llvm-cgdata-20 --merge \
    --output=merged.cgdata cgdata-example.o
$ test -s merged.cgdata && echo 'merged.cgdata is non-empty'
merged.cgdata is non-empty
$ file merged.cgdata
merged.cgdata: data

Safety warning: Choose a fresh output name. An existing output may be replaced. If you need to replace a valuable file, copy it first and only move the new file into place after the checks below pass.

4. Show the indexed file

Ask the tool to read the resulting file:

$ llvm-cgdata-20 --show merged.cgdata
$ printf 'show exit status: %s\n' "$?"
show exit status: 0

Checkpoint: --show prints summary information when the file contains records. A valid file with no recognised records can produce no visible summary, so check the status and file size together; do not mistake an empty terminal for evidence that the command did not run.

For a deliberately invalid input, the command fails rather than treating arbitrary bytes as CodeGen Data:

$ llvm-cgdata-20 --show /dev/null
error: /dev/null: empty codegen data
$ printf 'show exit status: %s\n' "$?"
show exit status: 1

That is a useful diagnostic for a missing, empty, or wrong input path. It does not mean that the compiler failed to emit data; inspect the object and regenerate it if necessary.

5. Convert binary data to text

The indexed file can be converted to text for inspection or test fixtures. Use the format value text and write to a separate file:

$ llvm-cgdata-20 --convert \
    --format=text --output=merged.cgdata.txt merged.cgdata
$ test -f merged.cgdata.txt
$ wc -c merged.cgdata.txt
0 merged.cgdata.txt

Example: The zero-byte result above is normal for an indexed file with no records, as in this minimal smoke test. With records, the text file contains their textual representation instead.

The installed help accepts the tested short spelling -f text as well:

$ llvm-cgdata-20 --convert -f text \
    -o merged.cgdata.txt merged.cgdata

Conversion writes a new file. It does not change merged.cgdata, so the binary input remains available for later consumers.

6. Diagnose failures without escalating privileges

These operations normally need no sudo. First check paths, permissions, and the input type:

$ test -r cgdata-example.o && echo 'object is readable'
object is readable
$ test -w . && echo 'current directory is writable'
current directory is writable
$ llvm-readobj-20 --sections cgdata-example.o | grep -E 'loutline|lmerge|llvm_outline|llvm_merge'

The final command is a diagnostic, not part of llvm-cgdata. Section names depend on the object format and target. If it finds no CodeGen Data section, compile a fresh object with -fcodegen-data-generate and check that you are merging that object, not a previously built one.

Recovery: If --show reports an empty or invalid CodeGen Data file, stop before replacing any known-good output. Check that the input is the file produced by --merge, that the merge included the intended objects, and that the command used the same LLVM generation family where compatibility matters. Do not repair a format error by editing the binary by hand.

Done means