Fun to Program – ELF

Date: 2013/08/09 (initial publish), 2021/08/02 (last update)

Previous Post Top Next Post

TOC

This was originally written and created around 2013 and may require to be updated. (2021)

ELF

In this chapter, I will play with ELF files generated from the same hello.c program file as the one in the Hello World: C with the debug information to learn how it works.

See the following for the he ELF:

An ELF file has two views:

TIP: Both readelf and objdump offer similar functions. The readelf command exists independently of the BFD library, so if there is a bug in the BFD objdump command then readelf will not be affected. Only the objdump command can do disassemble.

Compile hello-gdb

Let’s compile the hello.c program file into the ELF executable hello-gdb with the additional flags.

$ gcc -v -Wall -g -o hello-gdb hello.c
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.8.1-9' --with-b
ugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go
,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --en
able-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-t
hreads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --ena
ble-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-
libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --with-system-zlib
 --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-h
ome=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root
-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-expor
ts/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/shar
e/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 -
-with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-che
cking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-l
inux-gnu
Thread model: posix
gcc version 4.8.1 (Debian 4.8.1-9)
COLLECT_GCC_OPTIONS='-v' '-Wall' '-g' '-o' 'hello-gdb' '-mtune=generic' '-march=
x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/cc1 -quiet -v -imultiarch x86_64-linux-gnu he
llo.c -quiet -dumpbase hello.c -mtune=generic -march=x86-64 -auxbase hello -g -W
all -version -o /tmp/ccOf8WkQ.s
GNU C (Debian 4.8.1-9) version 4.8.1 (x86_64-linux-gnu)
    compiled by GNU C version 4.8.1, GMP version 5.1.2, MPFR version 3.1.1-p2, M
PC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../x8
6_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.
GNU C (Debian 4.8.1-9) version 4.8.1 (x86_64-linux-gnu)
    compiled by GNU C version 4.8.1, GMP version 5.1.2, MPFR version 3.1.1-p2, M
PC version 1.0.1
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 7de91109c57f16a4863bda169a999c04
COLLECT_GCC_OPTIONS='-v' '-Wall' '-g' '-o' 'hello-gdb' '-mtune=generic' '-march=
x86-64'
 as -v --64 -o /tmp/ccejjg1t.o /tmp/ccOf8WkQ.s
GNU assembler version 2.23.52 (x86_64-linux-gnu) using BFD version (GNU Binutils
 for Debian) 2.23.52.20130727
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4
.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/g
cc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.
8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:
/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-v' '-Wall' '-g' '-o' 'hello-gdb' '-mtune=generic' '-march=
x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hd
r -m elf_x86_64 --hash-style=gnu -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o 
hello-gdb /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /us
r/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86
_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/
x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4
.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux
-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. /tmp/ccejjg1
t.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-
as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-g
nu/4.8/../../../x86_64-linux-gnu/crtn.o

Here the gcc command steps through 3 stages of compilation with 3 sub-commands:

FYI:

$ /usr/lib/gcc/x86_64-linux-gnu/4.7/cc1 --help |grep "language C:" -A1
The following options are specific to just the language C:
 None found.  Use --help=C to show *all* the options supported by the C front-en
d
$ /usr/lib/gcc/x86_64-linux-gnu/4.7/cc1 --help=C
The following options are supported by the language C:
  --all-warnings
  --ansi
  --assert
  --assert=
  --comments
  --comments-in-macros
  --define-macro
  --define-macro=
   ... (snip)
$ /usr/lib/gcc/x86_64-linux-gnu/4.7/collect2 --help
Usage: collect2 [options]
 Wrap linker and generate constructor code if needed.
 Options:
  -debug          Enable debug output
  --help          Display this information
  -v, --version   Display this program's version number

Overview: http://gcc.gnu.org/onlinedocs/gccint/Collect2.html
Report bugs: <file:///usr/share/doc/gcc-4.7/README.Bugs>
   ... (snip)

In order to understand how linker works to create an executable from an object file, let me make the hello.o and hello-gdb.o ELF object files with the gcc -c command.

$ gcc -Wall -o hello.o -c hello.c
$ gcc -Wall -g -o hello-gdb.o -c hello.c

So including the hello file generated in Hello World: C, we have 4 ELF files to play with.

Summary of options and generated output files from hello.c.

option output file content
NONE hello executable file
-g hello-gdb executable file with debug symbol
-c hello.o object file
-c -g hello-gdb.o object file with debug symbol

size

Here is the size of the ELF files.

Size of the ELF file generated from hello.c.

$ ls -l hello.o hello hello-gdb.o hello-gdb
-rwxrwxr-x 1 osamu osamu 6687 Aug 17 23:41 hello
-rwxrwxr-x 1 osamu osamu 7719 Aug 17 23:41 hello-gdb
-rw-rw-r-- 1 osamu osamu 3296 Aug 17 23:41 hello-gdb.o
-rw-rw-r-- 1 osamu osamu 1480 Aug 17 23:41 hello.o
$ size  hello.o hello hello-gdb.o hello-gdb
   text       data        bss        dec        hex    filename
     91          0          0         91         5b    hello.o
   1216        560          8       1784        6f8    hello
     91          0          0         91         5b    hello-gdb.o
   1216        560          8       1784        6f8    hello-gdb

The GNU size command lists the section sizes – and the total size – for each of the object or archive files in its argument list.

Since the difference between hello and hello-gdb is the debug information, they share the same values with size(1) but their file size is different with ls(1).

The text column of hello-gdb is much larger than that of hello-gdb.o since the linker seems to link few additional object files such as crt1.o, crti.o, etc.

These will be elucidated from the following results.

readelf –file-header

Here are the ELF file header of the hello file.

ELF file Header of the hello file.

$ readelf -h hello.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          288 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         13
  Section header string table index: 10

TIP: -h = --file-header

Let’s compare the ELF file headers of the compiled hello.c.

ELF file headers of the compiled hello.c

Item hello.o hello-gdb.o hello hello-gdb
Magic 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class ELF64
Data 2’s complement, little endian
Version (EI_VERSION) 1 (current)
OS/ABI UNIX - System V
ABI Version 0
Type REL (Relocatable file) EXEC (Executable file)
Machine Advanced Micro Devices X86-64
Version (e_version) 0x1 0x1 0x1 0x1
Entry point address 0x0 0x0 0x400410 0x400410
Start of program headers (bytes into file) 0 0 64 64
Start of section headers (bytes into file) 288 944 2640 3232
Flags 0x0 0x0 0x0 0x0
Size of this header (bytes) 64 64 64 64
Size of program headers (bytes) 0 0 56 56
Number of program headers 0 0 8 8
Size of section headers (bytes) 64 64 64 64
Number of section headers 13 21 30 35
Section header string table index 10 18 27 32

readelf –sections

The section header lists the set of sections of the binary.

Here are the sections in these ELF files.

Sections of the hello-gdb file.

$ readelf -S hello-gdb
There are 35 section headers, starting at offset 0xca0:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400200  00000200
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             000000000040021c  0000021c
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             000000000040023c  0000023c
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400260  00000260
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000400280  00000280
       0000000000000060  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           00000000004002e0  000002e0
       000000000000003d  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           000000000040031e  0000031e
       0000000000000008  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000400328  00000328
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400348  00000348
       0000000000000018  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000400360  00000360
       0000000000000048  0000000000000018   A       5    12     8
  [11] .init             PROGBITS         00000000004003a8  000003a8
       000000000000001a  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         00000000004003d0  000003d0
       0000000000000040  0000000000000010  AX       0     0     16
  [13] .text             PROGBITS         0000000000400410  00000410
       00000000000001a2  0000000000000000  AX       0     0     16
  [14] .fini             PROGBITS         00000000004005b4  000005b4
       0000000000000009  0000000000000000  AX       0     0     4
  [15] .rodata           PROGBITS         00000000004005c0  000005c0
       0000000000000012  0000000000000000   A       0     0     4
  [16] .eh_frame_hdr     PROGBITS         00000000004005d4  000005d4
       0000000000000034  0000000000000000   A       0     0     4
  [17] .eh_frame         PROGBITS         0000000000400608  00000608
       00000000000000d4  0000000000000000   A       0     0     8
  [18] .init_array       INIT_ARRAY       00000000006006e0  000006e0
       0000000000000008  0000000000000000  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       00000000006006e8  000006e8
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .jcr              PROGBITS         00000000006006f0  000006f0
       0000000000000008  0000000000000000  WA       0     0     8
  [21] .dynamic          DYNAMIC          00000000006006f8  000006f8
       00000000000001d0  0000000000000010  WA       6     0     8
  [22] .got              PROGBITS         00000000006008c8  000008c8
       0000000000000008  0000000000000008  WA       0     0     8
  [23] .got.plt          PROGBITS         00000000006008d0  000008d0
       0000000000000030  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000600900  00000900
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000600910  00000910
       0000000000000008  0000000000000000  WA       0     0     1
  [26] .comment          PROGBITS         0000000000000000  00000910
       0000000000000038  0000000000000001  MS       0     0     1
  [27] .debug_aranges    PROGBITS         0000000000000000  00000948
       0000000000000030  0000000000000000           0     0     1
  [28] .debug_info       PROGBITS         0000000000000000  00000978
       000000000000009f  0000000000000000           0     0     1
  [29] .debug_abbrev     PROGBITS         0000000000000000  00000a17
       0000000000000042  0000000000000000           0     0     1
  [30] .debug_line       PROGBITS         0000000000000000  00000a59
       000000000000003c  0000000000000000           0     0     1
  [31] .debug_str        PROGBITS         0000000000000000  00000a95
       00000000000000bc  0000000000000001  MS       0     0     1
  [32] .shstrtab         STRTAB           0000000000000000  00000b51
       0000000000000148  0000000000000000           0     0     1
  [33] .symtab           SYMTAB           0000000000000000  00001560
       0000000000000690  0000000000000018          34    50     8
  [34] .strtab           STRTAB           0000000000000000  00001bf0
       0000000000000237  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

TIP: -S = --sections = --section-headers

Let’s compare the ELF file sections of the compiled hello.c.

ELF file sections of the compiled hello.c

section type hello.o hello-gdb.o hello hello-gdb size
NULL 0 0 0 0
.interp PROGBITS N/A N/A 0x1c 0x1c text
.note.ABI-tag NOTE N/A N/A 0x20 0x20 text
.note.gnu.build-i NOTE N/A N/A 0x24 0x24 text
.dynsym DYNSYM N/A N/A 0x60 0x60 text
.dynstr STRTAB N/A N/A 0x3d 0x3d text
.gnu.hash GNU_HASH N/A N/A 0x1c 0x1c text
.gnu.version VERSYM N/A N/A 0x8 0x8 text
.gnu.version_r VERNEED N/A N/A 0x20 0x20 text
.rela.dyn RELA N/A N/A 0x18 0x18 text
.rela.plt RELA N/A N/A 0x48 0x48 text
.init PROGBITS N/A N/A 0x1a 0x1a text
.plt PROGBITS N/A N/A 0x40 0x40 text
.text PROGBITS 0x15 0x15 0x1a2 0x1a2 text
.fini PROGBITS N/A N/A 0x9 0x9 text
.rodata PROGBITS 0xe 0xe 0x12 0x12 text
.eh_frame PROGBITS 0x38 0x38 0xd4 0xd4 text
.eh_frame_hdr PROGBITS N/A N/A 0x34 0x34 text
.dynamic DYNAMIC N/A N/A 0x1d0 0x1d0 data
.got PROGBITS N/A N/A 0x8 0x8 data
.got.plt PROGBITS N/A N/A 0x30 0x30 data
.data PROGBITS 0 0 0x10 0x10 data
.jcr PROGBITS N/A N/A 0x8 0x8 data
.fini_array FINI_ARRAY N/A N/A 0x8 0x8 data
.init_array INIT_ARRAY N/A N/A 0x8 0x8 data
.bss NOBITS 0 0 0x8 0x8 bss
.comment PROGBITS 0x1d 0x1d 0x38 0x38 ???
.debug_info PROGBITS N/A 0x9f N/A 0x9f ???
.debug_abbrev PROGBITS N/A 0x42 N/A 0x42 ???
.debug_aranges PROGBITS N/A 0x30 N/A 0x30 ???
.debug_line PROGBITS N/A 0x3c N/A 0x3c ???
.debug_str PROGBITS N/A 0xf5 N/A 0xbc ???
.symtab SYMTAB 0x108 0x180 0x618 0x690 ???
.strtab STRTAB 0x13 0x13 0x237 0x237 ???
.shstrtab STRTAB 0x61 0xb0 0x108 0x148 ???

Here, N/A stands for “not available”.

Let’s compare the .text size reported by size and readelf -S.

Comparison of the reported size.

file size readelf
hello.o text = 91 = 0x5b .text + .rodata + .eh_frame = 0x5b
hello text = 1350 = 0x546 all marked text in size column = 0x53b = 1339 (11 bytes mismatch)
hello data = 568 = 0x238 .dynamic + .got + .got.plt + .data + .jcr + .fini_array + .init.array = 0x238
hello bss = 4 = 0x4 .bss = 0x4

FIXME: Why different?

Here you see some additional sections marked as .debug_* exist since you compiled the hello-gdb.o and hello-gdb files with the -g option. The hello.o and hello files do not have these debug sections.

Various sections are described in the man page elf(5) after “Various sections hold program and control information:”.

TIP: The objdump -h outputs very similar results.

readelf –segments

The program header shows the segments used at run-time. So this is only available for the ELF executable files.

Here are the program headers (=segments) in these ELF files.

Program headers of the hello file.

$ readelf -l hello

Elf file type is EXEC (Executable file)
Entry point 0x400410
There are 8 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000006dc 0x00000000000006dc  R E    200000
  LOAD           0x00000000000006e0 0x00000000006006e0 0x00000000006006e0
                 0x0000000000000230 0x0000000000000238  RW     200000
  DYNAMIC        0x00000000000006f8 0x00000000006006f8 0x00000000006006f8
                 0x00000000000001d0 0x00000000000001d0  RW     8
  NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000005d4 0x00000000004005d4 0x00000000004005d4
                 0x0000000000000034 0x0000000000000034  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gn
u.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_
frame_hdr .eh_frame
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07

Segment headers of the hello-gdb file is the same as that of the hello file.

TIP: -l = --segments = --program-headers

Various sections are described mostly in the man page elf(5) under p_type.

TIP: The objdump -p outputs somewhat similar results.

hexdump

Here is a plain hexadecimal dump of the entire hello-gdb file. (some parts trimmed)

Hexdump of the hello-gdb file.

$ hd hello-gdb
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 3e 00 01 00 00 00  10 04 40 00 00 00 00 00  |..>.......@.....|
   ... (snip)
00000200  2f 6c 69 62 36 34 2f 6c  64 2d 6c 69 6e 75 78 2d  |/lib64/ld-linux-|
00000210  78 38 36 2d 36 34 2e 73  6f 2e 32 00 04 00 00 00  |x86-64.so.2.....|
00000220  10 00 00 00 01 00 00 00  47 4e 55 00 00 00 00 00  |........GNU.....|
00000230  02 00 00 00 06 00 00 00  20 00 00 00 04 00 00 00  |........ .......|
00000240  14 00 00 00 03 00 00 00  47 4e 55 00 f7 12 5f 2e  |........GNU..._.|
00000250  ca fb f7 11 b9 30 d4 c6  3e 86 52 bd 59 36 23 38  |.....0..>.R.Y6#8|
00000260  01 00 00 00 01 00 00 00  01 00 00 00 00 00 00 00  |................|
   ... (snip)
00000300  6e 00 5f 5f 67 6d 6f 6e  5f 73 74 61 72 74 5f 5f  |n.__gmon_start__|
00000310  00 47 4c 49 42 43 5f 32  2e 32 2e 35 00 00 00 00  |.GLIBC_2.2.5....|
00000320  02 00 02 00 00 00 00 00  01 00 01 00 01 00 00 00  |................|
00000330  10 00 00 00 00 00 00 00  75 1a 69 09 00 00 02 00  |........u.i.....|
00000340  31 00 00 00 00 00 00 00  c8 08 60 00 00 00 00 00  |1.........`.....|
00000350  06 00 00 00 03 00 00 00  00 00 00 00 00 00 00 00  |................|
00000360  e8 08 60 00 00 00 00 00  07 00 00 00 01 00 00 00  |..`.............|
00000370  00 00 00 00 00 00 00 00  f0 08 60 00 00 00 00 00  |..........`.....|
00000380  07 00 00 00 02 00 00 00  00 00 00 00 00 00 00 00  |................|
   ... (snip)

Here is a nicer hexadecimal dump with all sections clearly marked by the objdump command for the hello-gdb ELF object.

Hexadecimal dump for all sections of the hello-gdb ELF object.

$ objdump -s hello-gdb

hello-gdb:     file format elf64-x86-64

Contents of section .interp:
 400200 2f6c6962 36342f6c 642d6c69 6e75782d  /lib64/ld-linux-
 400210 7838362d 36342e73 6f2e3200           x86-64.so.2.
Contents of section .note.ABI-tag:
 40021c 04000000 10000000 01000000 474e5500  ............GNU.
 40022c 00000000 02000000 06000000 20000000  ............ ...
Contents of section .note.gnu.build-id:
 40023c 04000000 14000000 03000000 474e5500  ............GNU.
 40024c f7125f2e cafbf711 b930d4c6 3e8652bd  .._......0..>.R.
 40025c 59362338                             Y6#8
Contents of section .gnu.hash:
 400260 01000000 01000000 01000000 00000000  ................
 400270 00000000 00000000 00000000           ............
Contents of section .dynsym:
 400280 00000000 00000000 00000000 00000000  ................
 400290 00000000 00000000 0b000000 12000000  ................
   ... (snip)

Here is another hexadecimal dump for a section by the readelf command for the hello-gdb ELF object.

Hexadecimal dump for the .text section of the hello-gdb ELF object.

$ readelf -x.text hello-gdb

Hex dump of section '.text':
  0x00400410 31ed4989 d15e4889 e24883e4 f0505449 1.I..^H..H...PTI
  0x00400420 c7c0b005 400048c7 c1200540 0048c7c7 ....@.H.. .@.H..
  0x00400430 fd044000 e8b7ffff fff4660f 1f440000 ..@.......f..D..
  0x00400440 b8170960 0055482d 10096000 4883f80e ...`.UH-..`.H...
  0x00400450 4889e577 025dc3b8 00000000 4885c074 H..w.]......H..t
  0x00400460 f45dbf10 096000ff e00f1f80 00000000 .]...`..........
  0x00400470 b8100960 0055482d 10096000 48c1f803 ...`.UH-..`.H...
  0x00400480 4889e548 89c248c1 ea3f4801 d048d1f8 H..H..H..?H..H..
  0x00400490 75025dc3 ba000000 004885d2 74f45d48 u.]......H..t.]H
  0x004004a0 89c6bf10 096000ff e20f1f80 00000000 .....`..........
  0x004004b0 803d5904 20000075 11554889 e5e87eff .=Y. ..u.UH...~.
  0x004004c0 ffff5dc6 05460420 0001f3c3 0f1f4000 ..]..F. ......@.
  0x004004d0 48833d18 02200000 741eb800 00000048 H.=.. ..t......H
  0x004004e0 85c07414 55bff006 60004889 e5ffd05d ..t.U...`.H....]
  0x004004f0 e97bffff ff0f1f00 e973ffff ff554889 .{.......s...UH.
  0x00400500 e5bfc405 4000e8d5 feffffb8 00000000 ....@...........
  0x00400510 5dc3662e 0f1f8400 00000000 0f1f4000 ].f...........@.
  0x00400520 48896c24 d84c8964 24e0488d 2db70120 H.l$.L.d$.H.-..
  0x00400530 004c8d25 a8012000 48895c24 d04c896c .L.%.. .H.\$.L.l
  0x00400540 24e84c89 7424f04c 897c24f8 4883ec38 $.L.t$.L.|$.H..8
  0x00400550 4c29e541 89ff4989 f648c1fd 034989d5 L).A..I..H...I..
  0x00400560 31dbe841 feffff48 85ed741a 0f1f4000 1..A...H..t...@.
  0x00400570 4c89ea4c 89f64489 ff41ff14 dc4883c3 L..L..D..A...H..
  0x00400580 014839eb 75ea488b 5c240848 8b6c2410 .H9.u.H.\$.H.l$.
  0x00400590 4c8b6424 184c8b6c 24204c8b 7424284c L.d$.L.l$ L.t$(L
  0x004005a0 8b7c2430 4883c438 c30f1f80 00000000 .|$0H..8........
  0x004005b0 f3c3                                ..

As expected, these are all almost incomprehensible for human.

The readelf and objdump commands display the correct virtual memory address for the ELF object after this is loaded to the memory. The base address to load this is at 0x400000 (4 MiB) for GNU/Linux(amd64 = X86-64). The above plain hexadecimal dump displays the physical address in the file and does not count this base address offset in the virtual memory.

readelf -a

Here are all non-debug contents by the readelf command of the hello-gdb ELF object.

All contents by the readelf command for the hello-gdb ELF object.

$ readelf -a hello-gdb
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400410
  Start of program headers:          64 (bytes into file)
  Start of section headers:          3232 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         8
  Size of section headers:           64 (bytes)
  Number of section headers:         35
  Section header string table index: 32

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400200  00000200
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             000000000040021c  0000021c
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             000000000040023c  0000023c
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400260  00000260
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000400280  00000280
       0000000000000060  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           00000000004002e0  000002e0
       000000000000003d  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           000000000040031e  0000031e
       0000000000000008  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000400328  00000328
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400348  00000348
       0000000000000018  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000400360  00000360
       0000000000000048  0000000000000018   A       5    12     8
  [11] .init             PROGBITS         00000000004003a8  000003a8
       000000000000001a  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         00000000004003d0  000003d0
       0000000000000040  0000000000000010  AX       0     0     16
  [13] .text             PROGBITS         0000000000400410  00000410
       00000000000001a2  0000000000000000  AX       0     0     16
  [14] .fini             PROGBITS         00000000004005b4  000005b4
       0000000000000009  0000000000000000  AX       0     0     4
  [15] .rodata           PROGBITS         00000000004005c0  000005c0
       0000000000000012  0000000000000000   A       0     0     4
  [16] .eh_frame_hdr     PROGBITS         00000000004005d4  000005d4
       0000000000000034  0000000000000000   A       0     0     4
  [17] .eh_frame         PROGBITS         0000000000400608  00000608
       00000000000000d4  0000000000000000   A       0     0     8
  [18] .init_array       INIT_ARRAY       00000000006006e0  000006e0
       0000000000000008  0000000000000000  WA       0     0     8
  [19] .fini_array       FINI_ARRAY       00000000006006e8  000006e8
       0000000000000008  0000000000000000  WA       0     0     8
  [20] .jcr              PROGBITS         00000000006006f0  000006f0
       0000000000000008  0000000000000000  WA       0     0     8
  [21] .dynamic          DYNAMIC          00000000006006f8  000006f8
       00000000000001d0  0000000000000010  WA       6     0     8
  [22] .got              PROGBITS         00000000006008c8  000008c8
       0000000000000008  0000000000000008  WA       0     0     8
  [23] .got.plt          PROGBITS         00000000006008d0  000008d0
       0000000000000030  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000600900  00000900
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000600910  00000910
       0000000000000008  0000000000000000  WA       0     0     1
  [26] .comment          PROGBITS         0000000000000000  00000910
       0000000000000038  0000000000000001  MS       0     0     1
  [27] .debug_aranges    PROGBITS         0000000000000000  00000948
       0000000000000030  0000000000000000           0     0     1
  [28] .debug_info       PROGBITS         0000000000000000  00000978
       000000000000009f  0000000000000000           0     0     1
  [29] .debug_abbrev     PROGBITS         0000000000000000  00000a17
       0000000000000042  0000000000000000           0     0     1
  [30] .debug_line       PROGBITS         0000000000000000  00000a59
       000000000000003c  0000000000000000           0     0     1
  [31] .debug_str        PROGBITS         0000000000000000  00000a95
       00000000000000bc  0000000000000001  MS       0     0     1
  [32] .shstrtab         STRTAB           0000000000000000  00000b51
       0000000000000148  0000000000000000           0     0     1
  [33] .symtab           SYMTAB           0000000000000000  00001560
       0000000000000690  0000000000000018          34    50     8
  [34] .strtab           STRTAB           0000000000000000  00001bf0
       0000000000000237  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001c0 0x00000000000001c0  R E    8
  INTERP         0x0000000000000200 0x0000000000400200 0x0000000000400200
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000006dc 0x00000000000006dc  R E    200000
  LOAD           0x00000000000006e0 0x00000000006006e0 0x00000000006006e0
                 0x0000000000000230 0x0000000000000238  RW     200000
  DYNAMIC        0x00000000000006f8 0x00000000006006f8 0x00000000006006f8
                 0x00000000000001d0 0x00000000000001d0  RW     8
  NOTE           0x000000000000021c 0x000000000040021c 0x000000000040021c
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000005d4 0x00000000004005d4 0x00000000004005d4
                 0x0000000000000034 0x0000000000000034  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gn
u.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_
frame_hdr .eh_frame
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07

Dynamic section at offset 0x6f8 contains 24 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x4003a8
 0x000000000000000d (FINI)               0x4005b4
 0x0000000000000019 (INIT_ARRAY)         0x6006e0
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x6006e8
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x400260
 0x0000000000000005 (STRTAB)             0x4002e0
 0x0000000000000006 (SYMTAB)             0x400280
 0x000000000000000a (STRSZ)              61 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x6008d0
 0x0000000000000002 (PLTRELSZ)           72 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400360
 0x0000000000000007 (RELA)               0x400348
 0x0000000000000008 (RELASZ)             24 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x400328
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x40031e
 0x0000000000000000 (NULL)               0x0

Relocation section '.rela.dyn' at offset 0x348 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008c8  000300000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0

Relocation section '.rela.plt' at offset 0x360 contains 3 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
0000006008e8  000100000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
0000006008f0  000200000007 R_X86_64_JUMP_SLO 0000000000000000 __libc_start_main 
+ 0
0000006008f8  000300000007 R_X86_64_JUMP_SLO 0000000000000000 __gmon_start__ + 0

The decoding of unwind sections for machine type Advanced Micro Devices X86-64 i
s not currently supported.

Symbol table '.dynsym' contains 4 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLI
BC_2.2.5 (2)
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__

Symbol table '.symtab' contains 70 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000400200     0 SECTION LOCAL  DEFAULT    1
     2: 000000000040021c     0 SECTION LOCAL  DEFAULT    2
     3: 000000000040023c     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000400260     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000400280     0 SECTION LOCAL  DEFAULT    5
     6: 00000000004002e0     0 SECTION LOCAL  DEFAULT    6
     7: 000000000040031e     0 SECTION LOCAL  DEFAULT    7
     8: 0000000000400328     0 SECTION LOCAL  DEFAULT    8
     9: 0000000000400348     0 SECTION LOCAL  DEFAULT    9
    10: 0000000000400360     0 SECTION LOCAL  DEFAULT   10
    11: 00000000004003a8     0 SECTION LOCAL  DEFAULT   11
    12: 00000000004003d0     0 SECTION LOCAL  DEFAULT   12
    13: 0000000000400410     0 SECTION LOCAL  DEFAULT   13
    14: 00000000004005b4     0 SECTION LOCAL  DEFAULT   14
    15: 00000000004005c0     0 SECTION LOCAL  DEFAULT   15
    16: 00000000004005d4     0 SECTION LOCAL  DEFAULT   16
    17: 0000000000400608     0 SECTION LOCAL  DEFAULT   17
    18: 00000000006006e0     0 SECTION LOCAL  DEFAULT   18
    19: 00000000006006e8     0 SECTION LOCAL  DEFAULT   19
    20: 00000000006006f0     0 SECTION LOCAL  DEFAULT   20
    21: 00000000006006f8     0 SECTION LOCAL  DEFAULT   21
    22: 00000000006008c8     0 SECTION LOCAL  DEFAULT   22
    23: 00000000006008d0     0 SECTION LOCAL  DEFAULT   23
    24: 0000000000600900     0 SECTION LOCAL  DEFAULT   24
    25: 0000000000600910     0 SECTION LOCAL  DEFAULT   25
    26: 0000000000000000     0 SECTION LOCAL  DEFAULT   26
    27: 0000000000000000     0 SECTION LOCAL  DEFAULT   27
    28: 0000000000000000     0 SECTION LOCAL  DEFAULT   28
    29: 0000000000000000     0 SECTION LOCAL  DEFAULT   29
    30: 0000000000000000     0 SECTION LOCAL  DEFAULT   30
    31: 0000000000000000     0 SECTION LOCAL  DEFAULT   31
    32: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    33: 00000000006006f0     0 OBJECT  LOCAL  DEFAULT   20 __JCR_LIST__
    34: 0000000000400440     0 FUNC    LOCAL  DEFAULT   13 deregister_tm_clones
    35: 0000000000400470     0 FUNC    LOCAL  DEFAULT   13 register_tm_clones
    36: 00000000004004b0     0 FUNC    LOCAL  DEFAULT   13 __do_global_dtors_aux
    37: 0000000000600910     1 OBJECT  LOCAL  DEFAULT   25 completed.6392
    38: 00000000006006e8     0 OBJECT  LOCAL  DEFAULT   19 __do_global_dtors_aux
_fin
    39: 00000000004004d0     0 FUNC    LOCAL  DEFAULT   13 frame_dummy
    40: 00000000006006e0     0 OBJECT  LOCAL  DEFAULT   18 __frame_dummy_init_ar
ray_
    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS hello.c
    42: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    43: 00000000004006d8     0 OBJECT  LOCAL  DEFAULT   17 __FRAME_END__
    44: 00000000006006f0     0 OBJECT  LOCAL  DEFAULT   20 __JCR_END__
    45: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS
    46: 00000000006006e8     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_end
    47: 00000000006006f8     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC
    48: 00000000006006e0     0 NOTYPE  LOCAL  DEFAULT   18 __init_array_start
    49: 00000000006008d0     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_
    50: 00000000004005b0     2 FUNC    GLOBAL DEFAULT   13 __libc_csu_fini
    51: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMClon
eTab
    52: 0000000000600900     0 NOTYPE  WEAK   DEFAULT   24 data_start
    53: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@@GLIBC_2.2.5
    54: 0000000000600910     0 NOTYPE  GLOBAL DEFAULT   24 _edata
    55: 00000000004005b4     0 FUNC    GLOBAL DEFAULT   14 _fini
    56: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GL
IBC_
    57: 0000000000600900     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
    58: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    59: 0000000000600908     0 OBJECT  GLOBAL HIDDEN    24 __dso_handle
    60: 00000000004005c0     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    61: 0000000000400520   137 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    62: 0000000000600918     0 NOTYPE  GLOBAL DEFAULT   25 _end
    63: 0000000000400410     0 FUNC    GLOBAL DEFAULT   13 _start
    64: 0000000000600910     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start
    65: 00000000004004fd    21 FUNC    GLOBAL DEFAULT   13 main
    66: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _Jv_RegisterClasses
    67: 0000000000600910     0 OBJECT  GLOBAL HIDDEN    24 __TMC_END__
    68: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneT
able
    69: 00000000004003a8     0 FUNC    GLOBAL DEFAULT   11 _init

Version symbols section '.gnu.version' contains 4 entries:
 Addr: 000000000040031e  Offset: 0x00031e  Link: 5 (.dynsym)
  000:   0 (*local*)       2 (GLIBC_2.2.5)   2 (GLIBC_2.2.5)   0 (*local*)

Version needs section '.gnu.version_r' contains 1 entries:
 Addr: 0x0000000000400328  Offset: 0x000328  Link: 6 (.dynstr)
  000000: Version: 1  File: libc.so.6  Cnt: 1
  0x0010:   Name: GLIBC_2.2.5  Flags: none  Version: 2

Displaying notes found at file offset 0x0000021c with length 0x00000020:
  Owner                 Data size    Description
  GNU                  0x00000010    NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 2.6.32

Displaying notes found at file offset 0x0000023c with length 0x00000024:
  Owner                 Data size    Description
  GNU                  0x00000014    NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: f7125f2ecafbf711b930d4c63e8652bd59362338

The ELF file data structure is clearly analyzed excluding the debug contents.

The code content of the program is not disassembled.

readelf -wL

The readelf -wL command lists the decoded dump of debug contents of section .debug_line.

It lists the source file name with path. Then each C source line nember is matched with its starting address.

For the hello-gdb ELF object, the readelf -wL command lists the C source line numbers as follows.

All the source line numbers listed by the readelf -wL command for the hello-gdb ELF object.

$ readelf -wL hello-gdb
Decoded dump of debug contents of section .debug_line:

CU: hello.c:
File name                            Line number    Starting address
hello.c                                        5            0x4004fd
hello.c                                        6            0x400501
hello.c                                        7            0x40050b
hello.c                                        8            0x400510

TIP: The objdump -WL outputs very similar results. (The upper case W!)

TIP: All debug contents can be displayed at once by the readelf -w (or objdump -W) command.

objdump -d

Here is a disassembled code dump by the objdump command for the hello-gdb.o ELF object.

Disassembled code dump by the objdump command for the hello-gdb.o ELF object.

$ objdump -d hello-gdb.o

hello-gdb.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:    55                       push   %rbp
   1:    48 89 e5                 mov    %rsp,%rbp
   4:    bf 00 00 00 00           mov    $0x0,%edi
   9:    e8 00 00 00 00           callq  e <main+0xe>
   e:    b8 00 00 00 00           mov    $0x0,%eax
  13:    5d                       pop    %rbp
  14:    c3                       retq

Now we see the binary code in the readable assembler format.

Since code is not linked, some address data are left as 0 which will be filled by the linker.

Here is a disassembled code dump by the objdump command for the hello-gdb ELF object.

Disassembled code dump by the objdump command for the hello-gdb ELF object.

$ objdump -d hello-gdb

hello-gdb:     file format elf64-x86-64


Disassembly of section .init:

00000000004003a8 <_init>:
  4003a8:    48 83 ec 08              sub    $0x8,%rsp
  4003ac:    48 8b 05 15 05 20 00     mov    0x200515(%rip),%rax        # 6008c8
 <_DYNAMIC+0x1d0>
  4003b3:    48 85 c0                 test   %rax,%rax
  4003b6:    74 05                    je     4003bd <_init+0x15>
  4003b8:    e8 43 00 00 00           callq  400400 <__gmon_start__@plt>
  4003bd:    48 83 c4 08              add    $0x8,%rsp
  4003c1:    c3                       retq

Disassembly of section .plt:

00000000004003d0 <puts@plt-0x10>:
  4003d0:    ff 35 02 05 20 00        pushq  0x200502(%rip)        # 6008d8 <_GL
OBAL_OFFSET_TABLE_+0x8>
  4003d6:    ff 25 04 05 20 00        jmpq   *0x200504(%rip)        # 6008e0 <_G
LOBAL_OFFSET_TABLE_+0x10>
  4003dc:    0f 1f 40 00              nopl   0x0(%rax)

00000000004003e0 <puts@plt>:
  4003e0:    ff 25 02 05 20 00        jmpq   *0x200502(%rip)        # 6008e8 <_G
LOBAL_OFFSET_TABLE_+0x18>
  4003e6:    68 00 00 00 00           pushq  $0x0
  4003eb:    e9 e0 ff ff ff           jmpq   4003d0 <_init+0x28>

00000000004003f0 <__libc_start_main@plt>:
  4003f0:    ff 25 fa 04 20 00        jmpq   *0x2004fa(%rip)        # 6008f0 <_G
LOBAL_OFFSET_TABLE_+0x20>
  4003f6:    68 01 00 00 00           pushq  $0x1
  4003fb:    e9 d0 ff ff ff           jmpq   4003d0 <_init+0x28>

0000000000400400 <__gmon_start__@plt>:
  400400:    ff 25 f2 04 20 00        jmpq   *0x2004f2(%rip)        # 6008f8 <_G
LOBAL_OFFSET_TABLE_+0x28>
  400406:    68 02 00 00 00           pushq  $0x2
  40040b:    e9 c0 ff ff ff           jmpq   4003d0 <_init+0x28>

Disassembly of section .text:

0000000000400410 <_start>:
  400410:    31 ed                    xor    %ebp,%ebp
  400412:    49 89 d1                 mov    %rdx,%r9
  400415:    5e                       pop    %rsi
  400416:    48 89 e2                 mov    %rsp,%rdx
  400419:    48 83 e4 f0              and    $0xfffffffffffffff0,%rsp
  40041d:    50                       push   %rax
  40041e:    54                       push   %rsp
  40041f:    49 c7 c0 b0 05 40 00     mov    $0x4005b0,%r8
  400426:    48 c7 c1 20 05 40 00     mov    $0x400520,%rcx
  40042d:    48 c7 c7 fd 04 40 00     mov    $0x4004fd,%rdi
  400434:    e8 b7 ff ff ff           callq  4003f0 <__libc_start_main@plt>
  400439:    f4                       hlt
  40043a:    66 0f 1f 44 00 00        nopw   0x0(%rax,%rax,1)

0000000000400440 <deregister_tm_clones>:
  400440:    b8 17 09 60 00           mov    $0x600917,%eax
  400445:    55                       push   %rbp
  400446:    48 2d 10 09 60 00        sub    $0x600910,%rax
  40044c:    48 83 f8 0e              cmp    $0xe,%rax
  400450:    48 89 e5                 mov    %rsp,%rbp
  400453:    77 02                    ja     400457 <deregister_tm_clones+0x17>
  400455:    5d                       pop    %rbp
  400456:    c3                       retq
  400457:    b8 00 00 00 00           mov    $0x0,%eax
  40045c:    48 85 c0                 test   %rax,%rax
  40045f:    74 f4                    je     400455 <deregister_tm_clones+0x15>
  400461:    5d                       pop    %rbp
  400462:    bf 10 09 60 00           mov    $0x600910,%edi
  400467:    ff e0                    jmpq   *%rax
  400469:    0f 1f 80 00 00 00 00     nopl   0x0(%rax)

0000000000400470 <register_tm_clones>:
  400470:    b8 10 09 60 00           mov    $0x600910,%eax
  400475:    55                       push   %rbp
  400476:    48 2d 10 09 60 00        sub    $0x600910,%rax
  40047c:    48 c1 f8 03              sar    $0x3,%rax
  400480:    48 89 e5                 mov    %rsp,%rbp
  400483:    48 89 c2                 mov    %rax,%rdx
  400486:    48 c1 ea 3f              shr    $0x3f,%rdx
  40048a:    48 01 d0                 add    %rdx,%rax
  40048d:    48 d1 f8                 sar    %rax
  400490:    75 02                    jne    400494 <register_tm_clones+0x24>
  400492:    5d                       pop    %rbp
  400493:    c3                       retq
  400494:    ba 00 00 00 00           mov    $0x0,%edx
  400499:    48 85 d2                 test   %rdx,%rdx
  40049c:    74 f4                    je     400492 <register_tm_clones+0x22>
  40049e:    5d                       pop    %rbp
  40049f:    48 89 c6                 mov    %rax,%rsi
  4004a2:    bf 10 09 60 00           mov    $0x600910,%edi
  4004a7:    ff e2                    jmpq   *%rdx
  4004a9:    0f 1f 80 00 00 00 00     nopl   0x0(%rax)

00000000004004b0 <__do_global_dtors_aux>:
  4004b0:    80 3d 59 04 20 00 00     cmpb   $0x0,0x200459(%rip)        # 600910
 <__TMC_END__>
  4004b7:    75 11                    jne    4004ca <__do_global_dtors_aux+0x1a>
  4004b9:    55                       push   %rbp
  4004ba:    48 89 e5                 mov    %rsp,%rbp
  4004bd:    e8 7e ff ff ff           callq  400440 <deregister_tm_clones>
  4004c2:    5d                       pop    %rbp
  4004c3:    c6 05 46 04 20 00 01     movb   $0x1,0x200446(%rip)        # 600910
 <__TMC_END__>
  4004ca:    f3 c3                    repz retq
  4004cc:    0f 1f 40 00              nopl   0x0(%rax)

00000000004004d0 <frame_dummy>:
  4004d0:    48 83 3d 18 02 20 00     cmpq   $0x0,0x200218(%rip)        # 6006f0
 <__JCR_END__>
  4004d7:    00
  4004d8:    74 1e                    je     4004f8 <frame_dummy+0x28>
  4004da:    b8 00 00 00 00           mov    $0x0,%eax
  4004df:    48 85 c0                 test   %rax,%rax
  4004e2:    74 14                    je     4004f8 <frame_dummy+0x28>
  4004e4:    55                       push   %rbp
  4004e5:    bf f0 06 60 00           mov    $0x6006f0,%edi
  4004ea:    48 89 e5                 mov    %rsp,%rbp
  4004ed:    ff d0                    callq  *%rax
  4004ef:    5d                       pop    %rbp
  4004f0:    e9 7b ff ff ff           jmpq   400470 <register_tm_clones>
  4004f5:    0f 1f 00                 nopl   (%rax)
  4004f8:    e9 73 ff ff ff           jmpq   400470 <register_tm_clones>

00000000004004fd <main>:
  4004fd:    55                       push   %rbp
  4004fe:    48 89 e5                 mov    %rsp,%rbp
  400501:    bf c4 05 40 00           mov    $0x4005c4,%edi
  400506:    e8 d5 fe ff ff           callq  4003e0 <puts@plt>
  40050b:    b8 00 00 00 00           mov    $0x0,%eax
  400510:    5d                       pop    %rbp
  400511:    c3                       retq
  400512:    66 2e 0f 1f 84 00 00     nopw   %cs:0x0(%rax,%rax,1)
  400519:    00 00 00
  40051c:    0f 1f 40 00              nopl   0x0(%rax)

0000000000400520 <__libc_csu_init>:
  400520:    48 89 6c 24 d8           mov    %rbp,-0x28(%rsp)
  400525:    4c 89 64 24 e0           mov    %r12,-0x20(%rsp)
  40052a:    48 8d 2d b7 01 20 00     lea    0x2001b7(%rip),%rbp        # 6006e8
 <__init_array_end>
  400531:    4c 8d 25 a8 01 20 00     lea    0x2001a8(%rip),%r12        # 6006e0
 <__frame_dummy_init_array_entry>
  400538:    48 89 5c 24 d0           mov    %rbx,-0x30(%rsp)
  40053d:    4c 89 6c 24 e8           mov    %r13,-0x18(%rsp)
  400542:    4c 89 74 24 f0           mov    %r14,-0x10(%rsp)
  400547:    4c 89 7c 24 f8           mov    %r15,-0x8(%rsp)
  40054c:    48 83 ec 38              sub    $0x38,%rsp
  400550:    4c 29 e5                 sub    %r12,%rbp
  400553:    41 89 ff                 mov    %edi,%r15d
  400556:    49 89 f6                 mov    %rsi,%r14
  400559:    48 c1 fd 03              sar    $0x3,%rbp
  40055d:    49 89 d5                 mov    %rdx,%r13
  400560:    31 db                    xor    %ebx,%ebx
  400562:    e8 41 fe ff ff           callq  4003a8 <_init>
  400567:    48 85 ed                 test   %rbp,%rbp
  40056a:    74 1a                    je     400586 <__libc_csu_init+0x66>
  40056c:    0f 1f 40 00              nopl   0x0(%rax)
  400570:    4c 89 ea                 mov    %r13,%rdx
  400573:    4c 89 f6                 mov    %r14,%rsi
  400576:    44 89 ff                 mov    %r15d,%edi
  400579:    41 ff 14 dc              callq  *(%r12,%rbx,8)
  40057d:    48 83 c3 01              add    $0x1,%rbx
  400581:    48 39 eb                 cmp    %rbp,%rbx
  400584:    75 ea                    jne    400570 <__libc_csu_init+0x50>
  400586:    48 8b 5c 24 08           mov    0x8(%rsp),%rbx
  40058b:    48 8b 6c 24 10           mov    0x10(%rsp),%rbp
  400590:    4c 8b 64 24 18           mov    0x18(%rsp),%r12
  400595:    4c 8b 6c 24 20           mov    0x20(%rsp),%r13
  40059a:    4c 8b 74 24 28           mov    0x28(%rsp),%r14
  40059f:    4c 8b 7c 24 30           mov    0x30(%rsp),%r15
  4005a4:    48 83 c4 38              add    $0x38,%rsp
  4005a8:    c3                       retq
  4005a9:    0f 1f 80 00 00 00 00     nopl   0x0(%rax)

00000000004005b0 <__libc_csu_fini>:
  4005b0:    f3 c3                    repz retq

Disassembly of section .fini:

00000000004005b4 <_fini>:
  4005b4:    48 83 ec 08              sub    $0x8,%rsp
  4005b8:    48 83 c4 08              add    $0x8,%rsp
  4005bc:    c3                       retq

Now we see the binary code in the readable assembler format.

You also see many codes in addition to the main function existed in the hello-gdb.o ELF object since the linker seems to link few additional object files such as crt1.o, crti.o, etc.

Also some unresolved address references in the hello-gdb.o ELF object is resolved.

For example, let’s trace call puts in the assembler source hello.s as follows.

Code to call puts in the hello.s. (No address resolution)

    call    puts

We see the following for the relocatable object hello-gdb.o.

Code to call puts in the hello-gdb.o. (No address resolution)

     9:    e8 00 00 00 00           callq  e <main+0xe>

We see the following for the executable hello-gdb.

Code to call puts in the hello-gdb. (Address resolved)

4005b5:    e8 d6 fe ff ff           callq  400490 <puts@plt>

Later we will see the following under GDB.

Code to call puts in the hello-gdb viewed from (gdb) disassembler/r main. (Address resolved)

0x00000000004005b5 <+9>:	e8 d6 fe ff ff	callq  0x400490 <puts@plt>

objdump -S

Here is a disassembled code dump by the objdump command for the hello-gdb.o ELF object with the original C source code.

Disassembled code dump by the objdump command for the hello-gdb.o ELF object with the original C source code.

$ objdump -S hello-gdb.o

hello-gdb.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
#include <stdio.h>
#include <stdlib.h>
/* my first C program */
int main()
{
   0:    55                       push   %rbp
   1:    48 89 e5                 mov    %rsp,%rbp
    printf("Hello, world!\n");
   4:    bf 00 00 00 00           mov    $0x0,%edi
   9:    e8 00 00 00 00           callq  e <main+0xe>
    return EXIT_SUCCESS;
   e:    b8 00 00 00 00           mov    $0x0,%eax
}
  13:    5d                       pop    %rbp
  14:    c3                       retq

The ELF file only contains the location of the original C source code and correspondence to lines in it.

Since code is not linked, some address data are left as 0 which will be filled by the linker.

If you run objdump -S hello-gdb, you get a long disassembled list with the original C source code. Its addresses are resolved.

Core dump

When a user-process crashes, traditional Unix-like systems create a core file in the current directory if it is enabled. This is called core dump file which records the state of the working memory of the crashed user-process program. It is stored in the ELF file format on Linux.

In order to enable the creation of this core file, you need to set the core file size to unlimited with the shell’s ulimit -c unlimited command in advance.

Set the core file size to unlimited with ulimit -c unlimited.

$ ulimit -c
0
$ ulimit -c unlimited
$ ulimit -c
unlimited

Modern Linux system may behave somewhat differently. In order to achieve this simple classical core dump behavior, please ensure the following.

Please read the core(5) manpage and the ulimit section in the bash(1) manpage for more.

You can use GDB to inspect the core file as Debug: level 3: gdb prime8-gdb.

Previous Post Top Next Post