Inspired by this minimal ELF executable I created the following executable which works (and returns 42):
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 0300 0100 0000 5400 0008 3400 0000 ........T...4...
00000020: 0000 0000 0000 0000 3400 2000 0100 0000 ........4. .....
00000030: 0000 0000 0100 0000 0000 0000 0000 0008 ................
00000040: 0000 0008 6000 0000 6000 0000 0500 0000 ....`...`.......
00000050: 0000 0000 b801 0000 00bb 2a00 0000 cd80 ..........*.....
There is an ELF header here from 00
to 33
, a single program header from 34
to 53
and some code from 54
to 5F
.
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x8000054
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08000000 0x08000000 0x00060 0x00060 R E 0
If I now go ahead and change the p_vaddr and p_paddr from 0x8000000
to 0x1000
(or anything below 0x10000
) and adjust the entry point accordingly, I get an unexpected SEGFAULT. Here is the file after the adjustments:
00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
00000010: 0200 0300 0100 0000 5410 0000 3400 0000 ........T...4...
00000020: 0000 0000 0000 0000 3400 2000 0100 0000 ........4. .....
00000030: 0000 0000 0100 0000 0000 0000 0010 0000 ................
00000040: 0010 0000 6000 0000 6000 0000 0500 0000 ....`...`.......
00000050: 0000 0000 b801 0000 00bb 2a00 0000 cd80 ..........*.....
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x1054
Start of program headers: 52 (bytes into file)
Start of section headers: 0 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 0 (bytes)
Number of section headers: 0
Section header string table index: 0
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00001000 0x00001000 0x00060 0x00060 R E 0
This is surprising to me since GCC produces working executables with the following program header:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x00000034 0x00000034 0x00180 0x00180 R 0x4
INTERP 0x0001b4 0x000001b4 0x000001b4 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x00000000 0x00000000 0x00418 0x00418 R 0x1000
LOAD 0x001000 0x00001000 0x00001000 0x00524 0x00524 R E 0x1000
LOAD 0x002000 0x00002000 0x00002000 0x00228 0x00228 R 0x1000
LOAD 0x002ed4 0x00003ed4 0x00003ed4 0x00134 0x00138 RW 0x1000
DYNAMIC 0x002edc 0x00003edc 0x00003edc 0x000f8 0x000f8 RW 0x4
NOTE 0x0001c8 0x000001c8 0x000001c8 0x00060 0x00060 R 0x4
GNU_PROPERTY 0x0001ec 0x000001ec 0x000001ec 0x0001c 0x0001c R 0x4
GNU_EH_FRAME 0x002008 0x00002008 0x00002008 0x00074 0x00074 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x002ed4 0x00003ed4 0x00003ed4 0x0012c 0x0012c R 0x1
Can someone explain to me why changing the p_vaddr makes my program SEGFAULT?