summaryrefslogtreecommitdiff
path: root/write_elf.c
diff options
context:
space:
mode:
authoronelin <oscar@nelin.dk>2026-06-10 04:58:13 +0000
committeronelin <oscar@nelin.dk>2026-06-10 04:58:13 +0000
commit7cc1a2e6ccc8f4a87e73c35672e7bb973e965470 (patch)
treece65f72b384f9d75d15cc68ed2f0225e2b21ae0b /write_elf.c
Initial commit
Diffstat (limited to 'write_elf.c')
-rw-r--r--write_elf.c141
1 files changed, 141 insertions, 0 deletions
diff --git a/write_elf.c b/write_elf.c
new file mode 100644
index 0000000..62b6cd3
--- /dev/null
+++ b/write_elf.c
@@ -0,0 +1,141 @@
+#include "instructions.h"
+#include "registers.h"
+#include <elf.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+unsigned char some_opcodes[] = {MOVDI(REG_EAX, 0x3c),
+ // 0xb8, 0x3c, 0x00, 0x00, 0x00,
+ MOVDI(REG_EDI, 0x41),
+ // 0xbf, 0x41, 0x00, 0x00, 0x00,
+ SYSCALL};
+unsigned int some_opcodes_len = sizeof(some_opcodes) / sizeof(some_opcodes[0]);
+
+int
+write_elf(char* restrict file, size_t opcodes_len, char* restrict opcodes) {
+ int error = 0;
+
+ Elf64_Phdr header_program[] = {
+ //{
+ // .p_type = PT_LOAD,
+ // .p_flags = PF_R,
+ // .p_offset = 0, /* Segment file offset */
+ // .p_vaddr = 0x400000, /* Segment virtual address */
+ // .p_paddr = 0x400000, /* Segment physical address */
+ // .p_filesz = 0xb0, /* Segment size in file */
+ // .p_memsz = 0xb0, /* Segment size in memory */
+ // .p_align = 0x1000, /* Segment alignment */
+ //},
+ {
+ .p_type = PT_LOAD,
+ .p_flags = PF_X | PF_R,
+ .p_offset =
+ sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr), /* Segment file offset */
+ .p_vaddr = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), /* Segment virtual address */
+ .p_paddr = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), /* Segment physical address */
+ .p_filesz = opcodes_len, /* Segment size in file */
+ .p_memsz = opcodes_len, /* Segment size in memory */
+ .p_align = 0x1, /* Segment alignment */
+ },
+ };
+
+ Elf64_Shdr header_section[] = {
+ {
+ // .init
+ // Index in section header string table
+ .sh_name = 0,
+ .sh_type = 0,
+ .sh_flags = 0,
+ .sh_addr = 0,
+ .sh_offset = 0,
+ .sh_size = 0,
+ .sh_link = 0,
+ .sh_info = 0,
+ .sh_addralign = 0,
+ .sh_entsize = 0,
+ },
+ {
+ // .init
+ // Index in section header string table
+ .sh_name = 0,
+ .sh_type = SHT_PROGBITS,
+ .sh_flags = SHF_ALLOC | SHF_EXECINSTR,
+ .sh_addr = 0x401000,
+ .sh_offset = 0x1000,
+ .sh_size = opcodes_len,
+ /* todo: deps on type */
+ .sh_link = 0,
+ /* todo: deps on type */
+ .sh_info = 0,
+ .sh_addralign = 4,
+ .sh_entsize = 0,
+ },
+ {
+ // .shstrtab Section Header String Table
+ // Index in section header string table
+ .sh_name = 1,
+ .sh_type = SHT_STRTAB,
+ .sh_flags = 0,
+ .sh_addr = 0x100,
+ .sh_offset = 0x2000,
+ .sh_size = opcodes_len,
+ /* todo: deps on type */
+ .sh_link = 0,
+ /* todo: deps on type */
+ .sh_info = 0,
+ .sh_addralign = 1,
+ .sh_entsize = 0,
+ },
+ };
+
+ unsigned char string_header_table[] = {0, '.', 'i', 'n', 'i', 't', 0};
+
+ Elf64_Ehdr header = {
+ // memset(&header, 0, sizeof(Elf64_Ehdr));
+ .e_ident = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS64, ELFDATA2LSB,
+ EV_CURRENT, ELFOSABI_SYSV},
+ .e_type = ET_EXEC,
+ .e_machine = EM_X86_64,
+ .e_version = EV_CURRENT,
+ .e_entry = 0x400000 + sizeof(Elf64_Ehdr) +
+ sizeof(Elf64_Phdr), // point to VIRTUAL address of _start
+ .e_phoff = sizeof(Elf64_Ehdr) /* Program header table offset */,
+ .e_shoff = 0, // sizeof(Elf64_Ehdr) + sizeof(header_program) /* Section
+ // header table offset */,
+ .e_flags = 0,
+ .e_ehsize = sizeof(Elf64_Ehdr),
+ .e_phentsize = sizeof(Elf64_Phdr),
+ // If larger than PN_XNUM, then set to PN_XNUM and store real number in
+ // sh_info of first program header entry
+ .e_phnum = 1,
+ .e_shentsize = sizeof(header_section[0]),
+ // If larger than SHN_LORESERVE, then set to 0 and store real number in
+ // sh_size of first section header entry
+ .e_shnum = 0, // sizeof(header_section) / sizeof(header_section[0]),
+ // If larger than SHN_LORESERVE, then set to SHN_XINDEX and store real index
+ // in
+ // sh_link of first section header entry
+ .e_shstrndx = 0,
+ };
+
+ size_t bytes_written = 0;
+ FILE* fd = fopen(file, "w");
+
+ fwrite(&header, sizeof(Elf64_Ehdr), 1, fd);
+ fwrite(&header_program, sizeof(Elf64_Phdr),
+ sizeof(header_program) / sizeof(header_program[0]), fd);
+ // fseek(fd, 0x1000, SEEK_SET);
+
+ do {
+ bytes_written += fwrite(opcodes, sizeof(char), opcodes_len, fd);
+ } while (bytes_written != opcodes_len);
+ error = fclose(fd);
+ if (error) {
+ err(EXIT_FAILURE, "no way");
+ }
+ return 0;
+}