summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbinary_code_generation.c81
1 files 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 <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
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
//
// ================================================================