objdump

objdump gives you information about an object file or executable.

$ gcc -std=c99 -c hello.c
$ objdump -r hello.o > hello_relocation.info

objdump can be really useful when you want to understand more about the internals of executable and linkable format (ELF) files or disassemble an executable (output its corresponding assembly code).

Useful Options / Examples

For the following examples, we’ll be using the C file add.c compiled with the C99 standard and shown below.

int i = 5;

int main() {
    static int j = 2;
    int k = i + j;
}
$ gcc -std=c99 -c add.c
$ gcc -std=c99 add.c -o add
$ ls | grep add
add
add.c
add.o

The -std=c99 flag tells gcc to compile with the C99 standard, and the -c flag tells it to make an object file.

objdump -d

objdump -d disassembles the executable sections of the argument executable or object file. In other words, it shows you the assembly code equivalent of the actual machine code that your CPU runs.

$ objdump -d add > disassembly
$ head -n 10 disassembly

add:     file format elf64-x86-64


Disassembly of section .init:

0000000000400390 <_init>:
  400390:   48 83 ec 08             sub    $0x8,%rsp
  400394:   48 8b 05 5d 0c 20 00    mov    0x200c5d(%rip),%rax        # 600ff8 <_DYNAMIC+0x1d0>
  40039b:   48 85 c0                test   %rax,%rax

The output is extensive, so we only show the first 10 lines here. The first line tells you the file format of the input file and the assembly language used. In this case, the file format is ELF-64, and the assembly language is x86-64.

Next, you’ll see the disassembled code. Each section of disassembly begins with a line that tells you which section of your file that the following code is of. In the limited output above, we’re looking at a part of the .init section.

Each section of disassembly consists of several columns.

The first column tells you the address that the code will be located at runtime.

The second tells you the machine code in hex of the corresponding instruction.

The next two columns have the assembly language equivalent of the machine code.

objdump -t

objdump -t displays the symbol table of your argument file.

$ objdump -t add.o

add.o:     file format elf64-x86-64

SYMBOL TABLE:
0000000000000000 l    df *ABS*  0000000000000000 add.c
0000000000000000 l    d  .text  0000000000000000 .text
0000000000000000 l    d  .data  0000000000000000 .data
0000000000000000 l    d  .bss   0000000000000000 .bss
0000000000000004 l     O .data  0000000000000004 j.1703
0000000000000000 l    d  .note.GNU-stack    0000000000000000 .note.GNU-stack
0000000000000000 l    d  .eh_frame  0000000000000000 .eh_frame
0000000000000000 l    d  .comment   0000000000000000 .comment
0000000000000000 g     O .data  0000000000000004 i
0000000000000000 g     F .text  000000000000001c main

The symbol table has five columns.

The first displays the corresponding symbol’s address.

The second tells you the flags that are enabled for the symbol. In the output above, some of the flags are separated by whitespace, making them seem like different columns, but that’s because some flags are disabled. Some examples of flags are: l for local, g for global, d for debugging, f for file, F for function, and O for object. There are a number of other flags, but we won’t cover all of them here.

The third column tells you where the symbol lives. For example, .data means the data segment, text means the text segment, and *ABS* means absolute (the symbol doesn’t live anywhere in particular).

The fourth shows you the symbol’s size or alignment.

The fifth tells you the symbol’s name.

objdump -r

objdump -r displays the relocation table of your argument file. This command is most useful with object files.

$ objdump -r add.o

add.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
0000000000000006 R_X86_64_PC32     i-0x0000000000000004
000000000000000c R_X86_64_PC32     .data


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE 
0000000000000020 R_X86_64_PC32     .text

The relocation table has three columns.

The first column tells you the offset where the relocated symbol address should go.

The second tells you the type of the symbol.

The third tells you the symbol and the offset that should be added to it after resolving the symbol’s new location.

The -r flag can be used with the -d flag to get the relocation information interspersed in the disassembly.

$ objdump -dr add.o

add.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   8b 15 00 00 00 00       mov    0x0(%rip),%edx        # a <main+0xa>
                        6: R_X86_64_PC32    i-0x4
   a:   8b 05 00 00 00 00       mov    0x0(%rip),%eax        # 10 <main+0x10>
                        c: R_X86_64_PC32    .data
   10:  01 d0                   add    %edx,%eax
   12:  89 45 fc                mov    %eax,-0x4(%rbp)
   15:  b8 00 00 00 00          mov    $0x0,%eax
   1a:  5d                      pop    %rbp
   1b:  c3                      retq 

Other flags

There are a number of other flags that you can use with objdump to get more information about an object file. Because there are so many, we only covered the most useful ones here. You can read about the rest here.