From 654c14d92bfa58684598326c75be8d51d6cc98b4 Mon Sep 17 00:00:00 2001 From: janis Date: Fri, 5 Jun 2026 07:01:48 +0200 Subject: [PATCH] elf helper (linker?) program --- stages/hex1/elf.asm | 148 ++++++++++++++++++++++++ stages/hex1/elf.in | 266 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 414 insertions(+) create mode 100644 stages/hex1/elf.asm create mode 100644 stages/hex1/elf.in diff --git a/stages/hex1/elf.asm b/stages/hex1/elf.asm new file mode 100644 index 0000000..bd74c85 --- /dev/null +++ b/stages/hex1/elf.asm @@ -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 + + + + + + + + + diff --git a/stages/hex1/elf.in b/stages/hex1/elf.in new file mode 100644 index 0000000..dbf9d0d --- /dev/null +++ b/stages/hex1/elf.in @@ -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 \ No newline at end of file