I've been playing around with object files and ELF files, and I compiled a very basic assembly program using gcc like so:
gcc -nostartfiles -static -nostdlib -fno-stack-protector -c test.s
And then linking with ld -o test test.o
. I was under the impression that this wouldn't link any C libraries or other code, and would purely assemble and build an executable from test.s
. When I run readelf -h test
, I get this output:
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: 0x401000
Start of program headers: 64 (bytes into file)
Start of section headers: 4416 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 4
Size of section headers: 64 (bytes)
Number of section headers: 6
Section header string table index: 5
which states that the entry point is address 0x401000. However, inspecting the output with hexdump, I noticed that my executable doesn't have an address 0x401000, and in fact ends at byte 0x0012C0. Where does the entry point address refer to?
Here is test.s:
.global _start
.text
_start:
mov $1, %rax # system call 1 is write
mov $1, %rdi # file handle 1 is stdout
mov $message, %rsi # address of string to output
mov $13, %rdx # number of bytes
syscall # invoke operating system to do the write
mov $60, %rax # system call 60 is exit
xor %rdi, %rdi # we want return code 0
syscall # invoke operating system to exit
message:
.ascii "Hello, world\n"