elf helper (linker?) program

This commit is contained in:
janis 2026-06-05 07:01:48 +02:00
parent 79a4c65df3
commit 654c14d92b
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
2 changed files with 414 additions and 0 deletions

148
stages/hex1/elf.asm Normal file
View file

@ -0,0 +1,148 @@
;; Program that takes an output file to which it writes elf64 headers and the contents of a second file which is assumed to be a text section.
die:
mov rax, 60 ; syscall: exit
mov rdi, 0 ; status: 0
syscall
ret
fopen:
mov rax, 2 ; syscall: open
mov rsi, 0 ; flags: O_RDONLY
mov rdx, 0 ; mode
syscall
ret
fopen_write:
mov rax, 2 ; syscall: open
mov rsi, 0x241 ; flags: O_WRONLY | O_CREAT | O_TRUNC
mov rdx, 0o644 ; mode: rw-r--r--
syscall
ret
;; rdi: fd
;; rsi: buffer
fstat:
mov rax, 5 ; syscall: fstat
syscall
ret
fsize:
push rdi
push rsi
call fstat
pop rsi
pop rdi
mov rax, [rsi + 48] ; st_size
ret
;; rdi: dst
;; rsi: src
;; rdx: len
memcpy:
.memcpy_loop:
test rdx, rdx
jz .memcpy_done
mov al, byte [rsi]
mov byte [rdi], al
inc rsi
inc rdi
dec rdx
jmp .memcpy_loop
.memcpy_done:
ret
;; variables:
;; +0 buffer: [u8; 0x1000]
;; +0x1000 bytes_read: u32
;; +0x1004 in_size: u32
;; +0x1008 in_fd: u32
;; +0x100c out_fd: u32
;; +0x1010 argc: u32
;; +0x1018 argv: *const *const u8
_start:
mov eax, dword [rsp] ; argc
lea rbx, [rsp + 8] ; argv
sub rsp, 0x4000 ; reserve stack space
mov r15, rsp ; r15 = pointer to our state
mov dword [r15 + 0x1010], eax ; store argc
mov qword [r15 + 0x1018], rbx ; store argv
cmp eax, 3
jl die
;; open output file
mov rdi, [r15 + 0x1018] ; rdi = argv
add rdi, 8 ; rdi = argv[1]
mov rdi, [rdi] ; rdi = pointer to argv[1]
call fopen_write
mov dword [r15 + 0x100c], eax ; store out_fd
;; open input file and get size
mov rdi, [r15 + 0x1018] ; rdi = argv
add rdi, 16 ; rdi = argv[2]
mov rdi, [rdi] ; rdi = pointer to argv[2]
call fopen
mov dword [r15 + 0x1008], eax ; store in_fd
mov edi, eax ; rdi = in_fd
lea rsi, [r15] ; rsi = pointer to statbuf
call fsize
mov dword [r15 + 0x1004], eax ; store in_size
;; copy elf header to scratch space
mov rdi, 0x400000
mov rsi, r15
mov rdx, 0x40
call memcpy
;; copy program header to scratch space
mov rdi, 0x400040
mov rsi, [r15 + 0x40]
mov rdx, 0x38
call memcpy
;; write p_filesz and p_memsz to 0x78 + in_size
mov rax, 0x78
add eax, dword [r15 + 0x1004] ; rax = 0x78 + in_size
mov dword [r15 + 0x60], eax ; write p_filesz
mov dword [r15 + 0x68], eax ; write p_memsz
;; write e_entry to point at 0x40 + 0x38 + in_size - 5
sub rax, 5
mov dword [r15 + 24], eax ; write e_entry
;; write Ehdr and Phdr to output file
mov edi, dword [r15 + 0x100c] ; rdi = out_fd
mov rsi, r15 ; rsi = buffer
mov rdx, 0x78 ; size of Ehdr + Phdr
mov rax, 1 ; syscall: write
syscall
;; copy text section from input file to output file
.copy_loop:
mov edi, dword [r15 + 0x1008] ; rdi = in_fd
mov rsi, r15 ; rsi = pointer to buffer
mov rdx, 0x1000 ; rdx = size of buffer
mov rax, 0 ; syscall: read
syscall
test rax, rax
jle die
mov dword [r15 + 0x1000], eax ; store number of bytes read
mov edi, dword [r15 + 0x100c] ; rdi = out_fd
mov rsi, r15 ; rsi = pointer to buffer
mov edx, dword [r15 + 0x1000] ; rdx = number of bytes read
mov rax, 1 ; syscall: write
syscall
cmp dword [r15 + 0x1000], 0x1000 ; if we read less than 0x1000 bytes, we are done
je .copy_loop
call die

266
stages/hex1/elf.in Normal file
View file

@ -0,0 +1,266 @@
; ELF header
; e_ident: u128
; Magic number: 0x7f454c46 = "\x7fELF"
7f 45 4c 46
; EI_CLASS: u8 = ELFCLASS64
02
; EI_DATA: u8 = ELFDATA2LSB
01
; EI_VERSION: u8 = EV_CURRENT
01
; EI_OSABI: u8 = ELFOSABI_NONE
00
; EI_ABIVERSION: u8 = 0
00
; EI_PAD: [u8; 7]
00 00 00 00 00 00 00
; e_type: u16 = E_EXEC
02 00
; e_machine: u16 = EM_X86_64
3e 00
; e_version: u32 = EV_CURRENT
01 00 00 00
; e_entry: u64 = 0x400078
78 00 40 00 00 00 00 00
; e_phoff: u64 = 0x40
40 00 00 00 00 00 00 00
; e_shoff: u64 = 0x0
00 00 00 00 00 00 00 00
; e_flags: u32 = 0
00 00 00 00
; e_ehsize: u16 = 64
40 00
; e_phentsize: u16 = 56
38 00
; e_phnum: u16 = 1
01 00
; e_shentsize: u16 = 0
00 00
; e_shnum: u16 = 0
00 00
; e_shstrndx: u16 = 0
00 00
; End of ELF header
;
; Program header
; p_type: u32 = PT_LOAD
01 00 00 00
; p_flags: u32 = PF_R | PF_X
05 00 00 00
; p_offset: u64 = 0
00 00 00 00 00 00 00 00
; p_vaddr: u64 = 0x400000
00 00 40 00 00 00 00 00
; p_paddr: u64 = 0x0
00 00 00 00 00 00 00 00
; p_filesz: u64 = 0x167
67 01 00 00 00 00 00 00
; p_memsz: u64 = 0x167
67 01 00 00 00 00 00 00
; p_align: u64 = 0x1000
00 10 00 00 00 00 00 00
; End of program header
;
; @die: +0
; mov rax, 60 (exit)
b8 3c 00 00 00
; mov rdi, 0 (exit code)
bf 00 00 00 00
; syscall
0f 05
; ret
c3
;
; @fopen:
; mov rax, 2 (sys_open)
b8 02 00 00 00
; mov rsi, 0
be 00 00 00 00
; mov rdx, 0
ba 00 00 00 00
; syscall
0f 05
; ret
c3
;
; fopen_write:
; mov rax, 2 (sys_open)
b8 02 00 00 00
; mov rsi, 0x241 (O_WRONLY | O_CREAT | O_TRUNC)
be 41 02 00 00
; mov rdx, 0o644 (file mode)
ba a4 01 00 00
; syscall
0f 05
; ret
c3
;
; @fstat:
; mov rax, 5 (sys_fstat)
b8 05 00 00 00
; syscall
0f 05
; ret
c3
;
; @fsize:
; push rdi
57
; push rsi
56
; call 'fstat
e8 f1 ff ff ff
; pop rsi
5e
; pop rdi
5f
; mov rax, [rsi+48] (st_size)
48 8b 46 30
; ret
c3
; @memcpy:
; test rdx, rdx
48 85 d2
; jz 'memcpy_exit
74 0f
; mov al, byte [rsi]
8a 06
; mov byte [rdi], al
88 07
; inc rsi
48 ff c6
; inc rdi
48 ff c7
; dec rdx
48 ff ca
; jmp 'memcpy
eb ec
; @memcpy_exit:
c3
;
; @_start:
; mov eax, dword [rsp] (argc)
8b 04 24
; lea rbx, [rsp+8] (argv)
48 8d 5c 24 08
; sub rsp, 0x4000
48 81 ec 00 40 00 00
; mov r15, rsp
49 89 e7
; mov dword [r15+0x1010], eax (store argc)
41 89 87 10 10 00 00
; mov qword [r15+0x1018], rbx (store argv)
49 89 9f 18 10 00 00
; cmp eax, 3
83 f8 03
; jl 'die
0f 8c 7b ff ff ff
;
; mov rdi, qword [r15+0x1018] (argv)
49 8b bf 18 10 00 00
; add rdi, 8 (argv[1])
48 83 c7 08
; mov rdi, [rdi] (argv[1])
48 8b 3f
; call 'fopen_write
e8 87 ff ff ff
;
; mov dword [r15+0x101c], eax (store file descriptor)
41 89 87 0c 10 00 00
; mov rdi, qword [r15+0x1018] (argv)
49 8b bf 18 10 00 00
; add rdi, 16 (argv[2])
48 83 c7 10
; mov rdi, [rdi] (argv[2])
48 8b 3f
; call 'fopen
e8 5b ff ff ff
;
; mov dword [r15+0x1008], eax (store file descriptor)
41 89 87 08 10 00 00
; mov edi, eax (fd)
89 c7
; lea rsi, [r15]
49 8d 37
; call 'fsize
e8 76 ff ff ff
;
; mov dword [r15+0x1004], eax (store file size)
41 89 87 04 10 00 00
; mov edi, 0x400000
bf 00 00 40 00
; mov rsi, r15
4c 89 fe
; mov edx, 0x40 (size)
ba 40 00 00 00
; call 'memcpy
e8 6b ff ff ff
;
; mov edi, 0x400040
bf 40 00 40 00
; mov rsi, [r15+0x40]
49 8b 77 40
; mov edx, 0x38 (size)
ba 38 00 00 00
; call 'memcpy
e8 58 ff ff ff
;
; mov eax, 0x78
b8 78 00 00 00
; add eax, dword [r15+0x1004] (file size)
41 03 87 04 10 00 00
; mov dword [r15+0x60], eax (store file end)
41 89 47 60
; mov dword [r15+0x68], eax (store file end)
41 89 47 68
;
; sub rax, 5
48 83 e8 05
; mov dword [r15+0x18], eax (store file end - 5)
41 89 47 18
;
; mov edi, dword [r15+0x100c] (fd)
41 8b bf 0c 10 00 00
; mov rsi, r15
4c 89 fe
; mov edx, 0x78 (size)
ba 78 00 00 00
; mov eax, 1 (sys_write)
b8 01 00 00 00
; syscall
0f 05
; @write_loop:
; mov edi, dword [r15+0x1008] (fd)
41 8b bf 08 10 00 00
; mov rsi, r15
4c 89 fe
; mov edx, 0x1000 (size)
ba 00 10 00 00
; mov eax, 0 (sys_read)
b8 00 00 00 00
; syscall
0f 05
; test rax, rax
48 85 c0
; jle 'die
0f 8e c0 fe ff ff
;
; mov dword [r15+0x1000], eax (store bytes read)
41 89 87 00 10 00 00
; mov edi, dword [r15+0x100c] (fd)
41 8b bf 0c 10 00 00
; mov rsi, r15
4c 89 fe
; mov edx, dword [r15+0x1000] (bytes read)
41 8b 97 00 10 00 00
; mov eax, 1 (sys_write)
b8 01 00 00 00
; syscall
0f 05
; cmp dword [r15+0x1000], 0x1000
41 81 bf 00 10 00 00 00 10 00 00
; jz 'write_loop
74 b5
; call 'die
e8 8f fe ff ff