Home / Alt manpages / llvm-readobj-20(1)

  • llvm-readobj-20(1)
  • User command
  • linux

Inspect ELF Binaries Safely with llvm-readobj-20

llvm-readobj-20 reads the headers, sections, symbols and dynamic metadata out of an ELF binary without touching the file itself. Everything in this guide is read-only: no command here needs sudo, and nothing modifies the binary you point it at.

Allow about 10 minutes for the first pass. You need a shell, the llvm-20 package and a readable object file such as /bin/true. The examples below were checked with Ubuntu's llvm-20 package, version 20.1.8.

1. Confirm the installed tool

Check which executable is being used and which option set it provides. The version matters because LLVM tools gain and adjust format-specific options over time.

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

If the command is missing, install the package through your normal system administration process. That is the only step here that may need elevated privileges and it changes system state, so do not add sudo to an otherwise read-only inspection command.

Checkpoint

Continue when llvm-readobj-20 --version prints a version instead of a shell error.

2. Read the file header

Use --file-header, or its short form -h, for the identity and layout of an object file. The example below uses the system's true executable, but swap in a path you actually want to investigate.

$ llvm-readobj-20 --file-header /bin/true

File: /bin/true
Format: elf64-x86-64
Arch: x86_64
AddressSize: 64bit
LoadName: <Not found>
ElfHeader {
  Ident {
    Magic: (7F 45 4C 46)
    Class: 64-bit (0x2)
    DataEncoding: LittleEndian (0x1)
  }
  Type: SharedObject (0x3)
  Machine: EM_X86_64 (0x3E)
}

The exact fields depend on the file. Here is the surprising bit: an ordinary ELF executable can be reported as SharedObject when it is actually a position-independent executable. Treat this output as a description of the file's format and flags, not as a promise about how the program gets launched.

3. List sections and program headers

Sections describe linked contents such as .text, .rodata, .data and symbol tables. Program headers describe the segments the loader actually maps into memory. Ask for both when you are trying to understand how file contents become process memory.

$ llvm-readobj-20 --sections --program-headers /bin/true

File: /bin/true
Format: elf64-x86-64
...
Sections [
  Section {
    Index: 1
    Name: .interp
    Type: SHT_PROGBITS (0x1)
  }
  Section {
    Index: 16
    Name: .text
    Type: SHT_PROGBITS (0x1)
  }
]
ProgramHeaders [
  ProgramHeader {
    Type: PT_LOAD (0x1)
    Flags [ (0x5)
      PF_R (0x4)
      PF_X (0x1)
    ]
  }
]

That output is abbreviated for the page, not a complete transcript. For a compact ELF overview, --headers combines the file header, program headers and sections in one call:

$ llvm-readobj-20 --headers /bin/true > /tmp/true-headers.txt
$ test -s /tmp/true-headers.txt && echo "header report written"
header report written

Warning

Do not redirect output over the input path. A shell redirection is opened before the reader even starts, so a command like llvm-readobj-20 --headers binary > binary can destroy the file before inspection begins. Writing a report under /tmp is optional and safe to remove later.

4. Inspect symbols and demangle names

The symbol table is useful for object files and unstripped binaries. Use --symbols or -s. C++ names read a lot easier with --demangle or -C, an option that applies to both ELF and XCOFF.

$ llvm-readobj-20 --symbols --demangle path/to/program

File: path/to/program
Format: elf64-x86-64
...
Symbols [
  Symbol {
    Name: main
    Value: 0x0000000000000000
  }
]

Do not treat an empty symbol list as proof the file has no functions. Stripped executables can keep their dynamic symbols while losing the full regular symbol table. If runtime linkage is the actual question, inspect the dynamic table and dynamic symbols instead:

$ llvm-readobj-20 --dynamic-table --dyn-symbols /bin/true | sed -n '1,45p'

Keep the output on screen first so errors are visible. Add a redirect only once you know the input path and output path are different.

5. Choose text, bytes or JSON output

For a named section, --string-dump or -p shows you strings, while --hex-dump or -x shows you raw bytes. Pick the section by name or by index.

$ llvm-readobj-20 --string-dump=.rodata /bin/true | sed -n '1,25p'
$ llvm-readobj-20 --hex-dump=.interp /bin/true
  • These are views, not edits. Neither dump decompresses or rewrites a section.
  • Compressed section? Add --decompress alongside a hex or string dump.

For scripts, ask for JSON explicitly and validate that the result actually parses:

$ llvm-readobj-20 --elf-output-style=JSON --file-header --sections /bin/true > /tmp/true.json
$ python3 -m json.tool /tmp/true.json > /dev/null && echo "valid JSON"
valid JSON

LLVM-style structured output is the default. GNU style is available with --elf-output-style=GNU when you need to compare a result against readelf. JSON here is for machine consumption, but its field names are this LLVM tool's own vocabulary, not a universal ELF interchange format.

6. Read relocations and notes when troubleshooting

Use --relocs or -r for relocation entries, --notes or -n for ELF notes, and --dynamic-table or -d for dynamic linking metadata.

$ llvm-readobj-20 --relocs /bin/true | sed -n '1,35p'
$ llvm-readobj-20 --notes /bin/true | sed -n '1,35p'
$ llvm-readobj-20 --dynamic-table /bin/true | sed -n '1,35p'

Large binaries can produce a wall of output. Pipe it to a pager or select a bounded range, but remember a pipe can hide which command actually failed unless you check its status. For a complete first survey, --all turns on the main display options for the file format. That is usually more than you need, so reach for focused flags once you know which question you are answering.

Common errors and recovery

A non-zero exit status means the tool hit an error. Check it directly:

$ llvm-readobj-20 --file-header path/to/missing-file
llvm-readobj-20: error: 'path/to/missing-file': No such file or directory
$ printf 'status: %s\n' "$?"
status: 1
  • Unsure of the format? Run file path/to/input before choosing ELF-specific options. Unsupported format-specific flags may be ignored or produce nothing useful, depending on the file type and option.
  • Reading from a pipe. An input of - reads from standard input, so this is valid too:
$ cat /bin/true | llvm-readobj-20 --file-header - | sed -n '1,12p'

Recovery

There is no persistent change to undo here. If you created reports under /tmp, remove only the exact files you created after checking their names. Never reach for a broad recursive removal command just to tidy up a diagnostic.

Done means

  • Version confirmed: you know which llvm-readobj-20 build you are running.
  • Header and layout read: you can read an ELF file header and tell sections apart from program headers.
  • Right table for the job: you know when to reach for regular symbols, dynamic symbols, relocations and notes.
  • Machine-readable output checked: you can produce JSON and validate it before handing it to another tool.
  • Input untouched: you kept the file read-only and avoided redirecting output over it.