From bd2f069659f6ada5baa068ce984fa8ca36116780 Mon Sep 17 00:00:00 2001 From: ladevieq Date: Wed, 24 Sep 2025 00:10:35 +0200 Subject: Use input obj files bytecode for executable generation --- src/main.c | 91 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 41 deletions(-) (limited to 'src/main.c') diff --git a/src/main.c b/src/main.c index 880cd0b..6d63575 100644 --- a/src/main.c +++ b/src/main.c @@ -232,6 +232,7 @@ enum { // we allow for only one of each type struct COFF_sections { + u8* file_buffer; u32 text_section_off; u32 text_section_size; u32 data_section_off; @@ -244,40 +245,37 @@ struct COFF_sections { u32 string_section_size; }; -static struct COFF_sections* read_COFFs_header(const char* obj_files[], u32 obj_files_count, u8* sections_flag) { +static struct COFF_sections* read_COFFs_header(const char* obj_files[], u32 obj_files_count, u8* sections_flag, u32* c_COFF_sections) { ASSERT(*sections_flag == 0U); if (obj_files_count == 0U) { return NULL; } - size_t max_header_size = sizeof(IMAGE_SECTION_HEADER) * 96U + sizeof(IMAGE_FILE_HEADER); - // TODO: Make an array type u32 nb_sections_size = sizeof(struct COFF_sections) * obj_files_count; struct COFF_sections* sections = (struct COFF_sections*)VirtualAlloc(NULL, nb_sections_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); mem_set((void*)sections, nb_sections_size, 0U); - IMAGE_FILE_HEADER* header = (IMAGE_FILE_HEADER*)VirtualAlloc(NULL, max_header_size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - IMAGE_SECTION_HEADER* section_table = (IMAGE_SECTION_HEADER*)(((u8*)header) + sizeof(*header)); - for (u32 obj_id = 0U; obj_id < obj_files_count; obj_id++) { struct COFF_sections* section = §ions[obj_id]; const char* obj_file = obj_files[obj_id]; - HANDLE obj_file_handle = CreateFileA(obj_file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0U, NULL); if (!obj_file_handle && obj_file_handle != INVALID_HANDLE_VALUE) { continue; } - DWORD bread = 0U; - if (!ReadFile(obj_file_handle, (void*)header, sizeof(*header), &bread, NULL)) { - CloseHandle(obj_file_handle); - continue; - } + LARGE_INTEGER file_size = { 0 }; + GetFileSizeEx(obj_file_handle, &file_size); + + section->file_buffer = (u8*)VirtualAlloc(NULL, file_size.LowPart, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); - if (!ReadFile(obj_file_handle, (void*)section_table, sizeof(section_table[0U]) * header->NumberOfSections, &bread, NULL)) { + IMAGE_FILE_HEADER* header = (IMAGE_FILE_HEADER*)section->file_buffer; + IMAGE_SECTION_HEADER* section_table = (IMAGE_SECTION_HEADER*)(((u8*)header) + sizeof(*header)); + + DWORD bread = 0U; + if (!ReadFile(obj_file_handle, (void*)header, file_size.LowPart, &bread, NULL)) { CloseHandle(obj_file_handle); continue; } @@ -316,7 +314,7 @@ static struct COFF_sections* read_COFFs_header(const char* obj_files[], u32 obj_ CloseHandle(obj_file_handle); } - VirtualFree(header, 0U, MEM_RELEASE); + *c_COFF_sections = obj_files_count; return sections; } @@ -570,7 +568,7 @@ struct PE_headers { #define OBJ_EXT 0x6A626F2E // .obj -static void write_exe_headers(u8* buffer) { +static void write_exe_headers(struct PE_headers * buffer, u16 c_sections, u32 addr_entry_point, u32 base_of_code, u32 size_of_code, u32 size_of_headers, u32 size_of_image) { static struct PE_headers PE_headers = { .dos_header = { .e_magic = IMAGE_DOS_SIGNATURE, @@ -653,14 +651,20 @@ static void write_exe_headers(u8* buffer) { FILETIME filetime = { 0U }; GetSystemTimeAsFileTime(&filetime); - PE_headers.img_header.TimeDateStamp = filetime.dwLowDateTime; + PE_headers.img_header.TimeDateStamp = filetime.dwLowDateTime; + + PE_headers.img_header.NumberOfSections = c_sections; + + PE_headers.opt_header.AddressOfEntryPoint = addr_entry_point; + PE_headers.opt_header.BaseOfCode = base_of_code; + PE_headers.opt_header.SizeOfCode = size_of_code; + PE_headers.opt_header.SizeOfImage = size_of_image; + PE_headers.opt_header.SizeOfHeaders = size_of_headers; mem_copy(&PE_headers, buffer, sizeof(PE_headers)); } -static u8 test_main[] = { 0x33, 0xc0, 0xc3 }; - -static void write_text_section(IMAGE_SECTION_HEADER* section_table, u16* section_count) { +static void write_text_section_header(IMAGE_SECTION_HEADER* section_table, u16* section_count) { IMAGE_SECTION_HEADER* text_section_header = §ion_table[*section_count]; mem_copy(".text", text_section_header->Name, 6U); @@ -675,7 +679,7 @@ static void write_text_section(IMAGE_SECTION_HEADER* section_table, u16* section (*section_count)++; } -static void write_data_section(IMAGE_SECTION_HEADER* section_table, u16* section_count) { +static void write_data_section_header(IMAGE_SECTION_HEADER* section_table, u16* section_count) { IMAGE_SECTION_HEADER* data_section_header = §ion_table[*section_count]; mem_copy(".text", data_section_header->Name, 6U); @@ -690,7 +694,7 @@ static void write_data_section(IMAGE_SECTION_HEADER* section_table, u16* section (*section_count)++; } -static void write_bss_section(IMAGE_SECTION_HEADER* section_table, u16* section_count) { +static void write_bss_section_header(IMAGE_SECTION_HEADER* section_table, u16* section_count) { IMAGE_SECTION_HEADER* bss_section_header = §ion_table[*section_count]; mem_copy(".text", bss_section_header->Name, 6U); @@ -829,7 +833,8 @@ int mainCRTStartup(void) { // loop through all OBJs header to find out which sections we need u8 sections_flag = 0U; - struct COFF_sections* sections = read_COFFs_header(obj_files, c_obj_files, §ions_flag); + u32 c_COFF_sections = 0U; + struct COFF_sections* sections = read_COFFs_header(obj_files, c_obj_files, §ions_flag, &c_COFF_sections); __debugbreak(); @@ -839,30 +844,31 @@ int mainCRTStartup(void) { IMAGE_SECTION_HEADER* section_table = (IMAGE_SECTION_HEADER*)(exe_buffer + sizeof(*headers)); u16 c_sections = 0U; - // dont write section count to img header - write_exe_headers(exe_buffer); - // write the relevant sections if (sections_flag & TEXT_SECTION_FLAG) { // TODO: copy text to the relevant part of the buffer - write_text_section(section_table, &c_sections); + write_text_section_header(section_table, &c_sections); } if (sections_flag & DATA_SECTION_FLAG) { - write_data_section(section_table, &c_sections); + write_data_section_header(section_table, &c_sections); } if (sections_flag & BSS_SECTION_FLAG) { - write_bss_section(section_table, &c_sections); + write_bss_section_header(section_table, &c_sections); } - headers->img_header.NumberOfSections = c_sections; - // Write section bodies // TODO: index per section ? - u32 code_size = sizeof(test_main); u32 headers_size = ALIGN(sizeof(*headers) + (sizeof(IMAGE_SECTION_HEADER) * c_sections), FILE_ALIGNMENT); - mem_copy(test_main, (void*)(exe_buffer + headers_size), code_size); - section_table[0U].SizeOfRawData = ALIGN(code_size, FILE_ALIGNMENT); - section_table[0U].Misc.VirtualSize = ALIGN(code_size, SECTION_ALIGNMENT); + void* text_start = (void*)((u8*)headers + headers_size); + + for (u32 COFF_section_index = 0U; COFF_section_index < c_COFF_sections; COFF_section_index++) { + struct COFF_sections const* cur_section = §ions[COFF_section_index]; + if ( cur_section->text_section_off ) { + mem_copy((void*)(cur_section->file_buffer + cur_section->text_section_off), text_start, cur_section->text_section_size); + section_table[0U].SizeOfRawData = ALIGN(cur_section->text_section_size, FILE_ALIGNMENT); + section_table[0U].Misc.VirtualSize = ALIGN(cur_section->text_section_size, SECTION_ALIGNMENT); + } + } // Set sections pointer to raw data _Static_assert(FILE_ALIGNMENT < SECTION_ALIGNMENT, "section alignment must greater or equal to file alignment in order to align headers_size on section alignment"); @@ -879,13 +885,12 @@ int mainCRTStartup(void) { virtual_offset += cur_section->Misc.VirtualSize; } - // Fill remaining header informations - - headers->opt_header.SizeOfHeaders = headers_size; // aligned on file alignment - headers->opt_header.AddressOfEntryPoint = section_table[0U].VirtualAddress; - headers->opt_header.BaseOfCode = section_table[0U].PointerToRawData; - headers->opt_header.SizeOfCode = section_table[0U].SizeOfRawData; - headers->opt_header.SizeOfImage = ALIGN(section_table[c_sections - 1U].VirtualAddress + section_table[c_sections - 1U].Misc.VirtualSize, SECTION_ALIGNMENT); + // Fill header informations + u32 addr_entry_point = section_table[0U].VirtualAddress; + u32 base_of_code = section_table[0U].PointerToRawData; + u32 size_of_code = section_table[0U].SizeOfRawData; + u32 size_of_image = ALIGN(section_table[c_sections - 1U].VirtualAddress + section_table[c_sections - 1U].Misc.VirtualSize, SECTION_ALIGNMENT); + write_exe_headers(headers, c_sections, addr_entry_point, base_of_code, size_of_code, headers_size, size_of_image); DWORD bwrite = 0U; WriteFile(output_file, exe_buffer, headers->opt_header.SizeOfImage, &bwrite, NULL); @@ -894,6 +899,10 @@ int mainCRTStartup(void) { CloseHandle(output_file); } + for (u32 COFF_section_index = 0U; COFF_section_index < c_COFF_sections; COFF_section_index++) { + VirtualFree(sections[COFF_section_index].file_buffer, 0U, MEM_RELEASE); + } + VirtualFree(sections, 0U, MEM_RELEASE); VirtualFree(exe_buffer, 0U, MEM_RELEASE); VirtualFree(lib_path_env, 0U, MEM_RELEASE); -- cgit v1.3