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:
- The wikipedia: ELF
- The man page
elf
(5). - Linkers and Loaders (draft) for their mechanism.
- Understanding Memory for mechanism of the memory system on Linux.
- Executable and Linkable Format (ELF)
- GNU Binutils and BFD
An ELF file has two views:
- The section header lists the set of sections of the binary. (
readelf -S
) - The program header shows the segments used at run-time. (
readelf -l
)
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.
-g
flag produces debugging information in the operating system’s native format (DWARF on GNU/Linux).-v
flag produces verbose output of the commands executed to run the stages of compilation.
$ 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:
/usr/lib/gcc/x86_64-linux-gnu/4.7/cc1
which is roughly thegcc -S
command (Compiler from the C code to the assembler code).as
which is the assembler. (Thegcc -c
stops after this.)/usr/lib/gcc/x86_64-linux-gnu/4.7/collect2
which is roughly equivalent of the good oldld
(linker).
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.
- The
text
column is the size of the executable instructions of a program in the decimal expression. - The
data
column is the size of the initialized data that contribute to the program’s memory image in the decimal expression. - The
bss
column is the size of the uninitialized data that contributes to the program’s memory image in the decimal expression. - The
dec
column is the total size of thetext
,data
, andbss
sections in the decimal expression. - The
hex
column is the total size of thetext
,data
, andbss
sections in the hexadecimal expression.
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
.
PHDR
is for the program header table.INTERP
is for the interpreter path ASCIIZ string for starting the executable file.LOAD
is for the loadable segment. (may be repeated)DYNAMIC
is for the dynamic linking information.NOTE
is for auxiliary information.GNU_EH_FRAME
is for exception handling. (DWARF, see LSB Exception Frames)GNU_STACK
is for the controling the stack on Linux. (GNU extension)
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.
- Purge packages such as
apport-gtk
andapport
. - The
/proc/sys/kernel/core_pattern
file containscore
. - The
/proc/sys/kernel/core_uses_pid
file contains0
.
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 |