2018-10-31-decoding-an-elf-binary.md (38070B)
1 +++ 2 title = "Hand-decoding an ELF binary image" 3 date = "2018-10-31T00:00:00Z" 4 slug = "decoding-an-elf-binary" 5 tags = ["Software"] 6 +++ 7 8 While recovering from some dentistry the other day I figured I'd have a go at 9 better understanding the ELF binary format. What better way to do that than to 10 compile a small program and hand-decode the resulting binary with a hex editor 11 and whatever ELF format spec I could find. 12 13 Overview 14 -------- 15 16 Below, we'll use `nasm` to build a small assembly Hello World program to a 17 64-bit ELF object file, then link that into an ELF executable with GNU `ld`. 18 Finally, we'll run the resulting object file and binary image through `xxd` and 19 hand-decode the resulting hex. 20 21 The code and instructions below work on FreeBSD 11 on x86_64 hardware. For 22 other operating systems, hardware, and toolchains, you're on your own! I'd 23 imagine this should all work just fine on Linux. If I get bored one day, I may 24 redo this for Mach-O binaries on macOS. 25 26 hello.asm 27 --------- 28 29 First we'll bang up a minimal Hello World program in assembly. In the `.data` 30 section, we add a null-terminated string, `hello`, and its length `hbytes`. In 31 the program text, we set up and execute the `write(stdout, hello, hbytes)` 32 syscall, then set up and execute an `exit(0)` syscall. 33 34 Note that 64-bit FreeBSD, macOS, and Linux all use the SysV AMD64 calling 35 convention. For calls against the kernel interface, the syscall number is 36 stored in `rax` and up to six parameters are passed, in order, in `rdi`, `rsi`, 37 `rdx`, `r10`, `r8`, `r9`. For user calls, replace `r10` with `rcx` in this 38 list, and pass further arguments on the stack. In all cases, the return value 39 is passed through `rax`. More details can be found in section A.2.1 of the 40 [System V AMD64 ABI Reference][amd64_abi]. 41 42 ; hello.asm 43 44 %define stdin 0 45 %define stdout 1 46 %define stderr 2 47 %define SYS_exit 1 48 %define SYS_write 4 49 50 %macro system 1 51 mov rax, %1 52 syscall 53 %endmacro 54 55 %macro sys.exit 0 56 system SYS_exit 57 %endmacro 58 59 %macro sys.write 0 60 system SYS_write 61 %endmacro 62 63 section .data 64 hello db 'Hello, World!', 0Ah 65 hbytes equ $-hello 66 67 section .text 68 global _start 69 _start: 70 mov rdi, stdout 71 mov rsi, hello 72 mov rdx, hbytes 73 sys.write 74 75 xor rdi,rdi 76 sys.exit 77 78 Compile to object code 79 ---------------------- 80 81 Next, we'll compile `hello.asm` to a 64-bit ELF object file using `nasm`: 82 83 % nasm -f elf64 hello.asm 84 85 This emits `hello.o`, an 880-byte ELF-64 object file. Since we haven't yet run 86 this through the linker, addresses of global symbols (in this case, `hello`) 87 are not yet known and thus left with address 0x0 placeholders. We can see this 88 in the `movabs` instruction at offset 0x15 of the `.text` section below. 89 90 The relocation section (Section 6: `.rela.text`) contains an entry for each 91 symbolic reference that needs to be filled in by the linker. In this case 92 there's just a single entry for the symbol `hello` (which points to our hello 93 world string). The relocation table entry's `r_offset` indicates the address to 94 replace is at an offset of 0x7 into the section of the associated symbol table 95 entry. Its `r_info` (0x0000000200000001) encodes a relocation type in its lower 96 4 bytes (0x1: `R_AMD64_64`) and the associated symbol table entry in its upper 97 4 bytes (0x2, which, if we look it up in the symbol table is the `.text` 98 section). The `r_addend` field (0x0) specifies an additional adjustment to the 99 substituted symbol to be applied at link time; specifically, for the 100 `R_AMD64_64`, the final address is computed as S + A, where S is the 101 substituted symbol value (in our case, the address of `hello`) and A is the 102 addend (in our case, 0x0). 103 104 Without further ado, let's dump the object file: 105 106 % xxd hello.o 107 108 With whatever ELF64 [linker & loader guide][guide_linker] we can find at hand, 109 let's get decoding this thing: 110 111 ### ELF Header 112 113 |00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000| .ELF............ 114 |00000010: 0100 3e00 0100 0000 0000 0000 0000 0000| ..>............. 115 |00000020: 0000 0000 0000 0000 4000 0000 0000 0000| ........@....... 116 |00000030: 0000 0000 4000 0000 0000 4000 0700 0300| ....@.....@..... 117 118 e_ident[EI_MAG0..EI_MAG3] 0x7f + ELF Magic 119 e_ident[EI_CLASS] 0x02 64-bit 120 e_ident[EI_DATA] 0x01 Little-endian 121 e_ident[EI_VERSION] 0x01 ELF v1 122 e_ident[EI_OSABI] 0x00 System V 123 e_ident[EI_ABIVERSION] 0x00 Unused 124 e_ident[EI_PAD] 0x00000000000000 7 bytes unused padding 125 e_type 0x0001 ET_REL 126 e_machine 0x003e x86_64 127 e_version 0x00000001 Version 1 128 e_entry 0x0000000000000000 Entrypoint address (none) 129 e_phoff 0x0000000000000000 Program header table offset in image 130 e_shoff 0x0000000000000040 Section header table offset in image 131 e_flags 0x00000000 Architecture-dependent interpretation 132 e_ehsize 0x0040 Size of this ELF header (64B) 133 e_phentsize 0x0000 Size of program header table entry 134 e_phnum 0x0000 Number of program header table entries 135 e_shentsize 0x0040 Size of section header table entry (64B) 136 e_shnum 0x0007 Number of section header table entries 137 e_shstrndx 0x0003 Index of section header for .shstrtab 138 139 140 ### Section header table: Entry 0 (null) 141 142 |00000040: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 143 |00000050: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 144 |00000060: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 145 |00000070: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 146 147 sh_name 0x00000000 Offset into .shstrtab 148 sh_type 0x00000000 SHT_NULL 149 sh_flags 0x0000000000000000 Section attributes 150 sh_addr 0x0000000000000000 Virtual address of section in memory 151 sh_offset 0x0000000000000000 Offset of section in file image 152 sh_size 0x0000000000000000 Size in bytes of section in file image 153 sh_link 0x00000000 Section index of associated section 154 sh_info 0x00000000 Extra info about section 155 sh_addralign 0x0000000000000000 Alignment 156 sh_entsize 0x0000000000000000 Size in bytes of each entry 157 158 159 ### Section header table: Entry 1 (.data) 160 161 |00000080: 0100 0000 0100 0000 0300 0000 0000 0000| ................ 162 |00000090: 0000 0000 0000 0000 0002 0000 0000 0000| ................ 163 |000000a0: 0e00 0000 0000 0000 0000 0000 0000 0000| ................ 164 |000000b0: 0400 0000 0000 0000 0000 0000 0000 0000| ................ 165 166 sh_name 0x00000001 Offset into .shstrtab 167 sh_type 0x00000001 SHT_PROGBITS 168 sh_flags 0x0000000000000003 SHF_WRITE | SHF_ALLOC 169 sh_addr 0x0000000000000000 Virtual address of section in memory 170 sh_offset 0x0000000000000200 Offset of section in file image 171 sh_size 0x000000000000000e Size in bytes of section in file image 172 sh_link 0x00000000 Section index of associated section 173 sh_info 0x00000000 Extra info about section 174 sh_addralign 0x0000000000000004 Alignment 175 sh_entsize 0x0000000000000000 Size in bytes of each entry 176 177 178 ### Section header table: Entry 2 (.text) 179 180 |000000c0: 0700 0000 0100 0000 0600 0000 0000 0000| ................ 181 |000000d0: 0000 0000 0000 0000 1002 0000 0000 0000| ................ 182 |000000e0: 2500 0000 0000 0000 0000 0000 0000 0000| %............... 183 |000000f0: 1000 0000 0000 0000 0000 0000 0000 0000| ................ 184 185 sh_name 0x00000007 Offset into .shstrtab 186 sh_type 0x00000001 SHT_PROGBITS 187 sh_flags 0x0000000000000006 SHF_ALLOC | SHF_EXECINSTR 188 sh_addr 0x0000000000000000 Virtual address of section in memory 189 sh_offset 0x0000000000000210 Offset of section in file image 190 sh_size 0x0000000000000025 Size in bytes of section in file image 191 sh_link 0x00000000 Section index of associated section 192 sh_info 0x00000000 Extra info about section 193 sh_addralign 0x0000000000000001 Alignment 194 sh_entsize 0x0000000000000000 Size in bytes of each entry 195 196 197 ### Section header table: Entry 3 (.shstrtab) 198 199 |00000100: 0d00 0000 0300 0000 0000 0000 0000 0000| ................ 200 |00000110: 0000 0000 0000 0000 4002 0000 0000 0000| ........@....... 201 |00000120: 3200 0000 0000 0000 0000 0000 0000 0000| 2............... 202 |00000130: 0100 0000 0000 0000 0000 0000 0000 0000| ................ 203 204 sh_name 0x0000000d Offset into .shstrtab 205 sh_type 0x00000003 SHT_STRTAB 206 sh_flags 0x0000000000000000 Section attributes 207 sh_addr 0x0000000000000000 Virtual address of section in memory 208 sh_offset 0x0000000000000240 Offset of section in file image 209 sh_size 0x0000000000000032 Size in bytes of section in file image 210 sh_link 0x00000000 Section index of associated section 211 sh_info 0x00000000 Extra info about section 212 sh_addralign 0x0000000000000001 Alignment 213 sh_entsize 0x0000000000000000 Size in bytes of each entry 214 215 216 ### Section header table: Entry 4 (.symtab) 217 218 |00000140: 1700 0000 0200 0000 0000 0000 0000 0000| ................ 219 |00000150: 0000 0000 0000 0000 8002 0000 0000 0000| ................ 220 |00000160: a800 0000 0000 0000 0500 0000 0600 0000| ................ 221 |00000170: 0800 0000 0000 0000 1800 0000 0000 0000| ................ 222 223 sh_name 0x00000017 Offset into .shstrtab 224 sh_type 0x00000002 SHT_SYMTAB 225 sh_flags 0x0000000000000000 Section attributes 226 sh_addr 0x0000000000000000 Virtual address of section in memory 227 sh_offset 0x0000000000000280 Offset of section in file image 228 sh_size 0x00000000000000a8 Size in bytes of section in file image 229 sh_link 0x00000005 Section index of associated section 230 sh_info 0x00000006 Extra info about section 231 sh_addralign 0x0000000000000008 Alignment 232 sh_entsize 0x0000000000000018 Size in bytes of each entry 233 234 235 ### Section header table: Entry 5 (.strtab) 236 237 |00000180: 1f00 0000 0300 0000 0000 0000 0000 0000| ................ 238 |00000190: 0000 0000 0000 0000 3003 0000 0000 0000| ........0....... 239 |000001a0: 1f00 0000 0000 0000 0000 0000 0000 0000| ................ 240 |000001b0: 0100 0000 0000 0000 0000 0000 0000 0000| ................ 241 242 sh_name 0x0000001f Offset into .shstrtab 243 sh_type 0x00000003 SHT_STRTAB 244 sh_flags 0x0000000000000000 Section attributes 245 sh_addr 0x0000000000000000 Virtual address of section in memory 246 sh_offset 0x0000000000000330 Offset of section in file image 247 sh_size 0x000000000000001f Size in bytes of section in file image 248 sh_link 0x00000000 Section index of associated section 249 sh_info 0x00000000 Extra info about section 250 sh_addralign 0x0000000000000001 Alignment 251 sh_entsize 0x0000000000000000 Size in bytes of each entry 252 253 254 ### Section header table: Entry 6 (.rela.text) 255 256 |000001c0: 2700 0000 0400 0000 0000 0000 0000 0000| '............... 257 |000001d0: 0000 0000 0000 0000 5003 0000 0000 0000| ........P....... 258 |000001e0: 1800 0000 0000 0000 0400 0000 0200 0000| ................ 259 |000001f0: 0800 0000 0000 0000 1800 0000 0000 0000| ................ 260 261 sh_name 0x00000027 Offset into .shstrtab 262 sh_type 0x00000004 SHT_RELA 263 sh_flags 0x0000000000000000 Section attributes 264 sh_addr 0x0000000000000000 Virtual address of section in memory 265 sh_offset 0x0000000000000350 Offset of section in file image 266 sh_size 0x0000000000000018 Size in bytes of section in file image 267 sh_link 0x00000004 Section index of associated section 268 sh_info 0x00000002 Extra info about section 269 sh_addralign 0x0000000000000008 Alignment 270 sh_entsize 0x0000000000000018 Size in bytes of each entry 271 272 273 ### Section 1: .data (SHT_PROGBITS; SHF_WRITE | SHF_ALLOC) 274 275 |00000200: 4865 6c6c 6f2c 2057 6f72 6c64 210a 0000| Hello, World!... 276 277 0x000000 'Hello, World!\n' 278 Zero-padding (2 bytes starting at 0x20e) 279 280 281 ### Section 2: .text (SHT_PROGBITS; SHF_ALLOC | SHF_EXECINSTR) 282 283 |00000210: bf01 0000 0048 be00 0000 0000 0000 00ba| .....H.......... 284 |00000220: 0e00 0000 b804 0000 000f 0548 31ff b801| ...........H1... 285 |00000230: 0000 000f 0500 0000 0000 0000 0000 0000| ................ 286 287 0x00000010 mov edi, 0x1 288 0x00000015 movabs rsi, 0x000000 (placeholder for db hello) 289 0x0000001f mov edx, 0xe 290 0x00000024 mov eax, 0x4 291 0x00400029 syscall 292 0x0040002b xor rdi, rdi 293 0x0040002e mov eax, 0x1 294 0x00400033 syscall 295 Zero-padding (11 bytes starting at 0x235) 296 297 298 ### Section 3: .shstrtab (SHT_STRTAB;) 299 300 |00000240: 002e 6461 7461 002e 7465 7874 002e 7368| ..data..text..sh 301 |00000250: 7374 7274 6162 002e 7379 6d74 6162 002e| strtab..symtab.. 302 |00000260: 7374 7274 6162 002e 7265 6c61 2e74 6578| strtab..rela.tex 303 |00000270: 7400 0000 0000 0000 0000 0000 0000 0000| t............... 304 305 0x00000000: '' 306 0x00000001: '.data' 307 0x00000007: '.text' 308 0x0000000d: '.shstrtab' 309 0x00000017: '.symtab' 310 0x0000001f: '.strtab' 311 0x00000027: '.rela.text' 312 Zero-padding (14 bytes starting at 0x272) 313 314 315 ### Section 4: .symtab' (SHT_SYMTAB;) 316 317 #### Symbol table entry 0 318 |00000280: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 319 |00000290: 0000 0000 0000 0000 | ........ 320 321 st_name 0x00000000 322 st_info 0x00 323 st_other 0x00 324 st_shndx 0x0000 (SHN_UNDEF) 325 st_value 0x0000000000000000 326 st_size 0x0000000000000000 327 328 #### Symbol table entry 1 (hello.asm) 329 |00000298: 0100 0000 0400 f1ff| ........ 330 |000002a0: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 331 332 st_name 0x00000001 333 st_info 0x04 (STT_FILE) 334 st_other 0x00 335 st_shndx 0xfff1 (SHN_ABS) 336 st_value 0x0000000000000000 337 st_size 0x0000000000000000 338 339 #### Symbol table entry 2 340 |000002b0: 0000 0000 0300 0100 0000 0000 0000 0000| ................ 341 |000002c0: 0000 0000 0000 0000 | ........ 342 343 st_name 0x00000000 344 st_info 0x03 (STT_OBJECT | STT_FUNC) 345 st_other 0x00 346 st_shndx 0x0001 (Section 1: .data) 347 st_value 0x0000000000000000 348 st_size 0x0000000000000000 349 350 #### Symbol table entry 3 351 |000002c8: 0000 0000 0300 0200| ........ 352 |000002d0: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 353 354 st_name 0x00000000 355 st_info 0x03 (STT_OBJECT | STT_FUNC) 356 st_other 0x00 357 st_shndx 0x0002 (Section 2: .text) 358 st_value 0x0000000000000000 359 st_size 0x0000000000000000 360 361 #### Symbol table entry 4 (hello) 362 |000002e0: 0b00 0000 0000 0100 0000 0000 0000 0000| ................ 363 |000002f0: 0000 0000 0000 0000 | ........ 364 365 st_name 0x0000000b 366 st_info 0x00 367 st_other 0x00 368 st_shndx 0x0001 (Section 1: .data) 369 st_value 0x0000000000000000 370 st_size 0x0000000000000000 371 372 ### Symbol table entry 5 (hbytes) 373 |000002f8: 1100 0000 0000 f1ff| ........ 374 |00000300: 0e00 0000 0000 0000 0000 0000 0000 0000| ................ 375 376 st_name 0x00000011 377 st_info 0x00 378 st_other 0x00 379 st_shndx 0xfff1 (SHN_ABS) 380 st_value 0x000000000000000e 381 st_size 0x0000000000000000 382 383 #### Symbol table entry 6 (_start) 384 |00000310: 1800 0000 1000 0200 0000 0000 0000 0000| ................ 385 |00000320: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 386 387 st_name 0x00000018 388 st_info 0x01 (STT_OBJECT) 389 st_other 0x00 390 st_shndx 0x0002 (Section 2: .text) 391 st_value 0x0000000000000000 392 st_size 0x0000000000000000 393 Zero-padding (8 bytes starting at 0x328) 394 395 396 ### Section 5: .strtab (SHT_STRTAB;) 397 398 |00000330: 0068 656c 6c6f 2e61 736d 0068 656c 6c6f| .hello.asm.hello 399 |00000340: 0068 6279 7465 7300 5f73 7461 7274 0000| .hbytes._start.. 400 401 0x00000000: '' 402 0x00000001: 'hello.asm' 403 0x0000000b: 'hello' 404 0x00000011: 'hbytes' 405 0x00000018: '_start' 406 Zero-padding (1 byte starting at 0x34f) 407 408 409 ### Section 6: .rela.text (SHT_RELA;) 410 411 |00000350: 0700 0000 0000 0000 0100 0000 0200 0000| ................ 412 |00000360: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 413 414 r_offset 0x0000000000000007 415 r_info 0x0000000200000001 (Symbol table entry 2, type R_AMD64_64) 416 r_addend 0x0000000000000000 417 Zero-padding (8 bytes starting at 0x368) 418 419 420 Link to executable image 421 ------------------------ 422 423 Next, let's link `hello.o` into a 64-bit ELF executable: 424 425 % ld -o hello hello.o 426 427 This emits `hello`, a 951-byte ELF-64 executable image. 428 429 Since the linker has decided which segment each section maps into (if any) and 430 what the segment addresses are, addresses are now known for all (statically 431 linked) symbols, and address 0x0 placeholders have been replaced with actual 432 addresses. We can see this in the `mov` instruction at address 0x4000b5, which 433 now specifies an address of 0x6000d8. 434 435 Running the linked executable image through `xxd` as above and picking our 436 trusty linker & loader guide back up, here we go again: 437 438 ### ELF Header 439 440 |00000000: 7f45 4c46 0201 0109 0000 0000 0000 0000| .ELF............ 441 |00000010: 0200 3e00 0100 0000 b000 4000 0000 0000| ..>.......@..... 442 |00000020: 4000 0000 0000 0000 1001 0000 0000 0000| @............... 443 |00000030: 0000 0000 4000 3800 0200 4000 0600 0300| ....@.8...@..... 444 445 e_ident[EI_MAG0..EI_MAG3] 0x7f + ELF Magic 446 e_ident[EI_CLASS] 0x02 64-bit 447 e_ident[EI_DATA] 0x01 Little-endian 448 e_ident[EI_VERSION] 0x01 ELF v1 449 e_ident[EI_OSABI] 0x09 FreeBSD 450 e_ident[EI_ABIVERSION] 0x00 Unused 451 e_ident[EI_PAD] 0x0000000000 7 bytes unused padding 452 e_type 0x0002 ET_EXEC 453 e_machine 0x003e x86_64 454 e_version 0x00000001 Version 1 455 e_entry 0x00000000004000b0 Entrypoint addr 456 e_phoff 0x0000000000000040 Program header table offset in image 457 e_shoff 0x0000000000000110 Section header table offset in image 458 e_flags 0x00000000 Architecture-dependent interpretation 459 e_ehsize 0x0040 Size of this ELF header 460 e_phentsize 0x0038 Size of program header table entry 461 e_phnum 0x0002 Number of program header table entries 462 e_shentsize 0x0040 Size of section header table entry 463 e_shnum 0x0006 Number of section header table entries 464 e_shstrndx 0x0003 Index of section header for .shstrtab 465 466 467 ### Program header table: Entry 0 (PF_X | PF_R) 468 469 |00000040: 0100 0000 0500 0000 0000 0000 0000 0000| ................ 470 |00000050: 0000 4000 0000 0000 0000 4000 0000 0000| ..@.......@..... 471 |00000060: d500 0000 0000 0000 d500 0000 0000 0000| ................ 472 |00000070: 0000 2000 0000 0000 | .. ............. 473 474 p_type 0x00000001 PT_LOAD 475 p_flags 0x00000005 PF_X | PF_R 476 p_offset 0x00000000 Offset of segment in file image 477 p_vaddr 0x0000000000400000 Virtual address of segment in memory 478 p_paddr 0x0000000000400000 Physical address of segment 479 p_filesz 0x00000000000000d5 Size in bytes of segment in file image 480 p_memsz 0x00000000000000d5 Size in bytes of segment in memory 481 p_align 0x0000000000200000 Alignment (2MB) 482 483 484 ### Program header table: Entry 1 (PF_W | PF_R) 485 486 |00000078: 0100 0000 0600 0000| ........ 487 |00000080: d800 0000 0000 0000 d800 6000 0000 0000| ..........`..... 488 |00000090: d800 6000 0000 0000 0e00 0000 0000 0000| ..`............. 489 |000000a0: 0e00 0000 0000 0000 0000 2000 0000 0000| .......... ..... 490 491 p_type 0x00000001 PT_LOAD 492 p_flags 0x00000006 PF_W | PF_R 493 p_offset 0x00000000000000d8 Offset of segment in file image 494 p_vaddr 0x00000000006000d8 Virtual address of segment in memory 495 p_paddr 0x00000000006000d8 Physical address of segment 496 p_filesz 0x000000000000000e Size in bytes of segment in file image 497 p_memsz 0x000000000000000e Size in bytes of segment in memory 498 p_align 0x0000000000200000 Alignment (2MB) 499 500 501 ### Section 1: .text (SHT_PROGBITS; SHF_ALLOC | SHF_EXECINSTR) 502 503 |000000b0: bf01 0000 0048 bed8 0060 0000 0000 00ba| .....H...`...... 504 |000000c0: 0e00 0000 b804 0000 000f 0548 31ff b801| ...........H1... 505 |000000d0: 0000 000f 05 | ..... 506 507 0x4000b0 mov edi, 0x1 508 0x4000b5 movabs rsi, 0x6000d8 509 0x4000bf mov edx, 0xe 510 0x4000c4 mov eax, 0x4 511 0x4000c9 syscall 512 0x4000cb xor rdi, rdi 513 0x4000ce mov eax, 0x1 514 0x4000d3 syscall 515 Zero-padding (5 bytes starting at 0x000000d5) 516 517 518 ### Section 2: .data (SHT_PROGBITS; SHF_WRITE | SHF_ALLOC) 519 520 |000000d8: 4865 6c6c 6f2c 2057| Hello, W 521 |000000e0: 6f72 6c64 210a | orld!. 522 523 0x6000d8 'Hello, World!\n' 524 525 526 ### Section 3: .shstrtab (SHT_STRTAB;) 527 528 |000000e6: 002e 7379 6d74 6162 002e| ..symtab.. 529 |000000f0: 7374 7274 6162 002e 7368 7374 7274 6162| strtab..shstrtab 530 |00000100: 002e 7465 7874 002e 6461 7461 0000 0000| ..text..data. 531 532 0x00000000: '' 533 0x00000001: '.symtab' 534 0x00000009: '.strtab' 535 0x00000011: '.shstrtab' 536 0x0000001b: '.text' 537 0x00000021: '.data' 538 Zero-padding (3 bytes starting at 0x0000010d) 539 540 541 ### Section header table: Entry 0 (null) 542 543 |00000110: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 544 |00000120: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 545 |00000130: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 546 |00000140: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 547 548 sh_name 0x00000000 Offset into .shstrtab 549 sh_type 0x00000000 SHT_NULL 550 sh_flags 0x0000000000000000 Section attributes 551 sh_addr 0x0000000000000000 Virtual address of section in memory 552 sh_offset 0x0000000000000000 Offset of section in file image 553 sh_size 0x0000000000000000 Size in bytes of section in file image 554 sh_link 0x00000000 Section index of associated section 555 sh_info 0x00000000 Extra info about section 556 sh_addralign 0x0000000000000000 Alignment 557 sh_entsize 0x0000000000000000 Size in bytes of each entry 558 559 560 ### Section header table: Entry 1 (.text) 561 562 |00000150: 1b00 0000 0100 0000 0600 0000 0000 0000| ................ 563 |00000160: b000 4000 0000 0000 b000 0000 0000 0000| ..@............. 564 |00000170: 2500 0000 0000 0000 0000 0000 0000 0000| %............... 565 |00000180: 1000 0000 0000 0000 0000 0000 0000 0000| ................ 566 567 sh_name 0x0000001b Offset into .shstrtab 568 sh_type 0x00000001 SHT_PROGBITS 569 sh_flags 0x00000006 SHF_ALLOC | SHF_EXECINSTR 570 sh_addr 0x00000000004000b0 Virtual address of section in memory 571 sh_offset 0x00000000000000b0 Offset of section in file image 572 sh_size 0x0000000000000025 Size in bytes of section in file image 573 sh_link 0x00000000 Section index of associated section 574 sh_info 0x00000000 Extra info about section 575 sh_addralign 0x0000000000000010 Alignment (2B) 576 sh_entsize 0x0000000000000000 Size in bytes of each entry 577 578 579 ### Section header table: Entry 2 (.data) 580 581 |00000190: 2100 0000 0100 0000 0300 0000 0000 0000| !............... 582 |000001a0: d800 6000 0000 0000 d800 0000 0000 0000| ..`............. 583 |000001b0: 0e00 0000 0000 0000 0000 0000 0000 0000| ................ 584 |000001c0: 0400 0000 0000 0000 0000 0000 0000 0000| ................ 585 586 sh_name 0x00000021 Offset into .shstrtab 587 sh_type 0x00000001 SHT_PROGBITS 588 sh_flags 0x0000000000000003 SHF_WRITE | SHF_ALLOC 589 sh_addr 0x00000000006000d8 Virtual address of section in memory 590 sh_offset 0x00000000000000d8 Offset of section in file image 591 sh_size 0x000000000000000e Size in bytes of section in file image 592 sh_link 0x00000000 Section index of associated section 593 sh_info 0x00000000 Extra info about section 594 sh_addralign 0x0000000000000004 Alignment (4B) 595 sh_entsize 0x0000000000000000 Size in bytes of each entry 596 597 598 ### Section header table: Entry 3 (.shstrtab) 599 600 |000001d0: 1100 0000 0300 0000 0000 0000 0000 0000| ................ 601 |000001e0: 0000 0000 0000 0000 e600 0000 0000 0000| ................ 602 |000001f0: 2700 0000 0000 0000 0000 0000 0000 0000| '............... 603 |00000200: 0100 0000 0000 0000 0000 0000 0000 0000| ................ 604 605 sh_name 0x00000011 Offset into .shstrtab 606 sh_type 0x00000003 SHT_STRTAB 607 sh_flags 0x00000000 No flags 608 sh_addr 0x0000000000000000 Virtual address of section in memory 609 sh_offset 0x00000000000000e6 Offset of section in file image 610 sh_size 0x0000000000000027 Size in bytes of section in file image 611 sh_link 0x00000000 Section index of associated section 612 sh_info 0x00000000 Extra info about section 613 sh_addralign 0x0000000000000001 Alignment (1B) 614 sh_entsize 0x0000000000000000 Size in bytes of each entry 615 616 617 ### Section header table: Entry 4 (.symtab) 618 619 |00000210: 0100 0000 0200 0000 0000 0000 0000 0000| ................ 620 |00000220: 0000 0000 0000 0000 9002 0000 0000 0000| ................ 621 |00000230: f000 0000 0000 0000 0500 0000 0600 0000| ................ 622 |00000240: 0800 0000 0000 0000 1800 0000 0000 0000| ................ 623 624 sh_name 0x00000001 Offset into .shstrtab 625 sh_type 0x00000002 SHT_SYMTAB 626 sh_flags 0x00000000 No flags 627 sh_addr 0x0000000000000000 Virtual address of section in memory 628 sh_offset 0x0000000000000290 Offset of section in file image 629 sh_size 0x00000000000000f0 Size in bytes of section in file image 630 sh_link 0x00000005 Section index of associated section 631 sh_info 0x00000006 Flags 632 sh_addralign 0x0000000000000008 Alignment (8B) 633 sh_entsize 0x0000000000000018 Size in bytes of each entry (24B) 634 635 636 ### Section header table: Entry 5 (.strtab) 637 638 |00000250: 0900 0000 0300 0000 0000 0000 0000 0000| ................ 639 |00000260: 0000 0000 0000 0000 8003 0000 0000 0000| ................ 640 |00000270: 3700 0000 0000 0000 0000 0000 0000 0000| 7............... 641 |00000280: 0100 0000 0000 0000 0000 0000 0000 0000| ................ 642 643 sh_name 0x00000009 Offset into .shstrtab 644 sh_type 0x00000003 SHT_STRTAB 645 sh_flags 0x0000000000000000 No flags 646 sh_addr 0x0000000000000000 Virtual address of section in memory 647 sh_offset 0x0000000000000380 Offset of section in file image 648 sh_size 0x0000000000000037 Size in bytes of section in file image 649 sh_link 0x00000000 Section index of associated section 650 sh_info 0x00000000 Extrac info about section 651 sh_addralign 0x0000000000000001 Alignment (1B) 652 sh_entsize 0x0000000000000000 Size in bytes of each entry 653 654 655 ### Section 4: .symtab (SHT_SYMTAB;) 656 657 #### Symbol table entry 0 658 |00000290: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 659 |000002a0: 0000 0000 0000 0000 | ........ 660 661 st_name 0x00000000 662 st_info 0x00 663 st_other 0x00 664 st_shndx 0x0000 (SHN_UNDEF) 665 st_value 0x0000000000000000 666 st_size 0x0000000000000000 667 668 #### Symbol table entry 1 669 |000002a8: 0000 0000 0300 0100| ........ 670 |000002b0: b000 4000 0000 0000 0000 0000 0000 0000| ..@............. 671 672 st_name 0x00000000 673 st_info 0x03 (STT_OBJECT | STT_FUNC) 674 st_other 0x00 675 st_shndx 0x0001 (Section 1: .text) 676 st_value 0x00000000004000b0 677 st_size 0x0000000000000000 678 679 #### Symbol table entry 2 680 |000002c0: 0000 0000 0300 0200 d800 6000 0000 0000| ..........`..... 681 |000002d0: 0000 0000 0000 0000 | ........ 682 683 st_name 0x00000000 684 st_info 0x03 (STT_OBJECT | STT_FUNC) 685 st_other 0x00 686 st_shndx 0x0002 (Section 2: .data) 687 st_value 0x00000000006000d8 688 st_size 0x0000000000000000 689 690 #### Symbol table entry 3 (hello.asm) 691 |000002d0: 0100 0000 0400 f1ff| ........ 692 |000002e0: 0000 0000 0000 0000 0000 0000 0000 0000| ................ 693 694 st_name 0x00000001 695 st_info 0x04 (STT_FILE) 696 st_other 0x00 697 st_shndx 0xfff1 (SHN_ABS) 698 st_value 0x0000000000000000 699 st_size 0x0000000000000000 700 701 #### Symbol table entry 4 (hello) 702 |000002f0: 0b00 0000 0000 0200 d800 6000 0000 0000| ..........`..... 703 |00000300: 0000 0000 0000 0000 | ................ 704 705 st_name 0x0000000b 706 st_info 0x00 707 st_other 0x00 708 st_shndx 0x0002 (Section 2: .data) 709 st_value 0x00000000006000d8 710 st_size 0x0000000000000000 711 712 #### Symbol table entry 5 (hbytes) 713 |00000300: 1100 0000 0000 f1ff| ........ 714 |00000310: 0e00 0000 0000 0000 0000 0000 0000 0000| ................ 715 716 st_name 0x00000011 717 st_info 0x00 718 st_other 0x00 719 st_shndx 0xfff1 (SHN_ABS) 720 st_value 0x000000000000000e 721 st_size 0x0000000000000000 722 723 #### Symbol table entry 6 (_start) 724 |00000320: 1800 0000 1000 0100 b000 4000 0000 0000| ..........@..... 725 |00000330: 0000 0000 0000 0000 | ........ 726 727 st_name 0x00000018 728 st_info 0x10 (STB_GLOBAL) 729 st_other 0x00 730 st_shndx 0x0001 (Section 1: .text) 731 st_value 0x00000000004000b0 732 st_size 0x0000000000000000 733 734 #### Symbol table entry 7 (__bss_start) 735 |00000330: 1f00 0000 1000 f1ff| ........ 736 |00000340: e600 6000 0000 0000 0000 0000 0000 0000| ..`............. 737 738 st_name 0x0000001f 739 st_info 0x10 (STB_GLOBAL) 740 st_other 0x00 741 st_shndx 0xfff1 (SHN_ABS) 742 st_value 0x00000000006000e6 743 st_size 0x0000000000000000 744 745 #### Symbol table entry 8 (_edata) 746 |00000350: 2b00 0000 1000 f1ff e600 6000 0000 0000| +.........`..... 747 |00000360: 0000 0000 0000 0000 | ........ 748 749 st_name 0x0000002b 750 st_info 0x10 (STB_GLOBAL) 751 st_other 0x00 752 st_shndx 0xfff1 (SHN_ABS) 753 st_value 0x00000000006000e6 754 st_size 0x0000000000000000 755 756 #### Symbol table entry 9 (_end) 757 |00000360: 3200 0000 1000 f1ff| 2....... 758 |00000370: e800 6000 0000 0000 0000 0000 0000 0000| ..`............. 759 760 st_name 0x00000032 761 st_info 0x10 (STB_GLOBAL) 762 st_other 0x00 763 st_shndx 0xfff1 (SHN_ABS) 764 st_value 0x00000000006000e8 765 st_size 0x0000000000000000 766 767 768 ### Section 6: .strtab (SHT_STRTAB;) 769 770 |00000380: 0068 656c 6c6f 2e61 736d 0068 656c 6c6f| .hello.asm.hello 771 |00000390: 0068 6279 7465 7300 5f73 7461 7274 005f| .hbytes._start._ 772 |000003a0: 5f62 7373 5f73 7461 7274 005f 6564 6174| _bss_start._edat 773 |000003b0: 6100 5f65 6e64 00 | a._end. 774 775 0x00000000: '' 776 0x00000001: 'hello.asm' 777 0x0000000b: 'hello' 778 0x00000011: 'hbytes' 779 0x00000018: '_start' 780 0x0000001f: '__bss_start' 781 0x0000002b: '_edata' 782 0x00000032: '_end' 783 784 785 Effect of stripping 786 ------------------- 787 788 Running `strip` on the binary has the effect of dropping the `.symtab` and 789 `.strtab` sections along with their section headers and 16 bytes of data (the 790 section names `.symtab` and `.strtab`) from the `.shstrtab` section, reducing the 791 total binary size to 512 bytes. 792 793 In-memory process image 794 ----------------------- 795 796 FreeBSD uses a memory superpage size of 2MB (page size of 4kB) on x86_64. Since 797 attributes are set at the page level, read+execute program `.text` and 798 read+write `.data` are loaded into two separate segments on separate pages, as 799 laid-out by the linker. 800 801 On launch, the kernel maps the binary image into memory as specified in the 802 program header table: 803 * PHT Entry 0: The ELF header, program header table, and Section 1 (`.text`) 804 are mapped from offset 0x00 of the binary image (with length 0xd6 bytes) 805 into Segment 1 (readable, executable) at address 0x400000. 806 * PHT Entry 1: Section 2 (`.data`) at offset 0xd8 of the binary image is 807 mapped into Segment 2 (readable, writeable) at address 0x6000d8 from offset 808 0xd8 with length 0x0e bytes. 809 810 The program entrypoint is specified to be 0x4000b0, the start of the `.text` 811 section. 812 813 And that's it! Any corrections or comments are always welcome. Shoot me an 814 email at [chris@bracken.jp][email]. 815 816 [amd64_abi]: https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf 817 [guide_linker]: https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/index.html 818 [email]: mailto:chris@bracken.jp