diff options
Diffstat (limited to 'bxgen.c')
-rwxr-xr-x | bxgen.c | 215 |
1 files changed, 110 insertions, 105 deletions
@@ -720,8 +720,12 @@ void unit_set_entry_point(Pool *pool, i64 unit, i64 entry_point_proc) { void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { // Docs // - // AR https://man.freebsd.org/cgi/man.cgi?query=ar&sektion=5 - // ELF https://man7.org/linux/man-pages/man5/elf.5.html + // AR https://man.freebsd.org/cgi/man.cgi?query=ar&sektion=5 + // ELF https://man7.org/linux/man-pages/man5/elf.5.html + // + // LLVM impl https://github.com/llvm/llvm-project/blob/main/lld/ELF/Driver.cpp#L2822 + // https://github.com/llvm/llvm-project/blob/main/lld/ELF/Writer.cpp#L304 + // https://github.com/llvm/llvm-project/blob/main/lld/ELF/OutputSections.cpp#L469 // assert(pool != NULL && pool->entities != NULL); @@ -739,6 +743,90 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data u8 elf_abi_ver = 0; // ABI version u16 elf_machine = 62; // x86_64 + #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) + #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) + #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) + #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) + #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) + #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) + + 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; + u64 code_size = sizeof code; + u64 entry_offset = 0; + + u64 base_address = 0x400000; // x86_64 base address + u64 code_address = base_address + code_offset; + u64 entry = code_address + entry_offset; + + assert((code_offset % align) == 0); + assert((code_size % align) == 0); + + // ELF header + // + + WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic + + WRITE_V( elf_class ); + WRITE_V( elf_data ); + WRITE_V( elf_ver ); + WRITE_V( elf_abi ); + WRITE_V( elf_abi_ver ); + + WRITE_DUP(0, 7); // padding + + WRITE_2( 2 ); // executable + WRITE_2( elf_machine ); + WRITE_4( 1 ); // current version + WRITE_8( entry ); // entry point address + WRITE_8( ehs ); // program header offset + WRITE_8( 0 ); // section header offset + WRITE_4( 0 ); // flags + WRITE_2( ehs ); // ELF header size + WRITE_2( phs ); // program header size + WRITE_2( 1 ); // program header count + WRITE_2( shs ); // section header size + WRITE_2( 0 ); // section header count + WRITE_2( 0 ); // string table section header index + + // Program header + // + + WRITE_4( 1 ); // type (PT_LOAD) + WRITE_4( 5 ); // flags (PF_X | PF_R) + WRITE_8( code_offset ); // offset + WRITE_8( code_address ); // vaddr + WRITE_8( code_address ); // paddr + WRITE_8( code_size ); // filesz + WRITE_8( code_size ); // memsz + WRITE_8( 8 ); // align + + // Code + // + + for (i64 i = code_offset - ehs - phs; i > 0; --i) + WRITE_V( 0 ); + + WRITE( code, code_size ); + + #undef WRITE_V + #undef WRITE_DUP + #undef WRITE_32 + #undef WRITE_64 + + #undef WRITE + // Read dependencies // { @@ -1065,25 +1153,23 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data current_offset = prev_offset; } - printf("%-18s", type >= 1 && type <= 17 ? (c8 const *[]) { - "Program data", - "Symbols", - "String table", - "Rel width addends", - "Dynamic", - "Note", - "Zero", - "Rel", - "", - "", - "", - "", - "", - "", - "", - "", - "Group", - }[type - 1] : ""); + printf( + "%-18s", + type >= 1 && type <= 8 ? + (c8 const *[]) { + "Program data", + "Symbols", + "String table", + "Rel width addends", + "Dynamic", + "Note", + "No data", + "Rel", + }[type - 1] : + type == 17 ? + "Group" : + "" + ); if ((flags & 1) == 1) printf(" Writable"); @@ -1092,6 +1178,9 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data if ((flags & 4) == 4) printf(" Executable"); + // NOTE + // Only alloc sections should be written to the output binary. + printf("\n"); } @@ -1121,90 +1210,6 @@ void unit_write(Pool *pool, i64 unit, u16 target, i64 io_out, void *io_user_data io_close(f, io_user_data); } } - - #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) - #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) - #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) - #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) - #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) - #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) - - 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; - u64 code_size = sizeof code; - u64 entry_offset = 0; - - u64 base_address = 0x400000; // x86_64 base address - u64 code_address = base_address + code_offset; - u64 entry = code_address + entry_offset; - - assert((code_offset % align) == 0); - assert((code_size % align) == 0); - - // ELF header - // - - WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic - - WRITE_V( elf_class ); - WRITE_V( elf_data ); - WRITE_V( elf_ver ); - WRITE_V( elf_abi ); - WRITE_V( elf_abi_ver ); - - WRITE_DUP(0, 7); // padding - - WRITE_2( 2 ); // executable - WRITE_2( elf_machine ); - WRITE_4( 1 ); // current version - WRITE_8( entry ); // entry point address - WRITE_8( ehs ); // program header offset - WRITE_8( 0 ); // section header offset - WRITE_4( 0 ); // flags - WRITE_2( ehs ); // ELF header size - WRITE_2( phs ); // program header size - WRITE_2( 1 ); // program header count - WRITE_2( shs ); // section header size - WRITE_2( 0 ); // section header count - WRITE_2( 0 ); // string table section header index - - // Program header - // - - WRITE_4( 1 ); // type (PT_LOAD) - WRITE_4( 5 ); // flags (PF_X | PF_R) - WRITE_8( code_offset ); // offset - WRITE_8( code_address ); // vaddr - WRITE_8( code_address ); // paddr - WRITE_8( code_size ); // filesz - WRITE_8( code_size ); // memsz - WRITE_8( 8 ); // align - - // Code - // - - for (i64 i = code_offset - ehs - phs; i > 0; --i) - WRITE_V( 0 ); - - WRITE( code, code_size ); - - #undef WRITE_V - #undef WRITE_DUP - #undef WRITE_32 - #undef WRITE_64 - - #undef WRITE } i64 io_open_read(i64 name_size, c8 *name, void *user_data) { |