Inspect Object Files and Disassembly with objdump
A crash report names an address instead of a function, and that is exactly the gap objdump closes. This walks through identifying an object file, reading its sections and symbols, checking relocations, and disassembling one function. The examples use GNU Binutils 2.42, installed here as objdump, aarch64-linux-gnu-objdump and x86_64-linux-gnu-objdump; all three installed manpages are identical.
The route
Jump straight to the step you need, or tick off Done means at the end.
- Time: about fifteen minutes.
- You need: a shell and a readable ELF object, executable or archive.
- Safe to run: every command here is read-only against its input. No elevated privileges are needed, and
sudowill not make an unreadable file useful unless the permissions genuinely require it.
1. Confirm the installed command and input
Check which binary your shell will run, then ask for its version:
$ command -v objdump
/usr/bin/objdump
$ objdump --version | head -1
GNU objdump (GNU Binutils for Ubuntu) 2.42
The target file is the final argument. Start with a path you can read, such as /bin/ls, or swap in /path/to/program. Do not assume a file named "binary" is an executable, identify it first:
$ file /path/to/program
/path/to/program: ELF 64-bit LSB pie executable, x86-64, ...
Checkpoint
If file reports a script, text file or unrelated format, stop and pick a real object file. objdump can recognise plenty of formats, but it cannot turn arbitrary input into useful disassembly.
2. Read the file header and sections
Use -f for the BFD file format, architecture, flags and start address:
$ objdump -f /bin/ls
/bin/ls: file format elf64-x86-64
architecture: i386:x86-64, flags 0x00000150:
HAS_SYMS, DYNAMIC, D_PAGED
start address 0x0000000000006d30
Use -h for section headers: name, size, virtual address and file offset, handy when you need to narrow a later dump.
$ objdump -h /bin/ls | sed -n '1,12p'
/bin/ls: file format elf64-x86-64
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000000318 0000000000000318 00000318 2**0
For a compact overview of most metadata, use -x. It is equivalent to requesting all headers, section headers, private headers, relocations and symbols. The output can be large, so only redirect it to a report file once you have chosen that destination on purpose.
3. Disassemble code you can relate to a symbol
Use -d to disassemble sections expected to contain code. Unlike -D, it will not disassemble every section. Add -C for demangled C++ names:
$ objdump -d -C /path/to/program
/path/to/program: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <add>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
If you know the symbol, --disassemble=SYMBOL limits the output to it. The symbol has to be present in the file, and a stripped executable may have no ordinary symbol table to search. If that happens, check -h and use a carefully bounded address range instead:
$ objdump --disassemble=main -C /path/to/program
With an object built with debug information, -S interleaves source lines with disassembly and implies -d:
$ objdump -S -C /tmp/sample.o | sed -n '1,24p'
Disassembly of section .text:
0000000000000000 <add>:
int add(int left, int right) { return left + right; }
0: 55 push %rbp
No source appears when the file lacks usable debug information. That is a property of the input, not a reason to run the command as root.
4. Inspect symbols and relocations
Use -t for the ordinary symbol table and -T for the dynamic symbol table. A stripped executable can legitimately report no symbols for -t; do not read that as proof the executable contains no functions.
$ objdump -t /bin/ls | sed -n '1,8p'
/bin/ls: file format elf64-x86-64
SYMBOL TABLE:
no symbols
Use -r on an object file to show relocation records, including references the linker has not resolved yet. This is often the quickest explanation for a call whose displayed target is still provisional:
$ objdump -r /tmp/sample.o | sed -n '1,12p'
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
000000000000002b R_X86_64_PLT32 add-0x0000000000000004
For a shared object or executable, -R shows dynamic relocations instead. Keep the two uses distinct when you are writing up a build problem.
5. Dump bytes from one section
Use -s to display section contents, and add -j SECTION to avoid a noisy whole-file dump:
$ objdump -s -j .text /tmp/sample.o | sed -n '1,10p'
Contents of section .text:
0000 f30f1efa 554889e5 897dfc89 75f88b55 ....UH...}..u..U
0010 fc8b45f8 01d05dc3 f30f1efa 554889e5 ..E...].....UH..
Compressed sections show in compressed form by default. Add -Z with -s when you need decompressed contents. Treat this as a diagnostic view: it does not rewrite or decompress the input file on disk.
Common traps
- -d and -D have different boundaries.
-Ddisassembles all sections, including data, so its output can look like instructions where no code exists. - Address filters touch more than one option.
--start-address=ADDRESSand--stop-address=ADDRESSaffect-d,-rand-s. Confirm whether your addresses are virtual addresses or file offsets before filtering. - Long symbol names get truncated. Narrow terminals cut them short; add
-wfor wide output and keep the full names. - Cross-target aliases do not convert an object. Use
aarch64-linux-gnu-objdumpfor AArch64 work andx86_64-linux-gnu-objdumpfor x86-64 work, then confirm the reported format with-f. - Read-only does not mean the whole pipeline is safe. Do not feed an untrusted file into a toolchain pipeline that writes elsewhere just because
objdumpitself only reads. Check redirections and follow-on scripts separately.
Done means
- Version confirmed:
objdump --versionidentifies the installed Binutils release. - Format checked:
objdump -f FILEconfirms the format and architecture. - Sections mapped:
objdump -h FILEidentifies the sections you need. - Targeted, not dumped: you chose
-d,-t,-ror-s -j SECTIONfor a specific question, rather than treating a wall of output as an answer.