blog

Source files for chris.bracken.jp
git clone https://git.bracken.jp/blog.git
Log | Files | Refs | Submodules | README | LICENSE

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