From d35f6a6ee6da0c11063b6a88a3ce0f88346e8142 Mon Sep 17 00:00:00 2001 From: Mitya Selivanov Date: Sun, 9 Jun 2024 04:41:24 +0200 Subject: Writing dummy ELF executable --- binary_code_generation.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 3 deletions(-) diff --git a/binary_code_generation.c b/binary_code_generation.c index 3735b2c..e0853ec 100755 --- a/binary_code_generation.c +++ b/binary_code_generation.c @@ -40,6 +40,8 @@ exit $? #include #include #include +#include +#include typedef signed char i8; typedef signed short i16; @@ -341,6 +343,12 @@ void unit_set_entry_point(entity_pool_t *pool, i64 unit, i64 entry_point_proc) { pool->entities[unit].unit.entry_point = entry_point_proc; } +// ================================================================ +// +// Code generation proc +// +// ================================================================ + void unit_write(entity_pool_t *pool, i64 unit, i16 target, FILE *out) { assert(pool != NULL); assert(pool->entities[unit].is_enabled); @@ -348,10 +356,76 @@ void unit_write(entity_pool_t *pool, i64 unit, i16 target, FILE *out) { assert(out != NULL); assert(target == (FORMAT_ELF | ARCH_X86_64)); - // TODO - printf("[TODO] Writing ELF x86_64 executable..."); + printf("Writing ELF x86_64 executable...\n"); + + u16 ehs = 64; + u16 shs = 0; + u16 phs = 56; + u64 align = 8; + + u8 code[16] = { + 0xb8, // mov rax + 0x3c, 0, 0, 0, // 60 // exit + 0x48, 0x31, 0xff, // xor rdx, rdx // rdx = 0 + 0x0f, 0x05, // syscall + }; + + u64 code_offset = (ehs + phs + (align - 1)) & (~(align - 1)); + u64 code_size = sizeof code; + + assert((code_offset % align) == 0); + assert((code_size % align) == 0); + + u64 entry = 0x400000 + ehs + phs; + + // ELF header + // + + fwrite( (u8[4]) { 0x7f, 'E', 'L', 'F' }, 1, 4, out); // magic + + fwrite(&(u8) { 2 }, 1, 1, out); // elf64 + fwrite(&(u8) { 1 }, 1, 1, out); // 2's complement, little endian + fwrite(&(u8) { 1 }, 1, 1, out); // current version + fwrite(&(u8) { 0 }, 1, 1, out); // SysV + fwrite(&(u8) { 0 }, 1, 1, out); // ABI version + fwrite( (u8[7]) { 0 }, 1, 7, out); // padding + + fwrite(&(u16) { 2 }, 2, 1, out); // executable + fwrite(&(u16) { 62 }, 2, 1, out); // x86_64 + fwrite(&(u32) { 1 }, 4, 1, out); // current version + fwrite(&(u64) { entry }, 8, 1, out); // entry point address + fwrite(&(u64) { ehs }, 8, 1, out); // program header offset + fwrite(&(u64) { 0 }, 8, 1, out); // section header offset + fwrite(&(u32) { 0 }, 4, 1, out); // flags + fwrite(&(u16) { ehs }, 2, 1, out); // ELF header size + fwrite(&(u16) { phs }, 2, 1, out); // program header size + fwrite(&(u16) { 1 }, 2, 1, out); // program header count + fwrite(&(u16) { shs }, 2, 1, out); // section header size + fwrite(&(u16) { 0 }, 2, 1, out); // section header count + fwrite(&(u16) { 0 }, 2, 1, out); // string table section header index + + // Program header + // + + fwrite(&(u32) { 1 }, 4, 1, out); // type (PT_LOAD) + fwrite(&(u32) { 5 }, 4, 1, out); // flags (PF_X | PF_R) + fwrite(&(u64) { code_offset }, 8, 1, out); // offset + fwrite(&(u64) { entry }, 8, 1, out); // vaddr + fwrite(&(u64) { entry }, 8, 1, out); // paddr + fwrite(&(u64) { code_size }, 8, 1, out); // filesz + fwrite(&(u64) { code_size }, 8, 1, out); // memsz + fwrite(&(u64) { 8 }, 8, 1, out); // align + + // Code + // + + for (i64 i = code_offset - ehs - phs; i > 0; --i) + fwrite(&(u8) { 0 }, 1, 1, out); + + fwrite(code, 1, code_size, out); } + // ================================================================ // // Helpers @@ -401,11 +475,12 @@ void u_elf_x86_64(i64 unit, c8 const *output_file_name) { assert(f != NULL); unit_write(&g_pool, unit, FORMAT_ELF | ARCH_X86_64, f); fclose(f); + chmod(output_file_name, 0775); } // ================================================================ // -// Code generation proc +// Example // // ================================================================ -- cgit v1.2.3