this is done by setting the ABI version in the ELF header. many thanks to nortti for checking that things otherwise work, and validating that the approach makes sense in terms of FreeBSD's cultural expectations. Irenes don't have the ability to easily test this on our end, but this is an easy step that can improve compatibility. Force-Push: yes Change-Id: I3d55ed240c050839b8a11312f151d0809aef9031
233 lines
11 KiB
Text
233 lines
11 KiB
Text
~ This file is a commented hexadecimal representation of a compiled
|
|
~ program, the output of Evocation's hex transform. The comments are
|
|
~ intended to allow a human reader to audit it. You can convert it to a
|
|
~ runnable executable by piping it through the program named 'hex' and
|
|
~ chmodding the output 755. The difference between a source and a binary
|
|
~ is comments! Enjoy. :)
|
|
|
|
~ This particular program is 'hex' itself. You of course already need to
|
|
~ have a binary copy of it to use this file, but you may find it helpful
|
|
~ to have this hex dump anyway, to aid in auditing your binary.
|
|
|
|
|
|
~ ELF file header
|
|
~ * denotes mandatory fields according to breadbox
|
|
7f 45 4c 46 ~ *magic number
|
|
02 ~ 64-bit
|
|
01 ~ little-endian
|
|
01 ~ ELF header format v1
|
|
03 ~ Linux ABI
|
|
00 00 00 00 00 00 00 00 ~ (padding)
|
|
|
|
02 00 ~ *executable
|
|
3e 00 ~ *Intel x86-64
|
|
01 00 00 00 ~ ELF format version
|
|
|
|
78 00 00 08 00 00 00 00 ~ *entry point
|
|
40 00 00 00 00 00 00 00 ~ *program header offset
|
|
00 00 00 00 00 00 00 00 ~ section header offset
|
|
00 00 00 00 ~ processor flags
|
|
|
|
40 00 ~ ELF header size
|
|
38 00 ~ *program header entry size
|
|
01 00 ~ *number of program header entries
|
|
00 00 ~ section header entry size
|
|
00 00 ~ number of section header entries
|
|
00 00 ~ section name string table index
|
|
|
|
~ ELF program header
|
|
~ label elf-program-header at offset 0x0000000000000040 is here.
|
|
01 00 00 00 ~ *"loadable" segment type
|
|
07 00 00 00 ~ *read+write+execute permission
|
|
00 00 00 00 00 00 00 00 ~ *offset in file
|
|
00 00 00 08 00 00 00 00 ~ *virtual address
|
|
00 00 00 00 00 00 00 00 ~ physical address (ignored)
|
|
|
|
e0 01 00 00 00 00 00 00 ~ *size in file
|
|
e0 01 00 00 00 00 00 00 ~ *size in memory
|
|
|
|
00 00 00 00 00 00 00 00 ~ segment alignment
|
|
|
|
|
|
~ This is the start routine, the first thing that runs when the ELF loads.
|
|
~ label cold-start at offset 0x0000000000000078 is here.
|
|
~ The basic registers preserved across syscalls are rbx, rsp, rbp.
|
|
~ To avoid redundant moves, we store the buffer pointer in rbx just once,
|
|
~ and keep it there. We've made sure our load origin fits in 32 bits, so
|
|
~ we can use imm32 for that. We're going to want to do an indirect load
|
|
~ from it, so we can't use rbp for this.
|
|
48 c7 c3 d8 01 00 08 ~ 0x80001d8 :rbx mov-reg64-imm32
|
|
|
|
~ label input-loop-start at offset 0x000000000000007f is here.
|
|
e8 88 00 00 00 ~ 0x88 call-rel-imm32
|
|
|
|
~ If the length is 0, we got EOF. If it's less than zero, we got a read
|
|
~ error. Either way, we exit. This is a signed comparison, as it needs to
|
|
~ be.
|
|
48 83 f8 00 ~ 0x0 :rax cmp-reg64-imm8
|
|
74 72 ~ 0x72 :cc-equal jmp-cc-rel-imm8
|
|
7c ee ~ 0xee :cc-less jmp-cc-rel-imm8
|
|
|
|
~ Now that the length is handled, retrieve the input byte.
|
|
48 8b 03 ~ :rbx :rax mov-reg64-indirect-reg64
|
|
|
|
~ If it's space or linefeed, skip it (go back to the loop start).
|
|
48 83 f8 20 ~ 0x20 :rax cmp-reg64-imm8
|
|
~ ASCII space
|
|
74 ea ~ 0xffffffffffffffea :cc-equal jmp-cc-rel-imm8
|
|
48 83 f8 0a ~ 0xa :rax cmp-reg64-imm8
|
|
~ ASCII linefeed
|
|
74 e4 ~ 0xffffffffffffffe4 :cc-equal jmp-cc-rel-imm8
|
|
~ If it's a comment, skip the whole thing.
|
|
48 83 f8 7e ~ 0x7e :rax cmp-reg64-imm8
|
|
~ ASCII tilde
|
|
74 43 ~ 0x43 :cc-equal jmp-cc-rel-imm8
|
|
|
|
~ Decode the value, or exit with an error.
|
|
e8 79 00 00 00 ~ 0x79 call-rel-imm32
|
|
|
|
~ We use rbp as a place to stash the high nibble.
|
|
48 89 c5 ~ :rax :rbp mov-reg64-reg64
|
|
48 c1 c5 04 ~ 0x4 :rbp rol-reg64-imm8
|
|
|
|
~ Now we read another byte.
|
|
e8 5a 00 00 00 ~ 0x5a call-rel-imm32
|
|
|
|
~ Handle the length. A second hex digit is required here.
|
|
48 83 f8 00 ~ 0x0 :rax cmp-reg64-imm8
|
|
74 ac ~ 0xac :cc-equal jmp-cc-rel-imm8
|
|
7c c0 ~ 0xc0 :cc-less jmp-cc-rel-imm8
|
|
|
|
~ Now that the length is handled, retrieve the input byte.
|
|
48 8b 03 ~ :rbx :rax mov-reg64-indirect-reg64
|
|
|
|
~ Decode the value, or exit with an error.
|
|
e8 5d 00 00 00 ~ 0x5d call-rel-imm32
|
|
|
|
~ We OR in the low nibble.
|
|
48 0b e8 ~ :rax :rbp or-reg64-reg64
|
|
|
|
~ Output the byte. We reuse the buffer as a place to store it.
|
|
48 89 2b ~ :rbp :rbx mov-indirect-reg64-reg64
|
|
48 89 de ~ :rbx :rsi mov-reg64-reg64
|
|
~ buffer pointer
|
|
48 c7 c2 01 00 00 00 ~ 0x1 :rdx mov-reg64-imm32
|
|
~ buffer length
|
|
48 c7 c0 01 00 00 00 ~ 0x1 :rax mov-reg64-imm32
|
|
~ syscall number for sys-write
|
|
48 c7 c7 01 00 00 00 ~ 0x1 :rdi mov-reg64-imm32
|
|
~ file descriptor 1 is stdout
|
|
0f 05 ~ syscall
|
|
|
|
~ Back to the start of the loop.
|
|
eb 9b ~ 0xffffffffffffff9b jmp-rel-imm8
|
|
|
|
~ label skip-comment at offset 0x00000000000000e4 is here.
|
|
~ Read a byte for the comment.
|
|
e8 23 00 00 00 ~ 0x23 call-rel-imm32
|
|
|
|
~ Handle the length. We're allowed to end in a comment.
|
|
48 83 f8 00 ~ 0x0 :rax cmp-reg64-imm8
|
|
74 0d ~ 0xd :cc-equal jmp-cc-rel-imm8
|
|
7c 89 ~ 0x89 :cc-less jmp-cc-rel-imm8
|
|
|
|
~ Now that the length is handled, retrieve the input byte.
|
|
48 8b 03 ~ :rbx :rax mov-reg64-indirect-reg64
|
|
|
|
~ If it's linefeed, the comment is over.
|
|
48 83 f8 0a ~ 0xa :rax cmp-reg64-imm8
|
|
~ ASCII linefeed
|
|
74 85 ~ 0xffffffffffffff85 :cc-equal jmp-cc-rel-imm8
|
|
|
|
~ We're still in the comment, keep handling it.
|
|
eb e8 ~ 0xffffffffffffffe8 jmp-rel-imm8
|
|
|
|
~ This is the routine named "exit".
|
|
~ label exit at offset 0x00000000000000fc is here.
|
|
48 c7 c0 3c 00 00 00 ~ 0x3c :rax mov-reg64-imm32
|
|
~ syscall number for sys-exit
|
|
48 c7 c7 00 00 00 00 ~ 0x0 :rdi mov-reg64-imm32
|
|
~ exit code
|
|
0f 05 ~ syscall
|
|
|
|
~ This is the routine named "read-byte".
|
|
~ label read-byte at offset 0x000000000000010c is here.
|
|
~ We use self-xor as a concise way to set registers to zero.
|
|
48 33 c0 ~ :rax :rax xor-reg64-reg64
|
|
~ syscall number for sys-read
|
|
48 33 ff ~ :rdi :rdi xor-reg64-reg64
|
|
~ file descriptor 0 is stdin
|
|
48 89 de ~ :rbx :rsi mov-reg64-reg64
|
|
~ buffer pointer
|
|
~ We read one byte at a time, because it makes the loop structure simple.
|
|
48 c7 c2 01 00 00 00 ~ 0x1 :rdx mov-reg64-imm32
|
|
~ buffer length
|
|
0f 05 ~ syscall
|
|
c3 ~ ret
|
|
|
|
~ This is the routine named "decode-nibble".
|
|
~ label decode-nibble at offset 0x000000000000011f is here.
|
|
48 83 e8 30 ~ 0x30 :rax sub-reg64-imm8
|
|
~ ASCII zero
|
|
7c 29 ~ 0x29 :cc-less jmp-cc-rel-imm8
|
|
48 83 f8 0a ~ 0xa :rax cmp-reg64-imm8
|
|
72 22 ~ 0x22 :cc-below jmp-cc-rel-imm8
|
|
48 83 e8 11 ~ 0x11 :rax sub-reg64-imm8
|
|
~ ASCII capital A
|
|
7c 1d ~ 0x1d :cc-less jmp-cc-rel-imm8
|
|
48 83 c0 0a ~ 0xa :rax add-reg64-imm8
|
|
48 83 f8 10 ~ 0x10 :rax cmp-reg64-imm8
|
|
72 12 ~ 0x12 :cc-below jmp-cc-rel-imm8
|
|
48 83 e8 2a ~ 0x2a :rax sub-reg64-imm8
|
|
~ ASCII lowercase a
|
|
7c 0d ~ 0xd :cc-less jmp-cc-rel-imm8
|
|
48 83 c0 0a ~ 0xa :rax add-reg64-imm8
|
|
48 83 f8 10 ~ 0x10 :rax cmp-reg64-imm8
|
|
72 02 ~ 0x2 :cc-below jmp-cc-rel-imm8
|
|
eb 01 ~ 0x1 jmp-rel-imm8
|
|
~ label got-nibble at offset 0x000000000000014d is here.
|
|
c3 ~ ret
|
|
|
|
|
|
~ These are the error handler routines.
|
|
~ label invalid-byte at offset 0x000000000000014e is here.
|
|
48 be ae 01 00 08 00 00 00 00 ~ 0x80001ae :rsi mov-reg64-imm64
|
|
48 ba 0e 00 00 00 00 00 00 00 ~ 0xe :rdx mov-reg64-imm64
|
|
eb 2a ~ 0x2a jmp-rel-imm8
|
|
~ label unexpected-eof at offset 0x0000000000000164 is here.
|
|
48 be c8 01 00 08 00 00 00 00 ~ 0x80001c8 :rsi mov-reg64-imm64
|
|
48 ba 10 00 00 00 00 00 00 00 ~ 0x10 :rdx mov-reg64-imm64
|
|
eb 14 ~ 0x14 jmp-rel-imm8
|
|
~ label read-error at offset 0x000000000000017a is here.
|
|
48 be bc 01 00 08 00 00 00 00 ~ 0x80001bc :rsi mov-reg64-imm64
|
|
48 ba 0c 00 00 00 00 00 00 00 ~ 0xc :rdx mov-reg64-imm64
|
|
~ label exit-with-error at offset 0x000000000000018e is here.
|
|
48 c7 c0 01 00 00 00 ~ 0x1 :rax mov-reg64-imm32
|
|
~ syscall number for sys-write
|
|
48 c7 c7 02 00 00 00 ~ 0x2 :rdi mov-reg64-imm32
|
|
~ file descriptor 2 is stderr
|
|
0f 05 ~ syscall
|
|
48 c7 c0 3c 00 00 00 ~ 0x3c :rax mov-reg64-imm32
|
|
~ syscall number for sys-exit
|
|
48 c7 c7 01 00 00 00 ~ 0x1 :rdi mov-reg64-imm32
|
|
~ exit code
|
|
0f 05 ~ syscall
|
|
|
|
~ These are the message strings.
|
|
~ label invalid-byte-message at offset 0x00000000000001ae is here.
|
|
~ "Invalid byte." (string literal with null)
|
|
49 6e 76 61 6c 69 64 20 62 79 74 65 2e 00
|
|
~ label read-error-message at offset 0x00000000000001bc is here.
|
|
~ "Read error." (string literal with null)
|
|
52 65 61 64 20 65 72 72 6f 72 2e 00
|
|
~ label unexpected-eof-message at offset 0x00000000000001c8 is here.
|
|
~ "Unexpected EOF." (string literal with null)
|
|
55 6e 65 78 70 65 63 74 65 64 20 45 4f 46 2e 00
|
|
|
|
~ This is a buffer that's zero in the ELF, but is written to at runtime
|
|
~ and used as a variable.
|
|
~ label buffer at offset 0x00000000000001d8 is here.
|
|
00 00 00 00 00 00 00 00
|
|
~ label total-size at offset 0x00000000000001e0 is here.
|
|
|
|
~ This is the end of the hex dump.
|