|
| 1 | +// Copyright (c) 2019 Alexander Medvednikov. All rights reserved. |
| 2 | +// Use of this source code is governed by an MIT license |
| 3 | +// that can be found in the LICENSE file. |
| 4 | + |
| 5 | +module x64 |
| 6 | + |
| 7 | +import os |
| 8 | + |
| 9 | +const ( |
| 10 | + mag0 = 0x7f |
| 11 | + mag1 = `E` |
| 12 | + mag2 = `L` |
| 13 | + mag3 = `F` |
| 14 | + ei_class = 4 |
| 15 | + elfclass64 = 2 |
| 16 | + elfdata2lsb = 1 |
| 17 | + |
| 18 | + ev_current = 1 |
| 19 | + elf_osabi = 0 |
| 20 | + |
| 21 | + // ELF file types |
| 22 | + et_rel = 1 |
| 23 | + et_exec = 2 |
| 24 | + et_dyn = 3 |
| 25 | + |
| 26 | + e_machine = 0x3e |
| 27 | + |
| 28 | + shn_xindex = 0xffff |
| 29 | + |
| 30 | + sht_null = 0 |
| 31 | +) |
| 32 | + |
| 33 | +const ( |
| 34 | + segment_start = 0x400000 |
| 35 | +) |
| 36 | + |
| 37 | + |
| 38 | +pub fn (g mut Gen) generate_elf_header() { |
| 39 | + g.buf << [byte(mag0), mag1, mag2, mag3] |
| 40 | + g.buf << elfclass64 // file class |
| 41 | + g.buf << elfdata2lsb // data encoding |
| 42 | + g.buf << ev_current // file version |
| 43 | + g.buf << 1//elf_osabi |
| 44 | + g.write64(0)//et_rel) // et_rel for .o |
| 45 | + g.write16(2) // e_type |
| 46 | + g.write16(e_machine) // |
| 47 | + g.write32(ev_current) // e_version |
| 48 | + eh_size := 0x40 |
| 49 | + phent_size := 0x38 |
| 50 | + g.write64(segment_start + eh_size + phent_size) // e_entry |
| 51 | + g.write64(0x40) // e_phoff |
| 52 | + g.write64(0) // e_shoff |
| 53 | + g.write32(0) // e_flags |
| 54 | + g.write16(eh_size) // e_ehsize |
| 55 | + g.write16(phent_size) // e_phentsize |
| 56 | + g.write16(1) // e_phnum |
| 57 | + g.write16(0) // e_shentsize |
| 58 | + g.write16(0) // e_shnum (number of sections) |
| 59 | + g.write16(0) // e_shstrndx |
| 60 | + // Elf64_Phdr |
| 61 | + g.write32(1) // p_type |
| 62 | + g.write32(5) // p_flags |
| 63 | + g.write64(0) // p_offset |
| 64 | + g.write64(segment_start) // p_vaddr addr:050 |
| 65 | + g.write64(segment_start) // |
| 66 | + g.file_size_pos = g.buf.len |
| 67 | + g.write64(0) // p_filesz PLACEHOLDER, set to file_size later // addr: 060 |
| 68 | + g.write64(0) // p_memsz |
| 69 | + g.write64(0x1000) // p_align |
| 70 | + // user code starts here at |
| 71 | + // address: 00070 and a half |
| 72 | +} |
| 73 | + |
| 74 | +pub fn (g mut Gen) generate_elf_footer() { |
| 75 | + // Return 0 |
| 76 | + g.mov(.edi, 0) // ret value |
| 77 | + g.mov(.eax, 60) |
| 78 | + g.syscall() |
| 79 | + // Strings table |
| 80 | + // Loop thru all strings and set the right addresses |
| 81 | + for i, s in g.strings { |
| 82 | + g.write64_at(segment_start + g.buf.len, int(g.str_pos[i])) |
| 83 | + g.write_string(s) |
| 84 | + g.write8(6) |
| 85 | + } |
| 86 | + // Now we know the file size, set it |
| 87 | + file_size := g.buf.len |
| 88 | + g.write64_at(file_size, g.file_size_pos) // set file size 64 bit value |
| 89 | + g.write64_at(file_size, g.file_size_pos+8) |
| 90 | + // Create the binary |
| 91 | + f := os.create('out.bin') or { panic(err) } |
| 92 | + f.write_bytes(g.buf.data, g.buf.len) |
| 93 | + f.close() |
| 94 | + println('x64 elf binary has been successfully generated') |
| 95 | +} |
| 96 | + |
0 commit comments