On Ubuntu 20.10 x86_64
my sample code:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("helloworld\n");
return 0;
}
Build:
gcc -o test test.c
Show entry point address:
readelf -h ./test
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: DYN (Shared object file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x1060
Start of program headers: 64 (bytes into file)
Start of section headers: 14824 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
Why does entry point address start at 0x1060 ? not 0x40000 ?
The binary is relocatable, and the segments have been packed against each other. The .text
segment starts at 0x1050 in the file, and the entry point is relative to its location in the file, not the location it will ultimately be loaded.
For a non-relocatable file try readelf -h /usr/lib/klibc/bin/sh
. This file is simpler in a number of ways, including not using an interpreter but actually being loaded as-is by the kernel.
We're not in x86
anymore. Relocatable binaries are the default for everything now, not just shared libraries. It's no longer a great pain to do relocatable stuff, and in a certain way it's cheaper than non-relocatable now because we have to emit the vector table anyway because the processor doesn't have 64 bit displacement.
As Nate Eldredge points out, compiling with -no-pie
yields a non-relocatable binary, and I have verified the expected start address appears.