diff --git a/project.4coder b/project.4coder index 6092302..2859796 100644 --- a/project.4coder +++ b/project.4coder @@ -8,6 +8,7 @@ patterns = { "*.bat", "*.sh", "*.4coder", +"*.txt", }; blacklist_patterns = { ".*", diff --git a/src/base.c b/src/base.c index 5542075..d94a0ca 100644 --- a/src/base.c +++ b/src/base.c @@ -34,21 +34,11 @@ str8_match(String8 a, String8 b, U32 flags){ #if OS_WINDOWS -static RangePtr +// see: https://devblogs.microsoft.com/oldnewthing/20041025-00/?p=37483 +static void* os_this_image(void){ - RangePtr result = {0}; - HMODULE module = 0; - GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - (LPWSTR)os_this_image, &module); - if (module != 0){ - HANDLE process = GetCurrentProcess(); - MODULEINFO module_info = {0}; - if (GetModuleInformation(process, module, - &module_info, sizeof(module_info))){ - result.first = (U8*)module_info.lpBaseOfDll; - result.opl = result.first + module_info.SizeOfImage; - } - } + extern U8 __ImageBase[]; + void *result = __ImageBase; return(result); } @@ -59,18 +49,11 @@ os_this_image(void){ #if OS_WINDOWS # include "binary/pe/mr4th_pe.h" -# include "binary/pe/mr4th_pe.parse.h" -# include "binary/pe/mr4th_pe.parse.c" +# include "binary/pe/mr4th_pe.img_get_section.c" static RangePtr -selfimg_get_section(RangePtr image, String8 name){ - RangePtr result = {0}; - String8 image_str = str8(image.first, image.opl - image.first); - PE_SectionHeader *section = pe_section_header_from_name(image_str, name); - if (section != 0){ - result.first = image.first + section->voff; - result.opl = result.first + section->vsize; - } +self_img_get_section(void *image, String8 name){ + RangePtr result = pe_img_get_section(image, name); return(result); } diff --git a/src/base.h b/src/base.h index 2725e99..f39a691 100644 --- a/src/base.h +++ b/src/base.h @@ -247,5 +247,6 @@ typedef struct String8{ static String8 str8(U8 *str, U64 size); static B32 str8_match(String8 a, String8 b, U32 flags); -static RangePtr os_this_image(void); -static RangePtr selfimg_get_section(RangePtr image, String8 name); +static void* os_this_image(void); + +static RangePtr self_img_get_section(void *image, String8 name); diff --git a/src/binary/mr4th_binary.h b/src/binary/mr4th_binary.h deleted file mode 100644 index 1ec3eb8..0000000 --- a/src/binary/mr4th_binary.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MR4TH_BINARY_H -#define MR4TH_BINARY_H - -/* TODO: -** BINARY FILE PROJECT -** -** Research Questions: -** [ ] What the heck is that blob of data between the -** DOS header and the PE signature/COFF header? -** And why does it change so much from binary to binary? -** [ ] Unwind Info: The docs say there is a ULONG after the unwind codes??? -** -** TASKS: -** -** [x] Useful PE/COFF Table Tool -** [ ] PE/COFF Linker -** [ ] PE/COFF ObjFromRaw -** [ ] PE/COFF editing to hard wire magic IDs without a data section -** [ ] PE/COFF editing to merge separate data sections to -** consolidate magic gathered arrays into plain old .data -** -** [ ] Renaming pass over mr4th_elf.dump (similar to pe.dump -> pe.parsex) -** [ ] ELF Generator -** [ ] Useful ELF ASCII Visualizer -** [ ] ELF Linker -** [ ] Debug Information (CODEVIEW,DWARF) -** -*/ - -#endif //MR4TH_BINARY_H diff --git a/src/binary/pe/mr4th_pe.c b/src/binary/pe/mr4th_pe.c deleted file mode 100644 index af346fb..0000000 --- a/src/binary/pe/mr4th_pe.c +++ /dev/null @@ -1,277 +0,0 @@ -//////////////////////////////// -// Functions: COFF / PE - -// properties - -MR4TH_SYM_COMPTIME U32 -pe_unwind_num_code_slot_from_opcode_opinfo(PE_UnwindOpCode opcode, U8 opinfo){ - U32 num = 1; - - switch (opcode){ - case PE_UnwindOpCode_PUSH_NONVOL: - case PE_UnwindOpCode_ALLOC_SMALL: - case PE_UnwindOpCode_SET_FPREG: - case PE_UnwindOpCode_PUSH_MACHFRAME: - case PE_UnwindOpCode_EPILOG: - case PE_UnwindOpCode_SPARE: - { - num = 1; - }break; - - case PE_UnwindOpCode_ALLOC_LARGE: - { - if (opinfo == 0){ - num = 2; - } - else{ - num = 3; - } - }break; - - case PE_UnwindOpCode_SAVE_NONVOL: - case PE_UnwindOpCode_SAVE_XMM128: - { - num = 2; - }break; - - case PE_UnwindOpCode_SAVE_NONVOL_FAR: - case PE_UnwindOpCode_SAVE_XMM128_FAR: - { - num = 3; - }break; - } - - return(num); -} - -// checks - -MR4TH_SYM_COMPTIME B32 -pe_machine_type_is_valid(PE_MachineType machine_type){ - B32 result = 0; - switch (machine_type){ -#define X(N,C) case C: - PE_MachineType_XList(X) -#undef X - result = 1; break; - } - return(result); -} - -// strings - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_machine_type(PE_MachineType machine_type){ - String8 result = str8_lit("ERROR"); - switch (machine_type){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_MachineType_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME void -pe_str8list_from_flags(Arena *arena, String8List *out, PE_Flags flags){ - U32 f = 1; - for (U32 i = 0; i < 8*sizeof(flags); i += 1){ - if ((flags & f) != 0){ - switch (f){ -#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break; - PE_Flags_XList(X) -#undef X - } - } - f <<= 1; - } -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_flags(Arena *arena, PE_Flags flags){ - ArenaTemp scratch = arena_get_scratch(&arena, 1); - String8List list = {0}; - pe_str8list_from_flags(scratch.arena, &list, flags); - String8 result = str8_join_flags(arena, &list); - arena_release_scratch(&scratch); - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_optional_header_magic(PE_OptionalHeaderMagic magic){ - String8 result = str8_lit("ERROR"); - switch (magic){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_OptionalHeaderMagic_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_windows_subsystem(PE_WindowsSubsystem subsystem){ - String8 result = str8_lit("ERROR"); - switch (subsystem){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_WindowsSubsystem_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME void -pe_str8list_from_dll_flags(Arena *arena, String8List *out, PE_DLLFlags dll_flags){ - U32 f = 1; - for (U32 i = 0; i < 8*sizeof(dll_flags); i += 1){ - if ((dll_flags & f) != 0){ - switch (f){ -#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break; - PE_DLLFlags_XList(X) -#undef X - } - } - f <<= 1; - } -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_dll_flags(Arena *arena, PE_DLLFlags dll_flags){ - ArenaTemp scratch = arena_get_scratch(&arena, 1); - String8List list = {0}; - pe_str8list_from_dll_flags(scratch.arena, &list, dll_flags); - String8 result = str8_join_flags(arena, &list); - arena_release_scratch(&scratch); - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_data_directory_idx(PE_DataDirectoryIdx idx){ - String8 result = {0}; - switch (idx){ -#define X(N,D,C) case C: result = str8_lit(#N); break; - PE_DataDirectoryIdx_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_display_string_from_data_directory_idx(PE_DataDirectoryIdx idx){ - String8 result = {0}; - switch (idx){ -#define X(N,D,C) case C: result = str8_lit(D); break; - PE_DataDirectoryIdx_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_sec_alignment(U32 alignment){ - String8 result = {0}; - switch (alignment){ -#define X(Z,C) case C: result = str8_lit("ALIGN_" #Z "BYTES"); break; - PE_SectionAlign_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME void -pe_str8list_from_sec_flags(Arena *arena, String8List *out, PE_SectionFlags sec_flags){ - // align - U32 section_align = PE_SectionAlignFromSectionFlags(sec_flags); - String8 align_str = pe_str8_from_sec_alignment(section_align); - if (align_str.size > 0){ - str8_list_push(arena, out, align_str); - } - - // other flags - U32 f = 1; - for (U32 i = 0; i < 8*sizeof(sec_flags); i += 1){ - if ((sec_flags & f) != 0){ - switch (f){ -#define X(N,C) case C: str8_list_push(arena, out, str8_lit(#N)); break; - PE_SectionFlags_XList(X) -#undef X - } - } - f <<= 1; - } -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_sec_flags(Arena *arena, PE_SectionFlags sec_flags){ - ArenaTemp scratch = arena_get_scratch(&arena, 1); - String8List list = {0}; - pe_str8list_from_sec_flags(scratch.arena, &list, sec_flags); - String8 result = str8_join_flags(arena, &list); - arena_release_scratch(&scratch); - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_coff_relocation_type(PE_CoffRelocationType type){ - String8 result = str8_lit("ERROR"); - switch (type){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_CoffRelocationType_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_coff_symbol_type(Arena *arena, PE_CoffSymbolType type){ - String8 lo = str8_lit("ERROR"); - switch (type & 0xF){ -#define X(N,C) case C: lo = str8_lit(#N); break; - PE_CoffSymbolTypeLo_XList(X) -#undef X - } - - String8 result = lo; - switch ((type >> 4) & 0xF){ - case PE_CoffSymbolTypeHi_NULL: break; - case PE_CoffSymbolTypeHi_POINTER: - result = str8_pushf(arena, "POINTER %S", lo); break; - case PE_CoffSymbolTypeHi_FUNCTION: - result = str8_pushf(arena, "FUNCTION %S", lo); break; - case PE_CoffSymbolTypeHi_ARRAY: - result = str8_pushf(arena, "ARRAY %S", lo); break; - } - - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_coff_symbol_storage_class(PE_CoffSymbolStorageClass storage_class){ - String8 result = str8_lit("ERROR"); - switch (storage_class){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_CoffSymbolStorageClass_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_base_relocation_type(PE_BaseRelocationType type){ - String8 result = str8_lit("ERROR"); - switch (type){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_BaseRelocationType_XList(X) -#undef X - } - return(result); -} - -MR4TH_SYM_COMPTIME String8 -pe_str8_from_debug_type(PE_DebugType debug_type){ - String8 result = str8_lit("ERROR"); - switch (debug_type){ -#define X(N,C) case C: result = str8_lit(#N); break; - PE_DebugType_XList(X) -#undef X - } - return(result); -} diff --git a/src/binary/pe/mr4th_pe.gen.c b/src/binary/pe/mr4th_pe.gen.c deleted file mode 100644 index 2150466..0000000 --- a/src/binary/pe/mr4th_pe.gen.c +++ /dev/null @@ -1,1631 +0,0 @@ -/* -** PE File Generator -*/ - -/* TODO: -** -** Current Goal: -** -** PE/COFF Generator -** [ ] Symbol Table: Build out support for more symbol types -** [ ] Block System Improvements -** [ ] Acceleration: When attaching a block tree to a section, convert -** the whole tree to have automatic mapping onto the section. -** [ ] Acceleration: (pointer) <-> (block & off) mappings -** [ ] Checks: -** [ ] Error system that connects entire baker -** [ ] All data directories that are set use data blocks attached to a layout -** [ ] All patches that are set must use data blocks attached to a layout -** [ ] Structured Constructor -** [ ] Debug -** [ ] TLS -** [ ] Load Config -** [ ] Tool: Bake aribtrary data file into an object with a symbol name -** -*/ - -globalvar U8 pe_dos_header[] = { - 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, - 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, - 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, - 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, - 0x69, 0x73, 0x20, 0x70, 0x72, 0x6F, 0x67, 0x72, - 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, - 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, - 0x20, 0x69, 0x6E, 0x20, 0x44, 0x4F, 0x53, 0x20, - 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, - 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x65, 0x6C, 0x0C, 0xDD, 0x21, 0x0D, 0x62, 0x8E, - 0x21, 0x0D, 0x62, 0x8E, 0x21, 0x0D, 0x62, 0x8E, - 0xA1, 0x74, 0x61, 0x8F, 0x23, 0x0D, 0x62, 0x8E, - 0xA1, 0x74, 0x60, 0x8F, 0x20, 0x0D, 0x62, 0x8E, - 0x52, 0x69, 0x63, 0x68, 0x21, 0x0D, 0x62, 0x8E, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - - -#if 0 -globalvar U8 text[] = { - /**/ //sum: - 0x48, 0x8B, 0xC1, // mov rax,rcx - 0x48, 0x03, 0xC2, // add rax,rdx - 0xC3, // ret -}; -#endif - -#if 0 -globalvar U8 text[] = { - /**/ //main: - 0x48, 0xC7, 0xC0, 0x03, 0x01, 0x02, 0x01, // mov rax,01020103h - 0xC3, // ret -}; -#endif - -#if 1 -globalvar U8 text[] = { - /**/ //sum_longname: - 0x48, 0x8B, 0xC1, // mov rax,rcx - 0x48, 0x03, 0xC2, // add rax,rdx - 0x48, 0x8B, 0x0D, 0x00, 0x00, 0x00, 0x00, // mov rcx, - 0x48, 0x03, 0xC1, // add rax,rcx - 0xC3, // ret -}; -#endif - -#if 1 -globalvar U8 data[] = { - 0x18, 0x00, 0x00, 0x00 -}; -#endif - - -//////////////////////////////// -// PE Generator Functions - -/// gen api /// - -// ctx - -function PEGEN_Ctx* -pegen_begin(void){ - Arena *arena = arena_alloc(); - PEGEN_Ctx *gen = push_array(arena, PEGEN_Ctx, 1); - gen->arena = arena; - return(gen); -} - -function void -pegen_release(PEGEN_Ctx *gen){ - arena_release(gen->arena); -} - -// data blocks - -function PEGEN_Block* -pegen_block_new(PEGEN_Ctx *gen){ - PEGEN_Block *block = push_array(gen->arena, PEGEN_Block, 1); - SLLQueuePush_NZ(gen->first_block, gen->last_block, block, next_bucket, 0); - block->base_alignment = 1; - gen->block_count += 1; - return(block); -} - -function PEGEN_Block* -pegen_block_new_write(PEGEN_Ctx *gen, String8 data){ - PEGEN_Block *block = pegen_block_new(gen); - pegen_block_push_write(gen, block, data); - return(block); -} - -function PEGEN_Block* -pegen_block_new_aligned(PEGEN_Ctx *gen, U32 align){ - PEGEN_Block *block = pegen_block_new(gen); - pegen_block_align(gen, block, 0, align); - return(block); -} - -function void* -pegen_block_push(PEGEN_Ctx *gen, PEGEN_Block* block, U32 size){ - Assert(block != 0); - Assert(!block->attached); - Assert(block->child_count == 0 || block->data == 0); - - void *result = 0; - if (size > 0){ - - // case EMPTY: create raw block in place - if (block->child_count == 0 && block->data == 0){ - arena_align(gen->arena, 8); - result = push_array(gen->arena, U8, size + 1); - block->data = result; - block->total_size = size; - } - - // case NONEMPTY: attach new memory as a child - else{ - PEGEN_Block *child = pegen_block_new(gen); - - arena_align(gen->arena, 8); - result = push_array(gen->arena, U8, size + 1); - child->data = result; - child->total_size = size; - - pegen_block_push_block(gen, block, child); - } - } - return(result); -} - -function void* -pegen_block_push_write(PEGEN_Ctx *gen, PEGEN_Block *block, String8 data){ - void *result = pegen_block_push(gen, block, data.size); - MemoryCopy(result, data.str, data.size); - return(result); -} - -function U8* -pegen_block_push_cstring(PEGEN_Ctx *gen, PEGEN_Block *block, String8 string){ - void *result = pegen_block_push(gen, block, string.size + 1); - MemoryCopy(result, string.str, string.size); - ((U8*)result)[string.size] = 0; - return(result); -} - -function void -pegen_block_align(PEGEN_Ctx *gen, PEGEN_Block *block, U8 fillbyte, U32 align){ - Assert(block != 0); - Assert(IsPow2OrZero(align) && align != 0); - - // adjust this block's alignment state - block->padding_fillbyte = fillbyte; - block->base_alignment = Max(block->base_alignment, align); - - // push padding onto this block to align it if it is not aligned - U32 new_pos = AlignUpPow2(block->total_size, align); - U32 size = new_pos - block->total_size; - U8 *padding = (U8*)pegen_block_push(gen, block, size); - memory_fill(padding, size, block->padding_fillbyte); -} - -function void -pegen_block_fill_to_size(PEGEN_Ctx *gen, PEGEN_Block *block, U8 fillbyte, U32 target_size){ - if (block->total_size < target_size){ - U32 fill_size = target_size - block->total_size; - void *mem = pegen_block_push(gen, block, fill_size); - memory_fill(mem, fill_size, fillbyte); - } -} - -function void -pegen_block_push_block(PEGEN_Ctx *gen, PEGEN_Block *list, PEGEN_Block *block){ - Assert(list != 0); - if (block != 0){ - Assert(!list->attached); - Assert(!block->attached); - - // if (HAS RAW BLOCK) then (TRANSFER THE RAW BLOCK TO A CHILD BLOCK) - if (list->child_count == 0 && list->data != 0){ - PEGEN_Block *child = pegen_block_new(gen); - child->data = list->data; - child->total_size = list->total_size; - - list->data = 0; - list->total_size = 0; - - SLLQueuePush_NZ(list->first_child, list->last_child, child, next_sibling, 0); - child->attached = 1; - child->off_within_parent = list->total_size; - child->parent = list; - list->child_count = 1; - list->total_size += child->total_size; - } - - // align for this block - pegen_block_align(gen, list, list->padding_fillbyte, block->base_alignment); - - // attach block to list - { - SLLQueuePush_NZ(list->first_child, list->last_child, block, next_sibling, 0); - block->attached = 1; - block->off_within_parent = list->total_size; - block->parent = list; - list->child_count += 1; - list->total_size += block->total_size; - - list->base_alignment = Max(list->base_alignment, block->base_alignment); - } - } -} - -function U32 -pegen_block_get_size(PEGEN_Block* block){ - U32 result = 0; - if (block != 0){ - result = block->total_size; - } - return(result); -} - -function String8 -pegen_block_flatten(Arena *arena, PEGEN_Block *block){ - String8 result = {0}; - if (block != 0){ - U8 *data = push_array(arena, U8, block->total_size); - pegen_block_flatten__recursive(block, data); - result = str8(data, block->total_size); - } - return(result); -} - -function void -pegen_block_flatten__recursive(PEGEN_Block *block, U8 *dst){ - Assert(block != 0 && block->child_count == 0 || block->data == 0); - - if (block->data != 0){ - MemoryCopy(dst, block->data, block->total_size); - } - else{ - U32 off = 0; - for (PEGEN_Block *child = block->first_child; - child != 0; - child = child->next_sibling){ - pegen_block_flatten__recursive(child, dst + off); - off += child->total_size; - } - } -} - -function U32 -pegen_block_off_relative_to_ancestor(PEGEN_Block *block, PEGEN_Block *ancestor){ - U32 result = max_U32; - U32 off_accumulator = 0; - for (PEGEN_Block *blocki = block; - blocki != 0; - blocki = blocki->parent){ - if (blocki == ancestor){ - result = off_accumulator; - break; - } - off_accumulator += blocki->off_within_parent; - } - return(result); -} - -// labels - -function PEGEN_Label -pegen_label(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off){ - PEGEN_Label label = {block, off}; - return(label); -} - -function PEGEN_Label -pegen_label_from_pointer(PEGEN_Ctx *gen, void *ptr){ - PEGEN_Label result = {0}; - for (PEGEN_Block *block = gen->first_block; - block != 0; - block = block->next_bucket){ - if (block->data != 0 && - block->data <= (U8*)ptr && - (U8*)ptr <= block->data + block->total_size){ - result = pegen_label(gen, block, (U8*)ptr - block->data); - break; - } - } - return(result); -} - -function void* -pegen_pointer_from_block_off(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off){ - void *result = 0; - - PEGEN_Block *blocki = block; - U32 offi = off; - - start: - if (blocki->data != 0){ - if (offi < blocki->total_size){ - result = blocki->data + offi; - } - } - else{ - U32 cursor_off = 0; - for (PEGEN_Block *child = blocki->first_child; - child != 0; - child = child->next_sibling){ - if (offi < cursor_off + child->total_size){ - blocki = child; - offi = (offi - cursor_off); - goto start; - } - cursor_off += child->total_size; - } - } - - return(result); -} - -function void* -pegen_pointer_from_label(PEGEN_Ctx *gen, PEGEN_Label label){ - void *result = pegen_pointer_from_block_off(gen, label.block, label.off); - return(result); -} - -// patches - -function PEGEN_PatchList* -pegen_patch_list_new(PEGEN_Ctx *gen){ - PEGEN_PatchList *list = push_array(gen->arena, PEGEN_PatchList, 1); - return(list); -} - -function PEGEN_Patch* -pegen_patch_push(PEGEN_Ctx *gen, PEGEN_PatchList *list){ - PEGEN_Patch *patch = push_array(gen->arena, PEGEN_Patch, 1); - SLLQueuePush(list->first, list->last, patch); - list->count += 1; - return(patch); -} - -function void -pegen_patch_foff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, - void *patchpos_ptr, PEGEN_Label targetpos){ - PEGEN_Label patchpos = pegen_label_from_pointer(gen, patchpos_ptr); - Assert(patchpos.block != 0); - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_FileAbsolute; - patch->patch_numbits = 32; -} - -function void -pegen_patch_voff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, - void *patchpos_ptr, PEGEN_Label targetpos){ - PEGEN_Label patchpos = pegen_label_from_pointer(gen, patchpos_ptr); - Assert(patchpos.block != 0); - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_VirtAbsolute; - patch->patch_numbits = 32; -} - -function void -pegen_patch_voff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, - void *patchpos_ptr, void *targetpos_ptr){ - PEGEN_Label targetpos = pegen_label_from_pointer(gen, targetpos_ptr); - Assert(targetpos.block != 0); - pegen_patch_voff32_label(gen, list, patchpos_ptr, targetpos); -} - -function void -pegen_patch_vrel32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, - PEGEN_Label patchpos, PEGEN_Label targetpos, - S8 bias){ - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_VirtRelative; - patch->patch_numbits = 32; - patch->bias = bias; -} - -function void -pegen_patch_vaddr64(PEGEN_Ctx *gen, PEGEN_PatchList *list, - PEGEN_Label patchpos, PEGEN_Label targetpos){ - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_VirtAddress; - patch->patch_numbits = 64; -} - -function void -pegen_patch_secnum16(PEGEN_Ctx *gen, PEGEN_PatchList *list, - void *patchpos_ptr, PEGEN_Label targetpos){ - PEGEN_Label patchpos = pegen_label_from_pointer(gen, patchpos_ptr); - Assert(patchpos.block != 0); - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_SectionNumber; - patch->patch_numbits = 16; -} - -function void -pegen_patch_secoff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, - void *patchpos_ptr, PEGEN_Label targetpos){ - PEGEN_Label patchpos = pegen_label_from_pointer(gen, patchpos_ptr); - Assert(patchpos.block != 0); - PEGEN_Patch *patch = pegen_patch_push(gen, list); - patch->patchpos = patchpos; - patch->targetpos = targetpos; - patch->kind = PEGEN_PatchKind_SectionOffset; - patch->patch_numbits = 32; -} - -function void -pegen_data_apply_patches(PEGEN_Ctx *gen, U8 *data, U64 size, PEGEN_Block *block, - PEGEN_Layout *layout, PEGEN_PatchList *patch_list){ - - // apply patches - for (PEGEN_Patch *patch = patch_list->first; - patch != 0; - patch = patch->next){ - - // extract patch location information - PEGEN_Label patchpos = patch->patchpos; - U32 patch_off = - pegen_block_off_relative_to_ancestor(patchpos.block, block) + patchpos.off; - Assert(patch_off <= block->total_size); - - U32 target_size = CeilIntDiv(patch->patch_numbits, 8); - - U8 *data_ptr = data + patch_off; - - // extract target location information - PEGEN_Label targetpos = patch->targetpos; - U32 target_off = - pegen_block_off_relative_to_ancestor(targetpos.block, block) + targetpos.off; - - // caculate value - U64 val = 0; - switch (patch->kind){ - case PEGEN_PatchKind_FileAbsolute: - { - val = target_off; - }break; - - case PEGEN_PatchKind_FileRelative: - { - val = target_off - patch_off; - }break; - - case PEGEN_PatchKind_VirtAbsolute: - { - val = pegen_layout_voff_from_foff(layout, target_off); - }break; - - case PEGEN_PatchKind_VirtRelative: - { - U32 target_voff = pegen_layout_voff_from_foff(layout, target_off); - U32 patch_voff = pegen_layout_voff_from_foff(layout, patch_off); - val = target_voff - patch_voff; - }break; - - case PEGEN_PatchKind_VirtAddress: - { - U32 target_voff = pegen_layout_voff_from_foff(layout, target_off); - val = target_voff + layout->image_base_vaddr; - }break; - - case PEGEN_PatchKind_SectionNumber: - { - val = pegen_layout_secnum_from_foff(layout, target_off); - }break; - - case PEGEN_PatchKind_SectionOffset: - { - val = pegen_layout_secoff_from_foff(layout, target_off); - }break; - } - - // set relocation bits - U64 bitbuf = 0; - { - Assert(patch->patch_bitoff < 8); - - MemoryCopy(&bitbuf, data_ptr, target_size); - - // TODO(allen): master bitwise manipulations - simplify this - - U32 lobits = patch->patch_bitoff; - U32 midbits = patch->patch_numbits; - U32 lomidbits = lobits + midbits; - U32 hibits = 64 - lomidbits; - U32 midhibits = midbits + hibits; - - U64 hipart = bitbuf >> lomidbits; - U64 midpart = val; - U64 lopart = (bitbuf << midhibits) >> midhibits; - - U64 final = lopart | (midpart << lobits) | (hipart << lomidbits); - - MemoryCopy(data_ptr, &final, target_size); - } - } -} - -// sections - -function PEGEN_SectionList* -pegen_section_list_new(PEGEN_Ctx *gen){ - PEGEN_SectionList *list = push_array(gen->arena, PEGEN_SectionList, 1); - return(list); -} - -function PEGEN_Section* -pegen_section_push(PEGEN_Ctx *gen, PEGEN_SectionList *list, - String8 name, PE_SectionFlags flags, U32 vsize, - PEGEN_Block *block){ - PEGEN_Section *section = push_array(gen->arena, PEGEN_Section, 1); - SLLQueuePush(list->first, list->last, section); - list->count += 1; - section->block = block; - section->name = name.str; - section->name_size = name.size; - section->secnum = list->count; - section->flags = flags; - section->vsize = vsize; - return(section); -} - -function void -pegen_section_equip_coff_relocs(PEGEN_Section *section, - PEGEN_CoffRelocList *list){ - section->coff_relocs = list; -} - -// image config - -function PEGEN_ImgConfig* -pegen_img_config_new(PEGEN_Ctx *gen){ - PEGEN_ImgConfig *config = push_array(gen->arena, PEGEN_ImgConfig, 1); - config->base_vaddr = 0x140000000; - config->file_align = 512; - config->virt_align = KB(4); - return(config); -} - -function void -pegen_img_config_base_vaddr(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - U64 base_vaddr){ - config->base_vaddr = base_vaddr; -} - -function void -pegen_img_config_file_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - U32 file_align){ - config->file_align = file_align; -} - -function void -pegen_img_config_virt_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - U32 virt_align){ - config->virt_align = virt_align; -} - -function void -pegen_img_config_entry_point(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - PEGEN_Label label){ - config->entry_point = label; -} - -function void -pegen_img_config_data_directory(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - PE_DataDirectoryIdx idx, PEGEN_Block *block){ - if (idx < PE_DataDirectoryIdx_COUNT){ - config->data_directories[idx] = block; - } -} - -// object config - -function PEGEN_ObjConfig* -pegen_obj_config_new(PEGEN_Ctx *gen){ - PEGEN_ObjConfig *config = push_array(gen->arena, PEGEN_ObjConfig, 1); - return(config); -} - -function void -pegen_obj_config_symbol_table(PEGEN_Ctx *gen, PEGEN_ObjConfig *config, - PEGEN_SymbolTableBaked *table){ - config->symbol_table = table; -} - -// headers & layouts - -function PEGEN_HeaderAndLayout -pegen_img_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SectionList *section_list, - PEGEN_ImgConfig *img_config){ - // fill layout sections - U32 section_count = section_list->count; - PEGEN_LayoutSection *sections = - push_array(gen->arena, PEGEN_LayoutSection, section_count); - - U32 file_align = img_config->file_align; - U32 virt_align = img_config->virt_align; - - U32 headers_size = sizeof(pe_dos_header); - headers_size += sizeof(U32); - headers_size += sizeof(PE_CoffHeader); - headers_size += sizeof(PE_OptionalHeader32Plus); - headers_size += sizeof(PE_DataDirectory)*PE_DataDirectoryIdx_COUNT; - headers_size += sizeof(PE_SectionHeader)*section_count; - headers_size = AlignUpPow2(headers_size, file_align); - - { - U32 foff_cursor = headers_size; - U32 voff_cursor = AlignUpPow2(headers_size, virt_align); - - PEGEN_LayoutSection *layout_section = sections; - for (PEGEN_Section *section_node = section_list->first; - section_node != 0; - section_node = section_node->next, layout_section += 1){ - U32 block_size = pegen_block_get_size(section_node->block); - U32 vsize = ((section_node->vsize == PEGEN_DefaultVSize)? - block_size:section_node->vsize); - - U32 aligned_block_size = AlignUpPow2(block_size, file_align); - U16 fsize_padding = (U16)(aligned_block_size - block_size); - - layout_section->block = section_node->block; - layout_section->name = section_node->name; - layout_section->name_size = section_node->name_size; - layout_section->voff = voff_cursor; - layout_section->foff = foff_cursor; - layout_section->vsize = vsize; - layout_section->fsize = block_size; - layout_section->fsize_padding = fsize_padding; - layout_section->flags = section_node->flags; - - foff_cursor += block_size; - foff_cursor = AlignUpPow2(foff_cursor, file_align); - - voff_cursor += block_size; - voff_cursor = AlignUpPow2(vsize, virt_align); - } - } - - - // fill total layout - PEGEN_Layout *layout = push_array(gen->arena, PEGEN_Layout, 1); - layout->sections = sections; - layout->section_count = section_count; - layout->image_base_vaddr = img_config->base_vaddr; - - - // calculate layout stats - U32 total_size_text = 0; - U32 total_size_inited_data = 0; - U32 total_size_zeroed_data = 0; - U32 text_voff = 0; - U32 image_size = 0; - - for (U32 i = 0; i < section_count; i += 1){ - PEGEN_LayoutSection *layout_section = sections + i; - - if ((layout_section->flags & PE_SectionFlag_CNT_CODE) != 0){ - total_size_text += layout_section->fsize + layout_section->fsize_padding; - } - if ((layout_section->flags & PE_SectionFlag_CNT_INITIALIZED_DATA) != 0){ - total_size_inited_data += layout_section->fsize + layout_section->fsize_padding; - } - if ((layout_section->flags & PE_SectionFlag_CNT_UNINITIALIZED_DATA) != 0){ - total_size_zeroed_data += layout_section->fsize + layout_section->fsize_padding; - } - - if (text_voff == 0 && - (layout_section->flags & PE_SectionFlag_CNT_CODE) != 0){ - text_voff = layout_section->voff; - } - - if (layout_section->vsize > 0){ - U32 opl_voff = layout_section->voff + layout_section->vsize; - opl_voff = AlignUpPow2(opl_voff, img_config->virt_align); - image_size = opl_voff; - } - } - - // header - PEGEN_Block *block = pegen_block_new(gen); - { - // TODO(allen): this doesn't belong here - DateTime date = os_now_universal_time(); - DateTime local_date = os_local_time_from_universal(&date); - U32 time_stamp = os_time_stamp_32_from_date_time(&local_date); - - // dos header - pegen_block_push_write(gen, block, str8(pe_dos_header, sizeof(pe_dos_header))); - - // pe signature - { - U32 *signature = pegen_block_push_array(gen, block, U32, 1); - *signature = PE_SIGNATURE; - } - - // coff header - { - PE_CoffHeader *coffhdr = pegen_block_push_array(gen, block, PE_CoffHeader, 1); - // TODO(allen): this should be something the user has more control over - coffhdr->machine_type = PE_MachineType_AMD64; - coffhdr->section_count = section_count; - coffhdr->time_stamp = time_stamp; - coffhdr->optional_header_size = sizeof(PE_OptionalHeader32Plus) + 16*sizeof(PE_DataDirectory); - // TODO(allen): this should be something the user has more control over - coffhdr->flags = (PE_Flag_LARGE_ADDRESS_AWARE | - PE_Flag_EXECUTABLE_IMAGE); - } - - // optional header (pe32plus) - { - PE_OptionalHeader32Plus *opthdr = pegen_block_push_array(gen, block, PE_OptionalHeader32Plus, 1); - opthdr->magic = PE_OptionalHeaderMagic_PE32Plus; - opthdr->linker_version_major = 0xFF; - opthdr->linker_version_minor = 0xFF; - opthdr->total_size_text = total_size_text; - opthdr->total_size_inited_data = total_size_inited_data; - opthdr->total_size_zeroed_data = total_size_zeroed_data; - opthdr->entry_point_voff = - pegen_layout_voff_from_label(layout, img_config->entry_point); - opthdr->text_voff = text_voff; - - opthdr->image_base_vaddr = img_config->base_vaddr; - opthdr->section_alignment = virt_align; - opthdr->file_alignment = file_align; - opthdr->os_version_major = 6; - opthdr->os_version_minor = 0; - opthdr->subsystem_version_major = 6; - opthdr->subsystem_version_minor = 0; - opthdr->image_size = image_size; - opthdr->headers_size = headers_size; - opthdr->subsystem = PE_WindowsSubsystem_WINDOWS_CUI; - // TODO(allen): this should be something the user has more control over - opthdr->dll_flags = (PE_DLLFlag_HIGH_ENTROPY_VA | - PE_DLLFlag_DYNAMIC_BASE | - PE_DLLFlag_NX_COMPAT | - PE_DLLFlag_TERMINAL_SERVER_AWARE); - opthdr->data_directory_count = 16; - opthdr->stack_size_reserve = MB(1); - opthdr->stack_size_commit = KB(4); - opthdr->heap_size_reserve = MB(1); - opthdr->heap_size_commit = KB(4); - } - - // data directories - { - PE_DataDirectory *datadir = - pegen_block_push_array(gen, block, PE_DataDirectory, - PE_DataDirectoryIdx_COUNT); - - for (U32 i = 0; i < PE_DataDirectoryIdx_COUNT; i += 1){ - PEGEN_Block *block = img_config->data_directories[i]; - if (block != 0){ - datadir[i].voff = pegen_layout_voff_from_block(layout, block); - datadir[i].size = pegen_block_get_size(block); - } - } - } - - // section table - { - PE_SectionHeader *sechdrs = - pegen_block_push_array(gen, block, PE_SectionHeader, section_count); - - for (U64 i = 0; i < section_count; i += 1){ - PEGEN_LayoutSection *layout_section = sections + i; - PE_SectionHeader *sechdr = sechdrs + i; - MemoryCopy(sechdr->name, layout_section->name, layout_section->name_size); - sechdr->voff = layout_section->voff; - sechdr->vsize = layout_section->vsize; - sechdr->foff = layout_section->foff; - sechdr->fsize = layout_section->fsize + layout_section->fsize_padding; - sechdr->flags = layout_section->flags; - } - } - } - - // fill result - PEGEN_HeaderAndLayout result = {0}; - result.header = block; - result.layout = layout; - return(result); -} - -function PEGEN_HeaderAndLayout -pegen_obj_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SectionList *section_list, - PEGEN_ObjConfig *obj_config){ - // fill layout sections - U32 section_count = section_list->count; - PEGEN_LayoutSection *sections = - push_array(gen->arena, PEGEN_LayoutSection, section_count); - - { - U32 foff_cursor = sizeof(PE_CoffHeader); - foff_cursor += sizeof(PE_SectionHeader)*section_count; - - PEGEN_LayoutSection *layout_section = sections; - for (PEGEN_Section *section_node = section_list->first; - section_node != 0; - section_node = section_node->next, layout_section += 1){ - // bake the secondary block here (if necessary) - PEGEN_CoffRelocList *relocs = section_node->coff_relocs; - PEGEN_Block *reloc_block = 0; - if (relocs != 0){ - reloc_block = - pegen_block_from_coff_reloc_list(gen, obj_config->symbol_table, relocs); - } - - // fill the layout section - U32 block_size = pegen_block_get_size(section_node->block); - U32 relocs_block_size = pegen_block_get_size(reloc_block); - - layout_section->block = section_node->block; - layout_section->reloc_block = reloc_block; - layout_section->name = section_node->name; - layout_section->name_size = section_node->name_size; - layout_section->voff = 0; - layout_section->foff = foff_cursor; - layout_section->vsize = 0; - layout_section->fsize = block_size; - layout_section->flags = section_node->flags; - - if (relocs != 0){ - layout_section->reloc_count = (U16)relocs->count; - } - - // advance foff cursor - foff_cursor += block_size; - foff_cursor = AlignUpPow2(foff_cursor, 2); - foff_cursor += relocs_block_size; - } - } - - - // fill total layout - PEGEN_Layout *layout = push_array(gen->arena, PEGEN_Layout, 1); - layout->sections = sections; - layout->section_count = section_count; - - - // header - PEGEN_Block *block = pegen_block_new(gen); - { - // TODO(allen): this doesn't belong here - DateTime date = os_now_universal_time(); - DateTime local_date = os_local_time_from_universal(&date); - U32 time_stamp = os_time_stamp_32_from_date_time(&local_date); - - PE_CoffHeader *coffhdr = pegen_block_push_array(gen, block, PE_CoffHeader, 1); - // TODO(allen): this should be something the user has more control over - coffhdr->machine_type = PE_MachineType_AMD64; - coffhdr->section_count = section_list->count; - coffhdr->time_stamp = time_stamp; - - PEGEN_SymbolTableBaked *symbol_table = obj_config->symbol_table; - { - PEGEN_Label symbol_table_pos = pegen_label(gen, symbol_table->block, 0); - pegen_patch_foff32_label(gen, patch_list, - &coffhdr->symbol_table_foff, - symbol_table_pos); - } - - coffhdr->symbol_count = symbol_table->symbol_count; - // TODO(allen): this should be something the user has more control over - coffhdr->flags = 0; - } - - // section table - { - PE_SectionHeader *sechdrs = pegen_block_push_array(gen, block, PE_SectionHeader, section_count); - - for (U64 i = 0; i < section_count; i += 1){ - PEGEN_LayoutSection *layout_section = sections + i; - PE_SectionHeader *sechdr = sechdrs + i; - MemoryCopy(sechdr->name, layout_section->name, layout_section->name_size); - sechdr->voff = layout_section->voff; - sechdr->vsize = layout_section->vsize; - sechdr->foff = layout_section->foff; - sechdr->fsize = layout_section->fsize + layout_section->fsize_padding; - sechdr->flags = layout_section->flags; - - if (layout_section->reloc_block != 0){ - PEGEN_Label pos = pegen_label(gen, layout_section->reloc_block, 0); - pegen_patch_foff32_label(gen, patch_list, &sechdr->relocations_foff, pos); - } - sechdr->relocation_count = layout_section->reloc_count; - } - } - - // fill result - PEGEN_HeaderAndLayout result = {0}; - result.header = block; - result.layout = layout; - return(result); -} - -function U32 -pegen_layout_voff_from_foff(PEGEN_Layout *layout, U32 foff){ - U32 voff = 0; - for (U32 i = 0; i < layout->section_count; i += 1){ - PEGEN_LayoutSection *sec = layout->sections + i; - if (sec->foff <= foff && foff < sec->foff + sec->fsize){ - voff = sec->voff + foff - sec->foff; - break; - } - } - return(voff); -} - -function U32 -pegen_layout_secnum_from_foff(PEGEN_Layout *layout, U32 foff){ - U32 secnum = 0; - for (U32 i = 0; i < layout->section_count; i += 1){ - PEGEN_LayoutSection *sec = layout->sections + i; - if (sec->foff <= foff && foff < sec->foff + sec->fsize){ - secnum = i + 1; - break; - } - } - return(secnum); -} - -function U32 -pegen_layout_secoff_from_foff(PEGEN_Layout *layout, U32 foff){ - U32 secoff = max_U32; - for (U32 i = 0; i < layout->section_count; i += 1){ - PEGEN_LayoutSection *sec = layout->sections + i; - if (sec->foff <= foff && foff < sec->foff + sec->fsize){ - secoff = foff - sec->foff; - break; - } - } - return(secoff); -} - -function U32 -pegen_layout_voff_from_block(PEGEN_Layout *layout, PEGEN_Block *block){ - U32 result = 0; - - // TODO(allen): accelerator for Block -> Section - - for (U32 i = 0; i < layout->section_count; i += 1){ - PEGEN_LayoutSection *layout_section = layout->sections + i; - - B32 section_contains_block = 0; - { - PEGEN_Block *section_block = layout_section->block; - for (PEGEN_Block *blocki = block; - blocki != 0; - blocki = blocki->parent){ - if (blocki == section_block){ - section_contains_block = 1; - break; - } - } - } - - if (section_contains_block){ - U32 block_off = pegen_block_off_relative_to_ancestor(block, layout_section->block); - result = layout_section->voff + block_off; - } - } - - return(result); -} - -function U32 -pegen_layout_voff_from_label(PEGEN_Layout *layout, PEGEN_Label label){ - U32 block_voff = pegen_layout_voff_from_block(layout, label.block); - U32 result = block_voff + label.off; - return(result); -} - -// symbol table - -function PEGEN_SymbolTable* -pegen_symbol_table_new(PEGEN_Ctx *gen){ - PEGEN_SymbolTable *table = push_array(gen->arena, PEGEN_SymbolTable, 1); - return(table); -} - -function PEGEN_Symbol* -pegen_symbol_push(PEGEN_Ctx *gen, PEGEN_SymbolTable *symbols, - String8 name, - PE_CoffSymbolStorageClass storage_class, - PE_CoffSymbolType type, - PEGEN_Label pos){ - PEGEN_Symbol *symbol = push_array(gen->arena, PEGEN_Symbol, 1); - SLLQueuePush(symbols->first, symbols->last, symbol); - symbols->count += 1; - - symbol->name = str8_push_copy(gen->arena, name); - symbol->storage_class = storage_class; - symbol->type = type; - symbol->pos = pos; - - return(symbol); -} - -function PEGEN_SymbolTableBaked* -pegen_block_from_symbol_table(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SymbolTable *symbol_table){ - // setup blocks for symbol table and string table - PEGEN_Block *symbol_records = pegen_block_new(gen); - PEGEN_Block *string_table = pegen_block_new(gen); - - // allocate 4 bytes for string table size - U32 *string_table_size = pegen_block_push_array(gen, string_table, U32, 1); - - // symbol index map - U64 symbol_count = symbol_table->count; - PEGEN_Symbol **symbols = push_array(gen->arena, PEGEN_Symbol*, symbol_count); - U32 *symbol_idxs = push_array(gen->arena, U32, symbol_count); - - // serialize each symbol - { - U32 i = 0; - for (PEGEN_Symbol *symbol = symbol_table->first; - symbol != 0; - symbol = symbol->next, i += 1){ - U32 symbol_idx = pegen_block_get_size(symbol_records)/sizeof(PE_CoffSymbolRecord); - - PE_CoffSymbolRecord *record = - pegen_block_push_array(gen, symbol_records, PE_CoffSymbolRecord, 1); - - // fill record->name - if (symbol->name.size <= sizeof(record->name.raw)){ - MemoryCopy(record->name.raw, symbol->name.str, symbol->name.size); - } - else{ - U32 string_table_off = pegen_block_get_size(string_table); - pegen_block_push_cstring(gen, string_table, symbol->name); - record->name.zero = 0; - record->name.string_table_off = string_table_off; - } - - // TODO(allen): implement switch across all types/storage_classes - - // assign record's section number & val - pegen_patch_secnum16(gen, patch_list, &record->sec_number, symbol->pos); - pegen_patch_secoff32(gen, patch_list, &record->val, symbol->pos); - - // fill rest of record's fields - record->type = symbol->type; - record->storage_class = symbol->storage_class; - record->aux_symbol_count = 0; - - // fill symbol index map - symbols[i] = symbol; - symbol_idxs[i] = symbol_idx; - } - } - - // fill in string table size - *string_table_size = pegen_block_get_size(string_table); - - // assemble final block - PEGEN_Block *block = pegen_block_new(gen); - pegen_block_push_block(gen, block, symbol_records); - pegen_block_push_block(gen, block, string_table); - - // assemble final result - PEGEN_SymbolTableBaked *result = push_array(gen->arena, PEGEN_SymbolTableBaked, 1); - result->block = block; - result->symbols = symbols; - result->symbol_idxs = symbol_idxs; - result->symbol_count = symbol_table->count; - return(result); -} - -function U32 -pegen_symbol_idx_from_ptr(PEGEN_SymbolTableBaked *table, - PEGEN_Symbol *symbol){ - U32 result = max_U32; - PEGEN_Symbol **symbols = table->symbols; - U32 symbol_count = table->symbol_count; - for (U32 i = 0; i < symbol_count; i += 1){ - if (symbols[i] == symbol){ - result = table->symbol_idxs[i]; - break; - } - } - return(result); -} - -// coff relocs - -function PEGEN_CoffRelocList* -pegen_coff_reloc_list_new(PEGEN_Ctx *gen){ - PEGEN_CoffRelocList *list = push_array(gen->arena, PEGEN_CoffRelocList, 1); - return(list); -} - -function void -pegen_coff_reloc_push(PEGEN_Ctx *gen, PEGEN_CoffRelocList *list, - U32 off, PEGEN_Symbol *symbol, - PE_CoffRelocationType reloc_type){ - PEGEN_CoffReloc *reloc = push_array(gen->arena, PEGEN_CoffReloc, 1); - SLLQueuePush(list->first, list->last, reloc); - list->count += 1; - reloc->off = off; - reloc->symbol = symbol; - reloc->type = reloc_type; -} - -function PEGEN_Block* -pegen_block_from_coff_reloc_list(PEGEN_Ctx *gen, - PEGEN_SymbolTableBaked *symbol_table, - PEGEN_CoffRelocList *list){ - PEGEN_Block *block = pegen_block_new_aligned(gen, 2); - - for (PEGEN_CoffReloc *reloc_node = list->first; - reloc_node != 0; - reloc_node = reloc_node->next){ - PE_CoffRelocation *reloc = - pegen_block_push_array(gen, block, PE_CoffRelocation, 1); - - reloc->off = reloc_node->off; - reloc->symbol_idx = pegen_symbol_idx_from_ptr(symbol_table, reloc_node->symbol); - reloc->type = reloc_node->type; - } - - return(block); -} - -// export table - -function PEGEN_ExportTable* -pegen_export_table_new(PEGEN_Ctx *gen){ - PEGEN_ExportTable *table = push_array(gen->arena, PEGEN_ExportTable, 1); - return(table); -} - -function void -pegen_export_table_set_binary_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 name){ - table->binary_name = name; -} - -function void -pegen_export_table_set_time_stamp(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U32 time_stamp){ - table->time_stamp = time_stamp; -} - -function void -pegen_export_table_set_version(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U16 major, U16 minor){ - table->version_major = major; - table->version_minor = minor; -} - -function PEGEN_Export* -pegen_export_new(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Label label){ - PEGEN_Export *exp = push_array(gen->arena, PEGEN_Export, 1); - SLLQueuePush(table->first, table->last, exp); - table->count += 1; - exp->symbol_label = label; - return(exp); -} - -function PEGEN_Export* -pegen_export_new_fwd(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 fwdname){ - PEGEN_Export *exp = push_array(gen->arena, PEGEN_Export, 1); - SLLQueuePush(table->first, table->last, exp); - table->count += 1; - exp->symbol_fwdname = fwdname; - return(exp); -} - -function void -pegen_export_add_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Export *exp, String8 name){ - str8_list_push(gen->arena, &exp->names, name); - table->name_count += 1; -} - -function PEGEN_Block* -pegen_block_from_exports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_ExportTable *table){ - PEGEN_Block *block = 0; - - if (table->count > 0){ - block = pegen_block_new(gen); - - // place directory table - PE_ExportDirectoryTable *petable = pegen_block_push_array(gen, block, PE_ExportDirectoryTable, 1); - - // place exports - U32 *exports = pegen_block_push_array(gen, block, U32, table->count); - - // place name_voffs - U32 *name_voffs = pegen_block_push_array(gen, block, U32, table->name_count); - - // place ordinals - U16 *ordinals = pegen_block_push_array(gen, block, U16, table->name_count); - - // place binary name - U8 *binary_name = pegen_block_push_cstring(gen, block, table->binary_name); - - // fill exports, names & ordinals - U32 export_i = 0; - U32 ordinal_i = 0; - for (PEGEN_Export *exp = table->first; - exp != 0; - exp = exp->next, export_i += 1){ - - if (exp->symbol_label.block != 0){ - // ptr to fill the export - pegen_patch_voff32_label(gen, patch_list, &exports[export_i], exp->symbol_label); - } - else{ - // place the fwdname - U8 *fwdname = pegen_block_push_cstring(gen, block, exp->symbol_fwdname); - - // ptr to fill the fwdname voff - pegen_patch_voff32(gen, patch_list, &exports[export_i], fwdname); - } - - // fill ordinals & names - for (String8Node *export_name = exp->names.first; - export_name != 0; - export_name = export_name->next, ordinal_i += 1){ - ordinals[ordinal_i] = export_i; - - // place the name's string - U8 *string = pegen_block_push_cstring(gen, block, export_name->string); - - // ptr to fill the name_voff - pegen_patch_voff32(gen, patch_list, &name_voffs[ordinal_i], string); - } - } - - // fill petable - { - petable->time_stamp = table->time_stamp; - petable->version_major = table->version_major; - petable->version_minor = table->version_minor; - - pegen_patch_voff32(gen, patch_list, &petable->binary_name_voff, binary_name); - - petable->ordinal_base = 1; - petable->export_count = table->count; - petable->ordinal_count = table->name_count; - - pegen_patch_voff32(gen, patch_list, &petable->export_voff, exports); - pegen_patch_voff32(gen, patch_list, &petable->name_voff, name_voffs); - pegen_patch_voff32(gen, patch_list, &petable->ordinal_voff, ordinals); - } - } - - return(block); -} - -// import table - -function PEGEN_ImportList* -pegen_import_list_new(PEGEN_Ctx *gen){ - PEGEN_ImportList *result = push_array(gen->arena, PEGEN_ImportList, 1); - return(result); -} - -function PEGEN_ImportTable* -pegen_import_table_new(PEGEN_Ctx *gen, PEGEN_ImportList *list, - String8 binary_name, U32 time_stamp){ - PEGEN_ImportTable *result = push_array(gen->arena, PEGEN_ImportTable, 1); - SLLQueuePush(list->first_table, list->last_table, result); - list->table_count += 1; - result->time_stamp = time_stamp; - result->binary_name = binary_name; - return(result); -} - -function void -pegen_import_new(PEGEN_Ctx *gen, PEGEN_ImportTable *table, - String8 name, U16 ordinal){ - PEGEN_Import *import = push_array(gen->arena, PEGEN_Import, 1); - SLLQueuePush(table->first, table->last, import); - table->count += 1; - import->name = name; - import->ordinal = ordinal; -} - -function PEGEN_ImportBlocks -pegen_blocks_from_imports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_ImportList *imports){ - PEGEN_Block *block_directory_table = 0; - PEGEN_Block *block_iat = 0; - PEGEN_Block *block_import_data = 0; - - if (imports->table_count > 0){ - // setup import data blocks - block_directory_table = pegen_block_new(gen); - block_iat = pegen_block_new_aligned(gen, 8); - - PEGEN_Block *block_import_lookup_table = pegen_block_new_aligned(gen, 8); - PEGEN_Block *block_import_names = pegen_block_new(gen); - - // setup directory table - U32 load_count = imports->table_count; - PE_ImportDirectoryTable *directory_table = - pegen_block_push_array(gen, block_directory_table, - PE_ImportDirectoryTable, load_count + 1); - - // fill directory info & other blocks - { - PE_ImportDirectoryTable *directory = directory_table; - for (PEGEN_ImportTable *table = imports->first_table; - table != 0; - table = table->next, directory += 1){ - - // allocate import tables - U32 import_count = table->count; - U64 *import_lookup_table = - pegen_block_push_array(gen, block_import_lookup_table, U64, import_count + 1); - - U64 *import_address_table = - pegen_block_push_array(gen, block_iat, U64, import_count + 1); - - // fill import tables - { - U32 i = 0; - for (PEGEN_Import *imp = table->first; - imp != 0; - imp = imp->next, i += 1){ - - if (imp->name.size != 0){ - - // write hint & name into name block - U32 hint_name_size = 2 + imp->name.size + 1; - - pegen_block_align(gen, block_import_names, 0, 2); - U8 *hint_name = pegen_block_push_array(gen, block_import_names, U8, - hint_name_size); - - MemoryCopy(hint_name, &imp->ordinal, 2); - MemoryCopy(hint_name + 2, imp->name.str, imp->name.size); - hint_name[imp->name.size + 2] = 0; - - // assign import_lookup_table[i] & import_address_table[i]: - pegen_patch_voff32(gen, patch_list, - &import_lookup_table[i], - hint_name); - pegen_patch_voff32(gen, patch_list, - &import_address_table[i], - hint_name); - } - - // just write the ordinal and set the high bit - else{ - U64 val = imp->ordinal|(1llu << 63); - import_lookup_table[i] = val; - import_address_table[i] = val; - } - } - } - - // write binary name - U8 *binary_name = pegen_block_push_cstring(gen, block_import_names, - table->binary_name); - - // fill the directory - { - // assign directory->import_lookup_table_voff: - pegen_patch_voff32(gen, patch_list, - &directory->import_lookup_table_voff, - import_lookup_table); - - directory->time_stamp = table->time_stamp; - directory->first_forwarder_idx = 0; - - // assign directory->name_voff: - pegen_patch_voff32(gen, patch_list, - &directory->name_voff, - binary_name); - - // assign directory->import_address_table_voff: - pegen_patch_voff32(gen, patch_list, - &directory->import_address_table_voff, - import_address_table); - } - } - } - - // arrange final blocks - block_import_data = pegen_block_new(gen); - pegen_block_push_block(gen, block_import_data, block_import_lookup_table); - pegen_block_push_block(gen, block_import_data, block_import_names); - } - - PEGEN_ImportBlocks blocks = {0}; - blocks.directory_table = block_directory_table; - blocks.iat = block_iat; - blocks.import_data = block_import_data; - return(blocks); -} - -// base relocations - -function PEGEN_BaseRelocationList* -pegen_base_relocation_list_new(PEGEN_Ctx *gen){ - PEGEN_BaseRelocationList *list = push_array(gen->arena, PEGEN_BaseRelocationList, 1); - return(list); -} - -function void -pegen_base_relocation_new(PEGEN_Ctx *gen, PEGEN_BaseRelocationList *list, - PE_BaseRelocationType type, PEGEN_Label label){ - PEGEN_BaseRelocationLoose *reloc = push_array(gen->arena, PEGEN_BaseRelocationLoose, 1); - SLLQueuePush(list->first, list->last, reloc); - list->count += 1; - reloc->type = type; - reloc->label = label; -} - -function PEGEN_Block* -pegen_block_from_base_relocations(PEGEN_Ctx *gen, PEGEN_Layout *layout, - PEGEN_BaseRelocationList *list){ - PEGEN_Block *block = pegen_block_new(gen); - - ArenaTemp scratch = arena_get_scratch(0, 0); - - // resolve to array - U64 count = list->count; - PEGEN_BaseRelocation *base_relocs = push_array(scratch.arena, PEGEN_BaseRelocation, count); - { - PEGEN_BaseRelocation *base_reloc = base_relocs; - for (PEGEN_BaseRelocationLoose *node = list->first; - node != 0; - node = node->next, base_reloc += 1){ - base_reloc->type = node->type; - base_reloc->voff = pegen_layout_voff_from_label(layout, node->label); - } - } - - // sort array - sort_merge(base_relocs, sizeof(*base_relocs), count, - pegen_base_relocation_compare, 0); - - // bake base relocation data - { - PE_BaseRelocationBlock *reloc_block = 0; - U32 reloc_block_start_pos = 0; - - for (U64 i = 0; i < count; i += 1){ - U64 reloc_block_page_voff = base_relocs[i].voff & ~0xFFF; - - // emit block header - if (reloc_block == 0 || - reloc_block->page_voff != reloc_block_page_voff){ - - // close current block (if one is open) - if (reloc_block != 0){ - pegen_block_align(gen, block, 0, 4); - - U32 reloc_block_size = pegen_block_get_size(block) - reloc_block_start_pos; - reloc_block->block_size = reloc_block_size; - } - - // start new block - reloc_block_start_pos = pegen_block_get_size(block); - reloc_block = pegen_block_push_array(gen, block, PE_BaseRelocationBlock, 1); - reloc_block->page_voff = reloc_block_page_voff; - } - - // emit base relocation - { - PE_BaseRelocationTypeOffset *reloc = - pegen_block_push_array(gen, block, PE_BaseRelocationTypeOffset, 1); - *reloc = ((base_relocs[i].type) << 12) | (base_relocs[i].voff & 0xFFF); - } - } - - // close final block - if (reloc_block != 0){ - pegen_block_align(gen, block, 0, 4); - - U32 reloc_block_size = pegen_block_get_size(block) - reloc_block_start_pos; - reloc_block->block_size = reloc_block_size; - } - } - - arena_release_scratch(&scratch); - - return(block); -} - -function S32 -pegen_base_relocation_compare(void *a, void *b, void *udata){ - PEGEN_BaseRelocation *areloc = (PEGEN_BaseRelocation*)a; - PEGEN_BaseRelocation *breloc = (PEGEN_BaseRelocation*)b; - - S32 result = 0; - if (areloc->voff > breloc->voff){ - result = 1; - } - else if (areloc->voff < breloc->voff){ - result = -1; - } - return(result); -} - -// unwind info - -function PEGEN_UnwindInfoList* -pegen_unwind_info_list_new(PEGEN_Ctx *gen){ - PEGEN_UnwindInfoList *list = push_array(gen->arena, PEGEN_UnwindInfoList, 1); - return(list); -} - -function PEGEN_UnwindInfo* -pegen_unwind_info_push(PEGEN_Ctx *gen, PEGEN_UnwindInfoList *list){ - PEGEN_UnwindInfo *info = push_array(gen->arena, PEGEN_UnwindInfo, 1); - SLLQueuePush(list->first, list->last, info); - list->count += 1; - return(info); -} - -function void -pegen_unwind_info_code(PEGEN_Ctx *gen, PEGEN_UnwindInfo *info, - U8 offset, U8 opcode, U8 opinfo, U32 x){ - PEGEN_UnwindCode *code = push_array(gen->arena, PEGEN_UnwindCode, 1); - SLLQueuePush(info->first_code, info->last_code, code); - info->code_count += 1; - - U32 num_slots = pe_unwind_num_code_slot_from_opcode_opinfo(opcode, opinfo); - info->code_slot_count += num_slots; - - code->offset = offset; - code->opcode = opcode; - code->opinfo = opinfo; - code->x = x; -} - -function PEGEN_UnwindBlocks -pegen_blocks_from_unwind_info(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, PEGEN_UnwindInfoList *list){ - PEGEN_Block *exception_handlers = 0; - PEGEN_Block *unwind_info = 0; - - if (list->count > 0){ - exception_handlers = pegen_block_new(gen); - unwind_info = pegen_block_new(gen); - - for (PEGEN_UnwindInfo *info = list->first; - info != 0; - info = info->next){ - - // push & fill unwind info - PE_UnwindInfo *pe_info = - pegen_block_push_array(gen, unwind_info, PE_UnwindInfo, 1); - - pe_info->header = (info->flags << 3) | 1; - pe_info->prolog_size = info->prolog_size; - pe_info->code_count = info->code_slot_count; - pe_info->frame = (info->frame_off << 4) | info->frame_reg; - - for (PEGEN_UnwindCode *code = info->first_code; - code != 0; - code = code->next){ - U32 num_slots = pe_unwind_num_code_slot_from_opcode_opinfo(code->opcode, code->opinfo); - U16 *slots = pegen_block_push_array(gen, unwind_info, U16, num_slots); - slots[0] = PE_UnwindCode_FromOffsetOpCodeInfo(code->offset, code->opcode, code->opinfo); - if (num_slots > 1){ - MemoryCopy(slots + 1, &code->x, (num_slots - 1)*sizeof(U16)); - } - } - - pegen_block_align(gen, unwind_info, 0, 4); - - // push & fill exception handler - PE_ExceptionHandler_X86 *eh = - pegen_block_push_array(gen, exception_handlers, PE_ExceptionHandler_X86, 1); - - pegen_patch_voff32_label(gen, patch_list, &eh->begin_voff, info->start_pos); - pegen_patch_voff32_label(gen, patch_list, &eh->end_voff, info->opl_pos); - pegen_patch_voff32(gen, patch_list, &eh->unwind_voff, pe_info); - } - } - - PEGEN_UnwindBlocks blocks = {0}; - blocks.exception_handlers = exception_handlers; - blocks.unwind_info = unwind_info; - return(blocks); -} - - diff --git a/src/binary/pe/mr4th_pe.gen.h b/src/binary/pe/mr4th_pe.gen.h deleted file mode 100644 index 5eca3df..0000000 --- a/src/binary/pe/mr4th_pe.gen.h +++ /dev/null @@ -1,463 +0,0 @@ -#ifndef MR4TH_PE_GEN_H -#define MR4TH_PE_GEN_H - -//////////////////////////////// -// PE Generator Types - -// data block system - -typedef struct PEGEN_Block{ - struct PEGEN_Block *next_bucket; - struct PEGEN_Block *next_sibling; - struct PEGEN_Block *first_child; - struct PEGEN_Block *last_child; - struct PEGEN_Block *parent; - U32 child_count; - B8 attached; - U8 padding_fillbyte; - U32 base_alignment; - U8 *data; - U32 total_size; - U32 off_within_parent; -} PEGEN_Block; - -typedef struct PEGEN_Ctx{ - Arena *arena; - - PEGEN_Block *first_block; - PEGEN_Block *last_block; - U64 block_count; -} PEGEN_Ctx; - -typedef struct PEGEN_Label{ - PEGEN_Block *block; - U32 off; -} PEGEN_Label; - -// sections - -typedef struct PEGEN_Section{ - struct PEGEN_Section *next; - PEGEN_Block *block; - U8 *name; - U32 name_size; - U16 secnum; - PE_SectionFlags flags; - U32 vsize; - struct PEGEN_CoffRelocList *coff_relocs; -} PEGEN_Section; - -typedef struct PEGEN_SectionList{ - PEGEN_Section *first; - PEGEN_Section *last; - U64 count; -} PEGEN_SectionList; - -// patches for pe/coff files - -typedef enum PEGEN_PatchKind{ - PEGEN_PatchKind_FileAbsolute, - PEGEN_PatchKind_FileRelative, - PEGEN_PatchKind_VirtAbsolute, - PEGEN_PatchKind_VirtRelative, - PEGEN_PatchKind_VirtAddress, - PEGEN_PatchKind_SectionNumber, - PEGEN_PatchKind_SectionOffset, -} PEGEN_PatchKind; - -typedef struct PEGEN_Patch{ - struct PEGEN_Patch *next; - - // positions - PEGEN_Label patchpos; - PEGEN_Label targetpos; - - // patch bits - U8 patch_bitoff; - U8 patch_numbits; - - // value calculation - PEGEN_PatchKind kind; - S8 bias; - U8 shift; - - // val = ( (flags.SecIdx?IdxOf(SecOf(target)):VoffOf(target)) - // + (flags.Vaddr?ImageBaseVaddr:0) - // - (flags.RelocRel?AddrOf(reloc):0) - // - (flags.SecRel?AddrOf(SecOf(target)):0) - // + bias) >> shift - -} PEGEN_Patch; - -typedef struct PEGEN_PatchList{ - PEGEN_Patch *first; - PEGEN_Patch *last; - U64 count; -} PEGEN_PatchList; - -// image config - -typedef struct PEGEN_ImgConfig{ - U64 base_vaddr; - U32 file_align; - U32 virt_align; - PEGEN_Label entry_point; - PEGEN_Block *data_directories[PE_DataDirectoryIdx_COUNT]; -} PEGEN_ImgConfig; - -// object config - -typedef struct PEGEN_ObjConfig{ - struct PEGEN_SymbolTableBaked *symbol_table; -} PEGEN_ObjConfig; - -// headers & layouts - -typedef struct PEGEN_LayoutSection{ - PEGEN_Block *block; - U8 *name; - U32 name_size; - U32 voff; - U32 foff; - U32 vsize; - U32 fsize; - U16 fsize_padding; - PE_SectionFlags flags; - U16 reloc_count; - PEGEN_Block *reloc_block; -} PEGEN_LayoutSection; - -typedef struct PEGEN_Layout{ - PEGEN_LayoutSection *sections; - U32 section_count; - U64 image_base_vaddr; -} PEGEN_Layout; - -typedef struct PEGEN_HeaderAndLayout{ - PEGEN_Block *header; - PEGEN_Layout *layout; -} PEGEN_HeaderAndLayout; - -// symbol table - -typedef struct PEGEN_Symbol{ - struct PEGEN_Symbol *next; - String8 name; - PE_CoffSymbolStorageClass storage_class; - PE_CoffSymbolType type; - PEGEN_Label pos; -} PEGEN_Symbol; - -typedef struct PEGEN_SymbolTable{ - PEGEN_Symbol *first; - PEGEN_Symbol *last; - U64 count; -} PEGEN_SymbolTable; - -typedef struct PEGEN_SymbolTableBaked{ - PEGEN_Block *block; - U64 symbol_count; - // TODO(allen): accelerate Ptr -> Idx - PEGEN_Symbol **symbols; - U32 *symbol_idxs; -} PEGEN_SymbolTableBaked; - -// coff relocs - -typedef struct PEGEN_CoffReloc{ - struct PEGEN_CoffReloc *next; - U32 off; - PEGEN_Symbol *symbol; - PE_CoffRelocationType type; -} PEGEN_CoffReloc; - -typedef struct PEGEN_CoffRelocList{ - PEGEN_CoffReloc *first; - PEGEN_CoffReloc *last; - U64 count; -} PEGEN_CoffRelocList; - -// exports - -typedef struct PEGEN_Export{ - struct PEGEN_Export *next; - - PEGEN_Label symbol_label; - String8 symbol_fwdname; - String8List names; -} PEGEN_Export; - -typedef struct PEGEN_ExportTable{ - PEGEN_Export *first; - PEGEN_Export *last; - U32 count; - U32 name_count; - - U32 time_stamp; - U16 version_major; - U16 version_minor; - String8 binary_name; -} PEGEN_ExportTable; - -// imports - -typedef struct PEGEN_Import{ - struct PEGEN_Import *next; - String8 name; - U16 ordinal; -} PEGEN_Import; - -// TODO(allen): renaming - these aren't "tables" -typedef struct PEGEN_ImportTable{ - struct PEGEN_ImportTable *next; - - PEGEN_Import *first; - PEGEN_Import *last; - U32 count; - - U32 time_stamp; - String8 binary_name; -} PEGEN_ImportTable; - -typedef struct PEGEN_ImportList{ - PEGEN_ImportTable *first_table; - PEGEN_ImportTable *last_table; - U64 table_count; -} PEGEN_ImportList; - -typedef struct PEGEN_ImportBlocks{ - PEGEN_Block *directory_table; - PEGEN_Block *iat; - PEGEN_Block *import_data; -} PEGEN_ImportBlocks; - -// base relocations - -typedef struct PEGEN_BaseRelocationLoose{ - struct PEGEN_BaseRelocationLoose *next; - PE_BaseRelocationType type; - PEGEN_Label label; -} PEGEN_BaseRelocationLoose; - -typedef struct PEGEN_BaseRelocationList{ - PEGEN_BaseRelocationLoose *first; - PEGEN_BaseRelocationLoose *last; - U64 count; -} PEGEN_BaseRelocationList; - -typedef struct PEGEN_BaseRelocation{ - PE_BaseRelocationType type; - U32 voff; -} PEGEN_BaseRelocation; - -// unwind info - -typedef struct PEGEN_UnwindCode{ - struct PEGEN_UnwindCode *next; - U8 offset; - U8 opcode; - U8 opinfo; - U32 x; -} PEGEN_UnwindCode; - -typedef struct PEGEN_UnwindInfo{ - struct PEGEN_UnwindInfo *next; - - PEGEN_Label start_pos; - PEGEN_Label opl_pos; - - PE_UnwindInfoFlags flags; - U8 prolog_size; - U8 frame_reg; - U8 frame_off; - - PEGEN_UnwindCode *first_code; - PEGEN_UnwindCode *last_code; - U8 code_count; - U8 code_slot_count; -} PEGEN_UnwindInfo; - -typedef struct PEGEN_UnwindInfoList{ - PEGEN_UnwindInfo *first; - PEGEN_UnwindInfo *last; - U64 count; -} PEGEN_UnwindInfoList; - -typedef struct PEGEN_UnwindBlocks{ - PEGEN_Block *exception_handlers; - PEGEN_Block *unwind_info; -} PEGEN_UnwindBlocks; - -//////////////////////////////// -// PE Generator Functions - -/// gen api /// - -// ctx -function PEGEN_Ctx* pegen_begin(void); -function void pegen_release(PEGEN_Ctx *gen); - -// data blocks -function PEGEN_Block* pegen_block_new(PEGEN_Ctx *gen); -function PEGEN_Block* pegen_block_new_write(PEGEN_Ctx *gen, String8 data); -function PEGEN_Block* pegen_block_new_aligned(PEGEN_Ctx *gen, U32 align); - -function void*pegen_block_push(PEGEN_Ctx *gen, PEGEN_Block* block, U32 size); -function void*pegen_block_push_write(PEGEN_Ctx *gen, PEGEN_Block* block, String8 data); -function U8* pegen_block_push_cstring(PEGEN_Ctx *gen, PEGEN_Block* block, String8 string); - -#define pegen_block_push_array(gen,block,T,c) (T*)pegen_block_push((gen),(block),sizeof(T)*(c)) - -function void pegen_block_align(PEGEN_Ctx *gen, PEGEN_Block* block, U8 fillbyte, U32 align); -function void pegen_block_fill_to_size(PEGEN_Ctx *gen, PEGEN_Block *block, U8 fillbyte, U32 target_size); - -function void pegen_block_push_block(PEGEN_Ctx *gen, PEGEN_Block *list, PEGEN_Block *block); - -function U32 pegen_block_get_size(PEGEN_Block* block); -function String8 pegen_block_flatten(Arena *arena, PEGEN_Block *block); -function void pegen_block_flatten__recursive(PEGEN_Block *block, U8 *dst); - -function U32 pegen_block_off_relative_to_ancestor(PEGEN_Block *block, PEGEN_Block *ancestor); - -// labels -function PEGEN_Label pegen_label(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off); -function PEGEN_Label pegen_label_from_pointer(PEGEN_Ctx *gen, void *ptr); -function void* pegen_pointer_from_block_off(PEGEN_Ctx *gen, PEGEN_Block *block, U32 off); -function void* pegen_pointer_from_label(PEGEN_Ctx *gen, PEGEN_Label label); - -// patches -function PEGEN_PatchList* pegen_patch_list_new(PEGEN_Ctx *gen); - -function PEGEN_Patch* pegen_patch_push(PEGEN_Ctx *gen, PEGEN_PatchList *list); - -function void pegen_patch_foff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos); - -function void pegen_patch_voff32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos); -function void pegen_patch_voff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, void *targetpos_ptr); - -function void pegen_patch_vrel32_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, PEGEN_Label patchpos, PEGEN_Label targetpos, S8 bias); - -function void pegen_patch_vaddr64_label(PEGEN_Ctx *gen, PEGEN_PatchList *list, PEGEN_Label patchpos, PEGEN_Label targetpos); - -function void pegen_patch_secnum16(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos); -function void pegen_patch_secoff32(PEGEN_Ctx *gen, PEGEN_PatchList *list, void *patchpos_ptr, PEGEN_Label targetpos); - -function void pegen_data_apply_patches(PEGEN_Ctx *gen, U8 *data, U64 size, PEGEN_Block *block, PEGEN_Layout *layout, PEGEN_PatchList *patch_list); - -// sections -function PEGEN_SectionList* pegen_section_list_new(PEGEN_Ctx *gen); - -function PEGEN_Section* -pegen_section_push(PEGEN_Ctx *gen, PEGEN_SectionList *list, - String8 name, PE_SectionFlags flags, U32 vsize, - PEGEN_Block *block); - -function void -pegen_section_equip_coff_relocs(PEGEN_Section *section, - PEGEN_CoffRelocList *list); - -#define PEGEN_DefaultVSize (~((U32)0)) - -// image config -function PEGEN_ImgConfig* pegen_img_config_new(PEGEN_Ctx *gen); - -function void pegen_img_config_base_vaddr(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U64 base_vaddr); -function void pegen_img_config_file_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U32 file_align); -function void pegen_img_config_virt_align(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, U32 virt_align); -function void pegen_img_config_entry_point(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, PEGEN_Label label); -function void pegen_img_config_data_directory(PEGEN_Ctx *gen, PEGEN_ImgConfig *config, - PE_DataDirectoryIdx idx, PEGEN_Block *block); - -// object config -function PEGEN_ObjConfig* pegen_obj_config_new(PEGEN_Ctx *gen); - -function void pegen_obj_config_symbol_table(PEGEN_Ctx *gen, PEGEN_ObjConfig *config, - PEGEN_SymbolTableBaked *table); - -// headers & layouts -function PEGEN_HeaderAndLayout -pegen_img_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SectionList *section_list, - PEGEN_ImgConfig *img_config); - -function PEGEN_HeaderAndLayout -pegen_obj_header_bake(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SectionList *section_list, - PEGEN_ObjConfig *obj_config); - -function U32 pegen_layout_voff_from_foff(PEGEN_Layout *layout, U32 foff); -function U32 pegen_layout_secnum_from_foff(PEGEN_Layout *layout, U32 foff); -function U32 pegen_layout_secoff_from_foff(PEGEN_Layout *layout, U32 foff); - -function U32 pegen_layout_voff_from_block(PEGEN_Layout *layout, PEGEN_Block *block); -function U32 pegen_layout_voff_from_label(PEGEN_Layout *layout, PEGEN_Label label); - -// symbol table -function PEGEN_SymbolTable* pegen_symbol_table_new(PEGEN_Ctx *gen); - -function PEGEN_Symbol* pegen_symbol_push(PEGEN_Ctx *gen, PEGEN_SymbolTable *symbols, - String8 name, PE_CoffSymbolStorageClass storage_class, - PE_CoffSymbolType type, - PEGEN_Label pos); - -function PEGEN_SymbolTableBaked* -pegen_block_from_symbol_table(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, - PEGEN_SymbolTable *symbol_table); - -function U32 pegen_symbol_idx_from_ptr(PEGEN_SymbolTableBaked *table, - PEGEN_Symbol *symbol); - -// coff relocs -function PEGEN_CoffRelocList* pegen_coff_reloc_list_new(PEGEN_Ctx *gen); - -function void pegen_coff_reloc_push(PEGEN_Ctx *gen, PEGEN_CoffRelocList *list, - U32 off, PEGEN_Symbol *symbol, - PE_CoffRelocationType reloc_type); - -function PEGEN_Block* -pegen_block_from_coff_reloc_list(PEGEN_Ctx *gen, - PEGEN_SymbolTableBaked *symbol_table, - PEGEN_CoffRelocList *list); - -// export table -function PEGEN_ExportTable* pegen_export_table_new(PEGEN_Ctx *gen); - -function void pegen_export_table_set_binary_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 name); -function void pegen_export_table_set_time_stamp(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U32 timestamp); -function void pegen_export_table_set_version(PEGEN_Ctx *gen, PEGEN_ExportTable *table, U16 major, U16 minor); - -function PEGEN_Export* pegen_export_new(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Label label); -function PEGEN_Export* pegen_export_new_fwd(PEGEN_Ctx *gen, PEGEN_ExportTable *table, String8 fwdname); -function void pegen_export_add_name(PEGEN_Ctx *gen, PEGEN_ExportTable *table, PEGEN_Export *exp, String8 name); - -function PEGEN_Block* pegen_block_from_exports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list_out, PEGEN_ExportTable *table); - -// import table -function PEGEN_ImportList* pegen_import_list_new(PEGEN_Ctx *gen); - -function PEGEN_ImportTable* pegen_import_table_new(PEGEN_Ctx *gen, PEGEN_ImportList *list, - String8 binary_name, U32 time_stamp); - -function void pegen_import_new(PEGEN_Ctx *gen, PEGEN_ImportTable *table, - String8 name, U16 ordinal); - -function PEGEN_ImportBlocks pegen_blocks_from_imports(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, PEGEN_ImportList *imports); - -// base relocations -function PEGEN_BaseRelocationList* pegen_base_relocation_list_new(PEGEN_Ctx *gen); -function void pegen_base_relocation_new(PEGEN_Ctx *gen, PEGEN_BaseRelocationList *list, - PE_BaseRelocationType type, PEGEN_Label label); - -function PEGEN_Block* pegen_block_from_base_relocations(PEGEN_Ctx *gen, PEGEN_Layout *layout, PEGEN_BaseRelocationList *list); - -function S32 pegen_base_relocation_compare(void *a, void *b, void *udata); - -// unwind info -function PEGEN_UnwindInfoList* pegen_unwind_info_list_new(PEGEN_Ctx *gen); -function PEGEN_UnwindInfo* pegen_unwind_info_push(PEGEN_Ctx *gen, PEGEN_UnwindInfoList *list); -function void pegen_unwind_info_code(PEGEN_Ctx *gen, PEGEN_UnwindInfo *handler, - U8 offset, U8 opcode, U8 opinfo, U32 x); - -function PEGEN_UnwindBlocks pegen_blocks_from_unwind_info(PEGEN_Ctx *gen, PEGEN_PatchList *patch_list, PEGEN_UnwindInfoList *list); - -#endif //MR4TH_PE_GEN_H diff --git a/src/binary/pe/mr4th_pe.gen.main.c b/src/binary/pe/mr4th_pe.gen.main.c deleted file mode 100644 index eb61706..0000000 --- a/src/binary/pe/mr4th_pe.gen.main.c +++ /dev/null @@ -1,257 +0,0 @@ -/* -** PE File Generator Development -*/ - -#include "mr4th_base.h" -#include "mr4th_base.stdio.h" -#include "mr4th_keywords.h" - -#include "block/mr4th_block.h" - -#include "mr4th_pe.h" -#include "mr4th_pe.gen.h" - -#include "mr4th_base.c" -#include "mr4th_pe.c" -#include "mr4th_pe.gen.c" - -#include "block/mr4th_block.c" - -//////////////////////////////// -// Entry Point - -int main(int argc, char **argv){ - os_main_init(argc, argv); - - PEGEN_Ctx *gen = pegen_begin(); - - String8 output_filename = str8_lit("generated.obj"); - B32 gen_img = 0; - - // time stamp - DateTime date = os_now_universal_time(); - DateTime local_date = os_local_time_from_universal(&date); - U32 time_stamp = os_time_stamp_32_from_date_time(&local_date); - - /// loose construction helper /// - PEGEN_SectionList *section_list = pegen_section_list_new(gen); - PEGEN_PatchList *patch_list = pegen_patch_list_new(gen); - PEGEN_UnwindInfoList *unwind_info_list = pegen_unwind_info_list_new(gen); - - - /// loose construction helper (image) /// - PEGEN_ImgConfig *img_config = 0; - PEGEN_ExportTable *exports = 0; - PEGEN_ImportList *imports = 0; - PEGEN_BaseRelocationList *base_relocs = 0; - - if (gen_img){ - // init img config - img_config = pegen_img_config_new(gen); - - // init exports - exports = pegen_export_table_new(gen); - pegen_export_table_set_binary_name(gen, exports, output_filename); - pegen_export_table_set_time_stamp(gen, exports, time_stamp); - pegen_export_table_set_version(gen, exports, 0, 0); - - // init imports - imports = pegen_import_list_new(gen); -#if 0 - PEGEN_ImportTable *table = - pegen_import_table_new(gen, imports, str8_lit("api-ms-win-crt-heap-l1-1-0.dll"), time_stamp); - pegen_import_new(gen, table, str8_lit("malloc"), 25); -#endif - - // init base relocations - base_relocs = pegen_base_relocation_list_new(gen); - } - - - /// loose construction helper (object) /// - PEGEN_ObjConfig *obj_config = 0; - PEGEN_SymbolTable *symbol_table = 0; - - if (!gen_img){ - // init obj config - obj_config = pegen_obj_config_new(gen); - - // init symbol table - symbol_table = pegen_symbol_table_new(gen); - } - - // arrange section data - { - // bake imports - PEGEN_ImportBlocks import_blocks = {0}; - if (gen_img){ - import_blocks = pegen_blocks_from_imports(gen, patch_list, imports); - pegen_img_config_data_directory(gen, img_config, - PE_DataDirectoryIdx_ImportTable, - import_blocks.directory_table); - pegen_img_config_data_directory(gen, img_config, - PE_DataDirectoryIdx_IAT, - import_blocks.iat); - } - - // text & data - PEGEN_Block *text_block = pegen_block_new_write(gen, str8(text, sizeof(text))); - PEGEN_Section *text_section = - pegen_section_push(gen, section_list, str8_lit(".text$mn"), - PE_SectionFlag_CNT_CODE | - PE_SectionFlag_MEM_EXECUTE | - PE_SectionFlag_MEM_READ, - PEGEN_DefaultVSize, - text_block); - - PEGEN_CoffRelocList *text_relocs = 0; - if (!gen_img){ - text_relocs = pegen_coff_reloc_list_new(gen); - pegen_section_equip_coff_relocs(text_section, text_relocs); - } - - PEGEN_Block *data_block = pegen_block_new_write(gen, str8(data, sizeof(data))); - pegen_section_push(gen, section_list, str8_lit(".data"), - PE_SectionFlag_CNT_INITIALIZED_DATA | - PE_SectionFlag_MEM_READ | - PE_SectionFlag_MEM_WRITE, - PEGEN_DefaultVSize, - data_block); - - // entry point - if (gen_img){ - PEGEN_Label entry_point = pegen_label(gen, text_block, 0); - pegen_img_config_entry_point(gen, img_config, entry_point); - } - - // symbol table - PEGEN_Symbol *sym_sum_longname = 0; - PEGEN_Symbol *sym_variable = 0; - - if (!gen_img){ - - { - PEGEN_Label pos = pegen_label(gen, text_block, 0); - sym_sum_longname = - pegen_symbol_push(gen, symbol_table, str8_lit("sum_longname"), - PE_CoffSymbolStorageClass_EXTERNAL, - (PE_CoffSymbolTypeHi_FUNCTION << 4), pos); - } - - { - PEGEN_Label pos = pegen_label(gen, data_block, 0); - sym_variable = - pegen_symbol_push(gen, symbol_table, str8_lit("variable"), - PE_CoffSymbolStorageClass_EXTERNAL, 0, pos); - } - - } - - // text coff relocation - if (!gen_img){ - pegen_coff_reloc_push(gen, text_relocs, 9, sym_variable, - PE_CoffRelocationType_REL32); - } - - // bake exports - PEGEN_Block *export_block = 0; - if (gen_img){ - export_block = pegen_block_from_exports(gen, patch_list, exports); - pegen_img_config_data_directory(gen, img_config, - PE_DataDirectoryIdx_ExportTable, - export_block); - } - - // bake unwind info - PEGEN_UnwindBlocks unwind_blocks = {0}; - if (gen_img){ - unwind_blocks = pegen_blocks_from_unwind_info(gen, patch_list, unwind_info_list); - pegen_img_config_data_directory(gen, img_config, - PE_DataDirectoryIdx_ExceptionTable, - unwind_blocks.exception_handlers); - } - - // bake symbol table - PEGEN_SymbolTableBaked *symbol_table_baked = 0; - if (!gen_img){ - symbol_table_baked = - pegen_block_from_symbol_table(gen, patch_list, symbol_table); - pegen_obj_config_symbol_table(gen, obj_config, symbol_table_baked); - } - - // put exports & imports into rdata - if (gen_img){ - PEGEN_Block *rdata_block = pegen_block_new(gen); - pegen_block_push_block(gen, rdata_block, import_blocks.iat); - pegen_block_push_block(gen, rdata_block, export_block); - pegen_block_push_block(gen, rdata_block, unwind_blocks.unwind_info); - pegen_block_push_block(gen, rdata_block, import_blocks.directory_table); - pegen_block_push_block(gen, rdata_block, import_blocks.import_data); - - if (pegen_block_get_size(rdata_block) > 0){ - pegen_section_push(gen, section_list, str8_lit(".rdata"), - PE_SectionFlag_CNT_INITIALIZED_DATA | - PE_SectionFlag_MEM_READ, - PEGEN_DefaultVSize, - rdata_block); - } - } - - // put exception handlers into pdata - if (gen_img){ - if (pegen_block_get_size(unwind_blocks.exception_handlers) > 0){ - pegen_section_push(gen, section_list, str8_lit(".pdata"), - PE_SectionFlag_CNT_INITIALIZED_DATA | - PE_SectionFlag_MEM_READ, - PEGEN_DefaultVSize, - unwind_blocks.exception_handlers); - } - } - } - - // header block - PEGEN_HeaderAndLayout hdr_layout = {0}; - if (gen_img){ - hdr_layout = pegen_img_header_bake(gen, patch_list, section_list, img_config); - } - else{ - hdr_layout = pegen_obj_header_bake(gen, patch_list, section_list, obj_config); - } - - // assemble file - PEGEN_Block *file = pegen_block_new(gen); - { - pegen_block_push_block(gen, file, hdr_layout.header); - - for (U32 i = 0; i < hdr_layout.layout->section_count; i += 1){ - PEGEN_LayoutSection *sec = hdr_layout.layout->sections + i; - pegen_block_fill_to_size(gen, file, 0, sec->foff); - pegen_block_push_block(gen, file, sec->block); - - U32 aligned_up_foff = sec->foff + sec->fsize + sec->fsize_padding; - pegen_block_fill_to_size(gen, file, 0, aligned_up_foff); - - if (sec->reloc_block != 0){ - pegen_block_push_block(gen, file, sec->reloc_block); - } - } - - if (!gen_img){ - if (obj_config->symbol_table != 0){ - pegen_block_push_block(gen, file, obj_config->symbol_table->block); - } - } - } - - // render file - { - Arena *arena = arena_alloc(); - String8 data = pegen_block_flatten(arena, file); - pegen_data_apply_patches(gen, data.str, data.size, file, - hdr_layout.layout, patch_list); - os_file_write(output_filename, data); - } - - return(0); -} - diff --git a/src/binary/pe/mr4th_pe.img_get_section.c b/src/binary/pe/mr4th_pe.img_get_section.c new file mode 100644 index 0000000..a89784d --- /dev/null +++ b/src/binary/pe/mr4th_pe.img_get_section.c @@ -0,0 +1,68 @@ +//////////////////////////////// +// PE Get Section Function + +static RangePtr +pe_img_get_section(void *image_raw, String8 name){ + U8 *image = (U8*)image_raw; + + // dos header + PE_DosHeader *dos_header = (PE_DosHeader*)(image); + if (dos_header->magic != PE_MSDOS_MAGIC){ + dos_header = 0; + } + + // coff header + PE_CoffHeader *coff_header = 0; + U64 after_coff_header_offset = 0; + if (dos_header != 0){ + U64 pe_signature_offset = dos_header->coff_file_offset; + U64 coff_header_offset = pe_signature_offset + sizeof(U32); + U32 pe_signature = *(U32*)(image + pe_signature_offset); + if (pe_signature == PE_SIGNATURE){ + coff_header = (PE_CoffHeader*)(image + coff_header_offset); + after_coff_header_offset = coff_header_offset + sizeof(*coff_header); + } + } + + // section table offset & count + U32 section_table_offset = 0; + U32 section_count = 0; + if (coff_header != 0){ + section_table_offset = ( after_coff_header_offset + + coff_header->optional_header_size); + section_count = coff_header->section_count; + } + + // scan section table + PE_SectionHeader *match = 0; + { + PE_SectionHeader *sec = (PE_SectionHeader*)(image + section_table_offset); + for (U32 i = 0; i < section_count; i += 1, sec += 1){ + U8 *secptr = sec->name; + U8 *secopl = sec->name + sizeof(sec->name); + U8 *keyptr = name.str; + U8 *keyopl = name.str + name.size; + B32 string_match = 1; + for (;*secptr != 0 && secptr < secopl && keyptr < keyopl; + secptr += 1, keyptr += 1){ + if (*secptr != *keyptr){ + string_match = 0; + break; + } + } + if (string_match){ + match = sec; + break; + } + } + } + + // fill result + RangePtr result = {0}; + if (match != 0){ + result.first = image + match->voff; + result.opl = result.first + match->vsize; + } + + return(result); +} diff --git a/src/binary/pe/mr4th_pe.img_get_section.h b/src/binary/pe/mr4th_pe.img_get_section.h new file mode 100644 index 0000000..20da32f --- /dev/null +++ b/src/binary/pe/mr4th_pe.img_get_section.h @@ -0,0 +1,9 @@ +#ifndef MR4TH_PE_IMG_GET_SECTION_H +#define MR4TH_PE_IMG_GET_SECTION_H + +//////////////////////////////// +// PE Get Section Function + +static RangePtr pe_img_get_section(void *image, String8 name); + +#endif //MR4TH_PE_IMG_GET_SECTION_H diff --git a/src/binary/pe/mr4th_pe.parse.c b/src/binary/pe/mr4th_pe.parse.c deleted file mode 100644 index 9bcdc07..0000000 --- a/src/binary/pe/mr4th_pe.parse.c +++ /dev/null @@ -1,66 +0,0 @@ -//////////////////////////////// -// PE Parse Functions - -static PE_SectionHeader* -pe_section_header_from_name(String8 img, String8 name){ - // extract dos header - PE_DosHeader *dos_header = 0; - if (sizeof(*dos_header) <= img.size){ - dos_header = (PE_DosHeader*)(img.str); - if (dos_header->magic != PE_MSDOS_MAGIC){ - dos_header = 0; - } - } - - // extract coff file offset - U32 coff_file_offset = 0; - if (dos_header != 0){ - coff_file_offset = dos_header->coff_file_offset; - } - - // extract pe signature - U32 pe_signature = 0; - U32 coff_header_offset = 0; - if (0 < coff_file_offset && - coff_file_offset + sizeof(pe_signature) <= img.size){ - pe_signature = *(U32*)(img.str + coff_file_offset); - if (pe_signature == PE_SIGNATURE){ - coff_header_offset = coff_file_offset + sizeof(pe_signature); - } - } - - // extract coff header - PE_CoffHeader *coff_header = 0; - if (0 < coff_header_offset && - coff_header_offset + sizeof(*coff_header) <= img.size){ - coff_header = (PE_CoffHeader*)(img.str + coff_header_offset); - } - - // extract section table offset & count - U32 section_table_offset = 0; - U32 section_count = 0; - if (coff_header != 0){ - section_table_offset = ( coff_header_offset - + sizeof(*coff_header) - + coff_header->optional_header_size); - section_count = coff_header->section_count; - } - - // scan section table - PE_SectionHeader *match = 0; - if (0 < section_table_offset && - section_table_offset + sizeof(PE_SectionHeader)*section_count <= img.size){ - PE_SectionHeader *sec = (PE_SectionHeader*)(img.str + section_table_offset); - for (U32 i = 0; i < section_count; i += 1, sec += 1){ - U8 *ptr = sec->name; - for (;*ptr != 0 && ptr < sec->name + sizeof(sec->name); ptr += 1); - String8 secname = str8(sec->name, ptr - sec->name); - if (str8_match(name, secname, 0)){ - match = sec; - break; - } - } - } - - return(match); -} diff --git a/src/binary/pe/mr4th_pe.parse.h b/src/binary/pe/mr4th_pe.parse.h deleted file mode 100644 index 5d084e9..0000000 --- a/src/binary/pe/mr4th_pe.parse.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef MR4TH_PE_PARSE_H -#define MR4TH_PE_PARSE_H - -//////////////////////////////// -// PE Parse Functions - -static PE_SectionHeader* pe_section_header_from_name(String8 img, String8 name); - -#endif //MR4TH_PE_PARSE_H diff --git a/src/binary/pe/mr4th_pe.parse_example.c b/src/binary/pe/mr4th_pe.parse_example.c deleted file mode 100644 index db27fac..0000000 --- a/src/binary/pe/mr4th_pe.parse_example.c +++ /dev/null @@ -1,1369 +0,0 @@ -/* -** PE File Parse Example -*/ - -/* -** TODO(allen): -** [ ] Renaming pass PEDUMP -> something new -** [ ] Improve the quality of the example code -** -*/ - -#include "mr4th_base.h" -#include "mr4th_base.stdio.h" -#include "mr4th_keywords.h" - -#include "mr4th_pe.h" - -#include "mr4th_pe.parse_example.h" - -#include "mr4th_base.c" -#include "mr4th_pe.c" - -//////////////////////////////// -// PE Parse Example Arguments Functions - -function PEDUMP_Arguments* -pedump_args(Arena *arena, String8List *command_line_args){ - // parse - CMDLN *cmdln = cmdln_from_args(arena, command_line_args); - - // setup args - PEDUMP_Arguments *args = push_array(arena, PEDUMP_Arguments, 1); - - // get input file name - args->input_file_name = cmdln_input_from_idx(cmdln, 0); - - return(args); -} - -//////////////////////////////// -// Entry Point - -int main(int argc, char **argv){ - os_main_init(argc, argv); - - Arena *arena = arena_alloc(); - - // arguments - String8List command_line_args = os_command_line_arguments(); - PEDUMP_Arguments *args = pedump_args(arena, &command_line_args); - - // load input file - String8 input_data = os_file_read(arena, args->input_file_name); - - - ///////////////// - ///// PARSE ///// - ///////////////// - - B32 good = 1; - - /// determine offset to PE_CoffHeader - U64 coff_offset = 0; - if (good){ - if (sizeof(PE_DosHeader) <= input_data.size){ - - // parse dos header - PE_DosHeader *dos_header = (PE_DosHeader*)input_data.str; - if (dos_header->magic == PE_MSDOS_MAGIC){ - - // parse pe signature - if (dos_header->coff_file_offset + sizeof(U32) <= input_data.size){ - U32 *pe_signature = (U32*)(input_data.str + dos_header->coff_file_offset); - if (*pe_signature == PE_SIGNATURE){ - coff_offset = dos_header->coff_file_offset + 4; - } - } - - // invalidate - if (coff_offset == 0){ - good = 0; - } - } - } - } - - B32 is_image = (coff_offset != 0); - - /// extract PE_CoffHeader - PE_CoffHeader *coff_header = 0; - U64 after_coff_header_off = 0; - if (good){ - if (coff_offset + sizeof(PE_CoffHeader) <= input_data.size){ - coff_header = (PE_CoffHeader*)(input_data.str + coff_offset); - after_coff_header_off = coff_offset + sizeof(PE_CoffHeader); - } - else{ - good = 0; - } - } - -#if 0 - /// validate PE_CoffHeader - if (good){ - B8 bad_machine_type = 0; - switch (coff_header->machine_type){ -#define X(N,C) case C:break; - PE_MachineType_XList(X) -#undef X - default: bad_machine_type = 1; - } - - B8 bad_optional_header = 0; - if (coff_offset == 0){ - if (coff_header->optional_header_size > 0){ - bad_optional_header = 1; - } - } - else{ - if (coff_header->optional_header_size == 0){ - bad_optional_header = 1; - } - } - } -#endif - - /// parse optional header - PE_OptionalHeader32 *pe32 = 0; - PE_OptionalHeader32Plus *pe32plus = 0; - PE_DataDirectory *data_directories = 0; - U64 data_directory_count = 0; - U64 after_optional_header_off = after_coff_header_off; - - if (good && - coff_header != 0 && - coff_header->optional_header_size > 0){ - - after_optional_header_off = after_coff_header_off + coff_header->optional_header_size; - - // get optional header range - U8 *opt_header = 0; - U64 opt_header_size = 0; - if (after_optional_header_off <= input_data.size){ - opt_header = input_data.str + after_coff_header_off; - opt_header_size = input_data.size; - } - - // check optional header magic - PE_OptionalHeaderMagic optional_header_magic = 0; - if (opt_header != 0){ - if (sizeof(PE_OptionalHeaderMagic) <= opt_header_size){ - MemoryCopy(&optional_header_magic, opt_header, - sizeof(PE_OptionalHeaderMagic)); - } - } - - // extract optional header - switch (optional_header_magic){ - case PE_OptionalHeaderMagic_ROM: - case PE_OptionalHeaderMagic_PE32: - { - if (opt_header_size >= sizeof(PE_OptionalHeader32)){ - pe32 = (PE_OptionalHeader32*)opt_header; - } - }break; - - case PE_OptionalHeaderMagic_PE32Plus: - { - if (opt_header_size >= sizeof(PE_OptionalHeader32Plus)){ - pe32plus = (PE_OptionalHeader32Plus*)opt_header; - } - }break; - } - - // check for failure - if (pe32 == 0 && pe32plus == 0){ - good = 0; - } - - // extract data directories - U64 directories_off = 0; - U64 raw_directory_count = 0; - if (pe32plus != 0){ - directories_off = sizeof(*pe32plus); - raw_directory_count = pe32plus->data_directory_count; - } - else if (pe32 != 0){ - directories_off = sizeof(*pe32); - raw_directory_count = pe32->data_directory_count; - } - if (directories_off != 0){ - data_directories = (PE_DataDirectory*)(opt_header + directories_off); - - U64 max_directory_count = (after_optional_header_off - directories_off)/sizeof(PE_DataDirectory); - data_directory_count = ClampTop(raw_directory_count, max_directory_count); - } - } - - /// parse symbol table - PEDUMP_CoffSymbol *coff_symbols = 0; - U32 coff_symbol_count = 0; - U8 *coff_string_table = 0; - U32 coff_string_table_size = 0; - - if (good && coff_header != 0){ - // check symbol table - U64 table_foff = coff_header->symbol_table_foff; - U64 table_size = coff_header->symbol_count*sizeof(PE_CoffSymbolRecord); - if (table_foff + table_size + 4 <= input_data.size){ - - // check string table - U32 string_table_size = *(U32*)(input_data.str + table_foff + table_size); - if (table_foff + table_size + string_table_size <= input_data.size){ - - // fill string table - U32 string_table_foff = table_foff + table_size; - coff_string_table = input_data.str + string_table_foff; - coff_string_table_size = string_table_size; - - // allocate output - U32 max_count = coff_header->symbol_count; - coff_symbols = push_array(arena, PEDUMP_CoffSymbol, max_count); - - // setup parse loop - PE_CoffSymbolRecord *record = (PE_CoffSymbolRecord*)(input_data.str + table_foff); - PE_CoffSymbolRecord *opl = record + coff_header->symbol_count; - PEDUMP_CoffSymbol *dst_symbol = coff_symbols; - - for (;record < opl;){ - // extract name - String8 name = {0}; - if (record->name.zero == 0){ - // TODO(allen): tighter bound? - name = str8_cstring_capped(coff_string_table + record->name.string_table_off, - coff_string_table + string_table_size); - } - else{ - name = str8_cstring_capped(record->name.raw, record->name.raw + 8); - } - - // fill dst_symbol - dst_symbol->name = name; - dst_symbol->val = record->val; - dst_symbol->sec_number = record->sec_number; - dst_symbol->type = record->type; - dst_symbol->storage_class = record->storage_class; - dst_symbol->aux_symbol_count = record->aux_symbol_count; - dst_symbol += 1; - - // consume this symbol - U32 aux_symbol_count = record->aux_symbol_count; - record += 1 + aux_symbol_count; - } - - coff_symbol_count = (U32)(dst_symbol - coff_symbols); - } - } - } - - /// parse section table - PE_SectionHeader *sec_hdrs = 0; - U64 sec_count = 0; - - if (good && coff_header != 0){ - sec_count = coff_header->section_count; - - U64 sec_hdrs_off = after_optional_header_off; - U64 after_sec_hdrs_off = sec_hdrs_off + sec_count*sizeof(PE_SectionHeader); - - if (after_sec_hdrs_off <= input_data.size){ - sec_hdrs = (PE_SectionHeader*)(input_data.str + sec_hdrs_off); - } - else{ - good = 0; - } - } - - /// parse coff relocations - PE_CoffRelocation **sec_relocs = 0; - U32 *sec_reloc_counts = 0; - - if (good && !is_image && sec_hdrs != 0){ - sec_relocs = push_array(arena, PE_CoffRelocation*, sec_count); - sec_reloc_counts = push_array(arena, U32, sec_count); - - for (U64 i = 0; i < sec_count; i += 1){ - PE_SectionHeader *sec = sec_hdrs + i; - U64 size = sec->relocation_count*sizeof(PE_CoffRelocation); - if (sec->relocations_foff + size <= input_data.size){ - sec_relocs[i] = (PE_CoffRelocation*)(input_data.str + sec->relocations_foff); - sec_reloc_counts[i] = sec->relocation_count; - } - } - } - - /// create 'loaded' version of data - String8 loaded_data = {0}; - if (good && is_image){ - // allocate buffer - U32 image_size = 0; - U32 headers_size = 0; - if (pe32 != 0){ - image_size = pe32->image_size; - headers_size = pe32->headers_size; - } - else if (pe32plus != 0){ - image_size = pe32plus->image_size; - headers_size = pe32plus->headers_size; - } - U8 *buf = push_array(arena, U8, image_size); - - // headers - MemoryCopy(buf, input_data.str, headers_size); - - // load sections - for (U64 i = 0; i < sec_count; i += 1){ - PE_SectionHeader *sec = sec_hdrs + i; - U32 size = Min(sec->voff, sec->foff); - MemoryCopy(buf + sec->voff, input_data.str + sec->foff, size); - } - - // init loaded data - loaded_data = str8(buf, image_size); - } - - /// parse export table - U32 export_range_min = 0; - U32 export_range_max = 0; - PE_ExportDirectoryTable *exports = 0; - String8 export_binary_name = {0}; - U32 *export_voffs = 0; - U32 *export_names = 0; - U16 *export_ordinals = 0; - B32 good_exports = 0; - - if (good){ - // extract directory table - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_ExportTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_ExportTable; - if (dir->size != 0){ - if (dir->voff + dir->size <= loaded_data.size){ - if (sizeof(PE_ExportDirectoryTable) <= dir->size){ - export_range_min = dir->voff; - export_range_max = dir->voff + dir->size; - exports = (PE_ExportDirectoryTable*)(loaded_data.str + dir->voff); - } - } - } - } - - if (exports != 0){ - // name - { - U8 *binary_name_cstring = loaded_data.str + exports->binary_name_voff; - export_binary_name = - str8_cstring_capped(binary_name_cstring, loaded_data.str + loaded_data.size); - } - - // export_voffs - U32 export_count = exports->export_count; - U32 export_voff = exports->export_voff; - U32 after_export_voff = export_voff + export_count*sizeof(U32); - if (after_export_voff <= export_range_max){ - export_voffs = (U32*)(loaded_data.str + export_voff); - } - - // export_names - U32 names_count = exports->ordinal_count; - U32 names_voff = exports->name_voff; - U32 after_names_voff = names_voff + names_count*sizeof(U32); - if (after_names_voff <= export_range_max){ - export_names = (U32*)(loaded_data.str + names_voff); - } - - // export_ordinals - U32 ordinals_count = exports->ordinal_count; - U32 ordinals_voff = exports->ordinal_voff; - U32 after_ordinals_voff = ordinals_voff + ordinals_count*sizeof(U16); - if (after_ordinals_voff <= export_range_max){ - export_ordinals = (U16*)(loaded_data.str + ordinals_voff); - } - } - - if (export_voffs != 0 && - export_names != 0 && - export_ordinals != 0){ - good_exports = 1; - } - } - - /// process exports - PEDUMP_ExportSymbol *export_syms = 0; - U32 export_sym_count = 0; - - if (good_exports){ - export_sym_count = exports->export_count; - export_syms = push_array(arena, PEDUMP_ExportSymbol, export_sym_count); - - for (U32 i = 0; i < export_sym_count; i += 1){ - U32 export_voff = export_voffs[i]; - B32 forwarder = (export_range_min <= export_voff && - export_voff < export_range_max); - if (forwarder){ - export_syms[i].fwd = - str8_cstring_capped(loaded_data.str + export_voff, - loaded_data.str + export_range_max); - } - else{ - export_syms[i].voff = export_voff; - } - } - - for (U32 i = 0; i < exports->ordinal_count; i += 1){ - U32 export_name_voff = export_names[i]; - U16 export_unbiased_ordinal = export_ordinals[i]; - - String8 export_name = - str8_cstring_capped(loaded_data.str + export_name_voff, - loaded_data.str + export_range_max); - - export_syms[export_unbiased_ordinal].name = export_name; - } - } - - /// parse import table - U32 import_range_min = 0; - U32 import_range_max = 0; - PEDUMP_ImportTable *import_table_first = 0; - PEDUMP_ImportTable *import_table_last = 0; - U64 import_table_count = 0; - - if (good){ - // extract directory table - PE_DataDirectory *dir = 0; - PE_ImportDirectoryTable *import_dirs = 0; - if (PE_DataDirectoryIdx_ImportTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_ImportTable; - if (dir->size != 0){ - if (dir->voff + dir->size <= loaded_data.size){ - if (sizeof(PE_ImportDirectoryTable) <= dir->size){ - import_range_min = dir->voff; - import_range_max = dir->voff + dir->size; - import_dirs = (PE_ImportDirectoryTable*)(loaded_data.str + dir->voff); - } - } - } - } - - // count directory table - if (import_dirs != 0){ - U32 import_dir_max_count = dir->size/sizeof(PE_ImportDirectoryTable); - PE_ImportDirectoryTable *import_dir = import_dirs; - for (U32 i = 0; i < import_dir_max_count; i += 1, import_dir += 1){ - if (import_dir->import_lookup_table_voff == 0){ - break; - } - - PEDUMP_ImportTable *import_table = push_array(arena, PEDUMP_ImportTable, 1); - SLLQueuePush(import_table_first, import_table_last, import_table); - import_table_count += 1; - - import_table->time_stamp = import_dir->time_stamp; - import_table->first_forwarder_idx = import_dir->first_forwarder_idx; - - import_table->name = - str8_cstring_capped(loaded_data.str + import_dir->name_voff, - loaded_data.str + loaded_data.size); - - PEDUMP_ImportSymbol *syms = 0; - U32 sym_count = 0; - - U32 lookup_stride = 0; - if (pe32 != 0){ - lookup_stride = 4; - } - else if (pe32plus != 0){ - lookup_stride = 8; - } - if (lookup_stride != 0){ - U8 *lookup_table = loaded_data.str + import_dir->import_lookup_table_voff; - - // determine sym_count - { - U32 max_count = (loaded_data.size - import_dir->import_lookup_table_voff)/lookup_stride; - U8 *ptr = lookup_table; - U32 j = 0; - for (; j < max_count; j += 1, ptr += lookup_stride){ - if (lookup_stride == 4){ - if (*(U32*)ptr == 0){ - break; - } - } - else{ - if (*(U64*)ptr == 0){ - break; - } - } - } - sym_count = j; - } - - // fill syms - { - syms = push_array(arena, PEDUMP_ImportSymbol, sym_count); - U8 *ptr = lookup_table; - for (U32 j = 0; j < sym_count; j += 1, ptr += lookup_stride){ - - // is ordinal - if (((ptr[lookup_stride - 1])&0x80) != 0){ - syms[j].ordinal = *(U16*)(ptr); - } - - // is not ordinal - else{ - U32 hint_voff = (*(U32*)(ptr))&0x7FFFFFFF; - - U16 hint_ordinal = 0; - String8 name = {0}; - if (hint_voff + 2 <= loaded_data.size){ - hint_ordinal = *(U16*)(loaded_data.str + hint_voff); - - name = - str8_cstring_capped(loaded_data.str + hint_voff + 2, - loaded_data.str + loaded_data.size); - } - - syms[j].ordinal = hint_ordinal; - syms[j].name = name; - } - } - } - } - - import_table->syms = syms; - import_table->lookup_count = sym_count; - } - } - } - - /// parse exception handlers - U64 exception_handlers_count = 0; - PE_ExceptionHandler_X86 *exception_handlers_x86 = 0; - PEDUMP_UnwindInfo *exception_handlers_unwind_info = 0; - - if (good && coff_header != 0){ - // extract directory - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_ExceptionTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_ExceptionTable; - } - - // IMAGE version - if (dir != 0 && dir->size > 0){ - if (dir->voff + dir->size <= loaded_data.size){ - switch (coff_header->machine_type){ - // exception handler type: X86 - case PE_MachineType_I386: - case PE_MachineType_IA64: - case PE_MachineType_AMD64: - { - exception_handlers_x86 = (PE_ExceptionHandler_X86*)(loaded_data.str + dir->voff); - exception_handlers_count = dir->size/sizeof(PE_ExceptionHandler_X86); - }break; - } - - // gather unwind info - exception_handlers_unwind_info = push_array(arena, PEDUMP_UnwindInfo, exception_handlers_count); - for (U64 i = 0; i < exception_handlers_count; i += 1){ - U32 unwind_voff = exception_handlers_x86[i].unwind_voff; - if (unwind_voff + sizeof(PE_UnwindInfo) <= loaded_data.size){ - PEDUMP_UnwindInfo *unwind_info = &exception_handlers_unwind_info[i]; - PE_UnwindInfo *pe_unwind_info = (PE_UnwindInfo*)(loaded_data.str + unwind_voff); - - unwind_info->version = PE_UnwindInfo_VersionFromHeader(pe_unwind_info->header); - unwind_info->flags = PE_UnwindInfo_FlagsFromHeader(pe_unwind_info->header); - unwind_info->prolog_size = pe_unwind_info->prolog_size; - unwind_info->code_slot_count = pe_unwind_info->code_count; - unwind_info->frame_reg = PE_UnwindInfo_RegFromFrame(pe_unwind_info->frame); - unwind_info->frame_off = PE_UnwindInfo_OffFromFrame(pe_unwind_info->frame); - - U32 code_slot_count = pe_unwind_info->code_count; - U32 first_code_voff = unwind_voff + sizeof(PE_UnwindInfo); - U32 opl_code_voff = first_code_voff + code_slot_count*sizeof(U16); - U32 clamped_opl_code_voff = ClampTop(opl_code_voff, loaded_data.size); - U32 clamped_code_slot_count = (clamped_opl_code_voff - first_code_voff)/sizeof(U16); - U16 *codes = (U16*)(pe_unwind_info + 1); - U16 *codes_opl = codes + clamped_code_slot_count; - for (U16 *code_ptr = codes; - code_ptr < codes_opl;){ - - // extract fixed size op stuff - U16 code = *code_ptr; - U32 offset = PE_UnwindCode_GetOffset(code); - U32 opcode = PE_UnwindCode_GetOpCode(code); - U32 opinfo = PE_UnwindCode_GetOpInfo(code); - - // determine how many slots to advance - U32 advance = pe_unwind_num_code_slot_from_opcode_opinfo(opcode, opinfo); - - // read extra field from extra slots if possible - U32 x = 0; - if (advance > 1){ - U32 xsize = (advance - 1)*2; - if (code_ptr + 1 + xsize <= codes_opl){ - MemoryCopy(&x, code_ptr + 1, xsize); - } - } - - // form unwind code - { - PEDUMP_UnwindCode *unwind_code = push_array(arena, PEDUMP_UnwindCode, 1); - SLLQueuePush(unwind_info->first_code, unwind_info->last_code, unwind_code); - unwind_info->code_count += 1; - - unwind_code->offset = offset; - unwind_code->opcode = opcode; - unwind_code->opinfo = opinfo; - unwind_code->extra_slot_count = advance - 1; - unwind_code->x = x; - } - - // advance code pointer - code_ptr += advance; - } - } - } - - } - } - - // OBJECT version - if (dir == 0){ - PE_SectionHeader *pdata_sec = 0; - for (U64 i = 0; i < sec_count; i += 1){ - PE_SectionHeader *sec = sec_hdrs + i; - String8 sec_name = str8_cstring_capped(sec->name, sec->name + sizeof(sec->name)); - if (str8_match(sec_name, str8_lit(".pdata"), 0)){ - if (sec->foff + sec->fsize <= input_data.size){ - pdata_sec = sec; - break; - } - } - } - - if (pdata_sec != 0){ - switch (coff_header->machine_type){ - // exception handler type: X86 - case PE_MachineType_I386: - case PE_MachineType_IA64: - case PE_MachineType_AMD64: - { - exception_handlers_x86 = (PE_ExceptionHandler_X86*)(input_data.str + pdata_sec->foff); - exception_handlers_count = pdata_sec->fsize/sizeof(PE_ExceptionHandler_X86); - }break; - } - } - - // TODO(allen): gather unwind info - } - } - - /// parse base relocations - U64 base_relocation_count = 0; - PEDUMP_BaseRelocation *base_relocations = 0; - - if (good && coff_header != 0){ - // extract directory - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_BaseRelocationTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_BaseRelocationTable; - } - - if (dir != 0 && dir->size > 0){ - if (dir->voff + dir->size <= loaded_data.size){ - U8 *ptr = loaded_data.str + dir->voff; - U8 *opl = ptr + dir->size; - - U32 count_estimate = dir->size/2; - base_relocations = push_array(arena, PEDUMP_BaseRelocation, count_estimate); - - PEDUMP_BaseRelocation *relocptr = base_relocations; - - for (;;){ - - // look at block - if (ptr + sizeof(PE_BaseRelocationBlock) > opl){ - break; - } - PE_BaseRelocationBlock *block = (PE_BaseRelocationBlock*)ptr; - - U8 *block_opl = ptr + block->block_size; - if (block_opl > opl){ - block_opl = opl; - } - - ptr = (U8*)(block + 1); - - // scan relocs - U32 reloc_count = (U32)((block_opl - ptr)/2); - for (U32 i = 0; i < reloc_count; i += 1){ - U16 type_offset = *(U16*)ptr; - - U32 off = PE_BaseRelocationTypeOffset_GetOff(type_offset); - - relocptr->type = PE_BaseRelocationTypeOffset_GetType(type_offset); - relocptr->voff = block->page_voff + off; - relocptr += 1; - - ptr += 2; - } - - // put ptr on next block - U32 next_block_off = AlignUpPow2(block->block_size, 4); - ptr = (U8*)(block) + next_block_off; - } - - base_relocation_count = (U32)(relocptr - base_relocations); - - U32 over_estimate_count = count_estimate - base_relocation_count; - arena_pop_amount(arena, sizeof(*base_relocations)*over_estimate_count); - } - } - } - - /// parse debug - U64 debug_directory_count = 0; - PE_DebugDirectory *debug_directories = 0; - - if (good && coff_header != 0){ - // extract directory - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_Debug < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_Debug; - } - - if (dir != 0 && dir->size > 0){ - if (dir->voff + dir->size <= loaded_data.size){ - debug_directory_count = dir->size/sizeof(PE_DebugDirectory); - debug_directories = (PE_DebugDirectory*)(loaded_data.str + dir->voff); - } - } - } - - String8 pdb_path = {0}; - if (debug_directories != 0){ - for (U64 i = 0; i < debug_directory_count; i += 1){ - PE_DebugDirectory *dbgdir = debug_directories + i; - if (dbgdir->type == PE_DebugType_CODEVIEW){ - if (dbgdir->foff + dbgdir->size <= input_data.size){ - - pdb_path = str8_cstring_capped(input_data.str + dbgdir->foff + 24, - input_data.str + dbgdir->foff + dbgdir->size); - } - } - } - } - - /// parse tls table - U64 tlsdir_count = 0; - PE_TLSDirectory32 *tlsdir32 = 0; - PE_TLSDirectory32Plus *tlsdir32plus = 0; - - if (good && coff_header != 0){ - // extract directory - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_TLSTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_TLSTable; - } - - if (dir != 0 && dir->size > 0){ - if (dir->voff + dir->size <= loaded_data.size){ - if (pe32 != 0){ - tlsdir_count = dir->size/sizeof(PE_TLSDirectory32); - tlsdir32 = (PE_TLSDirectory32*)(loaded_data.str + dir->voff); - } - else if (pe32plus != 0){ - tlsdir_count = dir->size/sizeof(PE_TLSDirectory32Plus); - tlsdir32plus = (PE_TLSDirectory32Plus*)(loaded_data.str + dir->voff); - } - } - } - } - - /// parse load config - PE_LoadConfig32 *loadconfig32 = 0; - PE_LoadConfig64 *loadconfig64 = 0; - - if (good && coff_header != 0){ - // extract directory - PE_DataDirectory *dir = 0; - if (PE_DataDirectoryIdx_LoadConfigTable < data_directory_count){ - dir = data_directories + PE_DataDirectoryIdx_LoadConfigTable; - } - - if (dir != 0 && dir->size > 0){ - if (dir->voff + dir->size <= loaded_data.size){ - if (pe32 != 0){ - if (sizeof(PE_LoadConfig32) <= dir->size){ - loadconfig32 = (PE_LoadConfig32*)(loaded_data.str + dir->voff); - } - } - else if (pe32plus != 0){ - if (sizeof(PE_LoadConfig64) <= dir->size){ - loadconfig64 = (PE_LoadConfig64*)(loaded_data.str + dir->voff); - } - } - } - } - } - - /// parse .drectve - String8List directives = {0}; - - if (good && coff_header != 0){ - for (U64 i = 0; i < sec_count; i += 1){ - PE_SectionHeader *sec = sec_hdrs + i; - if ((sec->flags & PE_SectionFlag_LNK_INFO) != 0){ - String8 sec_name = str8_cstring_capped(sec->name, sec->name + sizeof(sec->name)); - if (str8_match(sec_name, str8_lit(".drectve"), 0)){ - if (sec->foff + sec->fsize <= input_data.size){ - U8 *sec_data = input_data.str + sec->foff; - U8 *sec_opl = sec_data + sec->fsize; - - U8 *directive_ptr = sec_data; - if (sec->fsize >= 3){ - if (sec_data[0] == 0xEF && - sec_data[1] == 0xBB && - sec_data[2] == 0xBF){ - directive_ptr += 3; - } - } - - str8_list_push(arena, &directives, str8_range(directive_ptr, sec_opl)); - } - } - } - } - } - - - //////////////// - ///// DUMP ///// - //////////////// - - if (!good){ - m4_printf("Unsuccessful parse\n"); - } - - if (good){ - ArenaTemp scratch = arena_get_scratch(0, 0); - - // file type - { - if (is_image){ - m4_printf("Type: PE Binary File\n"); - } - else{ - m4_printf("Type: PE Object File\n"); - } - m4_printf("\n"); - } - - // coff header - { - String8 machine_type_str = pe_str8_from_machine_type(coff_header->machine_type); - - String8 flags_str = pe_str8_from_flags(scratch.arena, coff_header->flags); - - m4_printf("coff_header.machine_type = %S\n", machine_type_str); - m4_printf("coff_header.section_count = %u\n", coff_header->section_count); - m4_printf("coff_header.time_stamp = %u\n", coff_header->time_stamp); - m4_printf("coff_header.symbol_table_foff = 0x%x\n", coff_header->symbol_table_foff); - m4_printf("coff_header.symbol_count = %u\n", coff_header->symbol_count); - m4_printf("coff_header.optional_header_size = %u\n", coff_header->optional_header_size); - m4_printf("coff_header.flags = %S\n", flags_str); - m4_printf("\n"); - - } - - // optional header PE32 - if (pe32 != 0){ - String8 subsystem_str = pe_str8_from_windows_subsystem(pe32->subsystem); - String8 dll_flags_str = pe_str8_from_dll_flags(arena, pe32->dll_flags); - - m4_printf("pe32.linker_version_major = %u\n", pe32->linker_version_major); - m4_printf("pe32.linker_version_minor = %u\n", pe32->linker_version_minor); - m4_printf("pe32.total_size_text = %$u\n", pe32->total_size_text); - m4_printf("pe32.total_size_inited_data = %$u\n", pe32->total_size_inited_data); - m4_printf("pe32.total_size_zeroed_data = %$u\n", pe32->total_size_zeroed_data); - m4_printf("pe32.entry_point_voff = 0x%x\n", pe32->entry_point_voff); - m4_printf("pe32.text_voff = 0x%x\n", pe32->text_voff); - m4_printf("pe32.data_voff = 0x%x\n", pe32->data_voff); - m4_printf("pe32.image_base_vaddr = 0x%x\n", pe32->image_base_vaddr); - m4_printf("pe32.section_alignment = %u\n", pe32->section_alignment); - m4_printf("pe32.file_alignment = %u\n", pe32->file_alignment); - m4_printf("pe32.os_version_major = %u\n", pe32->os_version_major); - m4_printf("pe32.os_version_minor = %u\n", pe32->os_version_minor); - m4_printf("pe32.image_version_major = %u\n", pe32->image_version_major); - m4_printf("pe32.image_version_minor = %u\n", pe32->image_version_minor); - m4_printf("pe32.subsystem_version_major = %u\n", pe32->subsystem_version_major); - m4_printf("pe32.subsystem_version_minor = %u\n", pe32->subsystem_version_minor); - m4_printf("pe32.image_size = %$u\n", pe32->image_size); - m4_printf("pe32.headers_size = %u\n", pe32->headers_size); - m4_printf("pe32.checksum = %u\n", pe32->checksum); - m4_printf("pe32.subsystem = %S\n", subsystem_str); - m4_printf("pe32.dll_flags = %S\n", dll_flags_str); - m4_printf("pe32.stack_size_reserve = %$u\n", pe32->stack_size_reserve); - m4_printf("pe32.stack_size_commit = %$u\n", pe32->stack_size_commit); - m4_printf("pe32.heap_size_reserve = %$u\n", pe32->heap_size_reserve); - m4_printf("pe32.heap_size_commit = %$u\n", pe32->heap_size_commit); - m4_printf("pe32.data_directory_count = %u\n", pe32->data_directory_count); - m4_printf("\n"); - - } - - // optional header PE32+ - if (pe32plus != 0){ - String8 subsystem_str = pe_str8_from_windows_subsystem(pe32plus->subsystem); - String8 dll_flags_str = pe_str8_from_dll_flags(arena, pe32plus->dll_flags); - - m4_printf("pe32plus.linker_version_major = %u\n", pe32plus->linker_version_major); - m4_printf("pe32plus.linker_version_minor = %u\n", pe32plus->linker_version_minor); - m4_printf("pe32plus.total_size_text = %$u\n", pe32plus->total_size_text); - m4_printf("pe32plus.total_size_inited_data = %$u\n", pe32plus->total_size_inited_data); - m4_printf("pe32plus.total_size_zeroed_data = %$u\n", pe32plus->total_size_zeroed_data); - m4_printf("pe32plus.entry_point_voff = 0x%x\n", pe32plus->entry_point_voff); - m4_printf("pe32plus.text_voff = 0x%x\n", pe32plus->text_voff); - m4_printf("pe32plus.image_base_vaddr = 0x%llx\n", pe32plus->image_base_vaddr); - m4_printf("pe32plus.section_alignment = %u\n", pe32plus->section_alignment); - m4_printf("pe32plus.file_alignment = %u\n", pe32plus->file_alignment); - m4_printf("pe32plus.os_version_major = %u\n", pe32plus->os_version_major); - m4_printf("pe32plus.os_version_minor = %u\n", pe32plus->os_version_minor); - m4_printf("pe32plus.image_version_major = %u\n", pe32plus->image_version_major); - m4_printf("pe32plus.image_version_minor = %u\n", pe32plus->image_version_minor); - m4_printf("pe32plus.subsystem_version_major = %u\n", pe32plus->subsystem_version_major); - m4_printf("pe32plus.subsystem_version_minor = %u\n", pe32plus->subsystem_version_minor); - m4_printf("pe32plus.image_size = %$u\n", pe32plus->image_size); - m4_printf("pe32plus.headers_size = %u\n", pe32plus->headers_size); - m4_printf("pe32plus.checksum = %u\n", pe32plus->checksum); - m4_printf("pe32plus.subsystem = %S\n", subsystem_str); - m4_printf("pe32plus.dll_flags = %S\n", dll_flags_str); - m4_printf("pe32plus.stack_size_reserve = %$llu\n", pe32plus->stack_size_reserve); - m4_printf("pe32plus.stack_size_commit = %$llu\n", pe32plus->stack_size_commit); - m4_printf("pe32plus.heap_size_reserve = %$llu\n", pe32plus->heap_size_reserve); - m4_printf("pe32plus.heap_size_commit = %$llu\n", pe32plus->heap_size_commit); - m4_printf("pe32plus.data_directory_count = %u\n", pe32plus->data_directory_count); - m4_printf("\n"); - - } - - // data directories - if (data_directory_count > 0){ - for (U64 i = 0; i < data_directory_count; i += 1){ - PE_DataDirectory *directory = data_directories + i; - - String8 directory_name = {0}; - if (i < PE_DataDirectoryIdx_COUNT){ - directory_name = pe_str8_from_data_directory_idx(i); - } - else{ - directory_name = str8_pushf(scratch.arena, "%llu", i); - } - - m4_printf("data_directory[%S] = { voff = 0x%x, size = %u }\n", - directory_name, directory->voff, directory->size); - } - m4_printf("\n"); - } - - // symbol table - if (coff_symbols != 0){ - PEDUMP_CoffSymbol *coff_symbol = coff_symbols; - for (U32 i = 0; i < coff_symbol_count; i += 1, coff_symbol += 1){ - String8 type_str = pe_str8_from_coff_symbol_type(scratch.arena, coff_symbol->type); - String8 storage_class_str = pe_str8_from_coff_symbol_storage_class(coff_symbol->storage_class); - - m4_printf("coff_symbol[%u] = {\n", i); - m4_printf(" name = %S,\n", coff_symbol->name); - m4_printf(" val = %u\n", coff_symbol->val); - m4_printf(" sec_number = %d\n", coff_symbol->sec_number); - m4_printf(" type = %S\n", type_str); - m4_printf(" storage_class = %S\n", storage_class_str); - m4_printf(" aux_symbol_count = %u\n", coff_symbol->aux_symbol_count); - m4_printf("}\n"); - } - - m4_printf("\n"); - } - - // section headers - { - for (U64 i = 0; i < sec_count; i += 1){ - PE_SectionHeader *sec = sec_hdrs + i; - - String8 flags_str = pe_str8_from_sec_flags(scratch.arena, sec->flags); - - m4_printf("section[%u] = {\n" - " name = \"%.*s\",\n" - " vsize = %$u,\n" - " voff = 0x%x,\n" - " fsize = %$u,\n" - " foff = 0x%x,\n" - " relocations_foff = 0x%x,\n" - " line_numbers_foff = 0x%x,\n" - " relocation_count = %u,\n" - " line_number_count = %u,\n" - " flags = %S\n" - "}\n", - 1 + i, ArrayCount(sec->name), sec->name, - sec->vsize, sec->voff, sec->fsize, sec->foff, - sec->relocations_foff, sec->line_numbers_foff, - sec->relocation_count, sec->line_number_count, - flags_str); - } - m4_printf("\n"); - } - - // coff section relocations - if (sec_relocs != 0){ - for (U64 i = 0; i < sec_count; i += 1){ - m4_printf("section[%u].relocations = {\n", i + 1); - - U32 reloc_count = sec_reloc_counts[i]; - PE_CoffRelocation *reloc = sec_relocs[i]; - for (U32 j = 0; j < reloc_count; j += 1, reloc += 1){ - String8 type_str = pe_str8_from_coff_relocation_type(reloc->type); - m4_printf(" { off = 0x%08x, symbol_idx = %u, type = %S }\n", - reloc->off, reloc->symbol_idx, type_str); - } - - m4_printf("}\n"); - } - m4_printf("\n"); - } - - // exports - { - if (export_binary_name.size > 0){ - m4_printf("export_binary_name = \"%S\"\n", export_binary_name); - } - if (good_exports){ - m4_printf("exports = {\n"); - for (U32 i = 0; i < export_sym_count; i += 1){ - PEDUMP_ExportSymbol *export_sym = export_syms + i; - - if (export_sym->fwd.size != 0){ - if (export_sym->name.size != 0){ - m4_printf(" { ord = %3u, name = \"%S\", fwd = \"%S\" }\n", - exports->ordinal_base + i, - export_sym->name, export_sym->fwd); - } - else{ - m4_printf(" { ord = %3u, fwd = \"%S\" }\n", - exports->ordinal_base + i, - export_sym->fwd); - } - } - else{ - if (export_sym->name.size != 0){ - m4_printf(" { ord = %3u, name = \"%S\", voff = 0x%x }\n", - exports->ordinal_base + i, - export_sym->name, export_sym->voff); - } - else{ - m4_printf(" { ord = %3u, voff = 0x%x }\n", - exports->ordinal_base + i, - export_sym->voff); - } - } - } - - m4_printf("}\n\n"); - } - } - - // imports - if (import_table_first != 0){ - m4_printf("imports = {\n"); - - for (PEDUMP_ImportTable *table = import_table_first; - table != 0; - table = table->next){ - m4_printf(" { name = \"%S\", time_stamp = %u, first_forwarder_idx = %u,\n", - table->name, table->time_stamp, table->first_forwarder_idx); - - m4_printf(" lookup_table = {\n"); - - for (U64 j = 0; j < table->lookup_count; j += 1){ - PEDUMP_ImportSymbol *sym = table->syms + j; - - if (sym->name.size == 0){ - m4_printf(" ordinal %u,\n", sym->ordinal); - } - else{ - m4_printf(" \"%S\" hint %u,\n", sym->name, sym->ordinal); - } - } - - m4_printf(" }\n"); - - m4_printf(" }\n"); - } - - m4_printf("}\n\n"); - } - - // exception handlers (x86) - if (exception_handlers_x86 != 0){ - m4_printf("exception_handlers = {\n"); - - for (U64 i = 0; i < exception_handlers_count; i += 1){ - PE_ExceptionHandler_X86 *handler = exception_handlers_x86 + i; - - m4_printf(" { begin_voff = 0x%x, end_voff = 0x%x, unwind_voff = 0x%x,", - handler->begin_voff, handler->end_voff, handler->unwind_voff); - - PEDUMP_UnwindInfo *unwind_info = &exception_handlers_unwind_info[i]; - if (unwind_info != 0){ - m4_printf("\n"); - - m4_printf(" unwind_info = {\n"); - m4_printf(" version = %d,\n", unwind_info->version); - // TODO(allen): pneumonics - m4_printf(" flags = 0x%x,\n", unwind_info->flags); - m4_printf(" prolog_size = %d,\n", unwind_info->prolog_size); - m4_printf(" code_count = %d,\n", unwind_info->code_count); - // TODO(allen): pneumonics - m4_printf(" frame_reg = %d,\n", unwind_info->frame_reg); - m4_printf(" frame_off = %d,\n", unwind_info->frame_off); - m4_printf(" codes = {\n"); - for (PEDUMP_UnwindCode *code = unwind_info->first_code; - code != 0; - code = code->next){ - // TODO(allen): pneumonics - m4_printf(" { offset = %d, opcode = %d, opinfo = %d, x = %d }\n", - code->offset, code->opcode, code->opinfo, code->x); - } - - m4_printf(" }\n"); - m4_printf(" }\n"); - } - - m4_printf(" }\n"); - } - - m4_printf("}\n\n"); - } - - // base relocations - if (base_relocations != 0){ - m4_printf("base_relocations = {\n"); - - for (U64 i = 0; i < base_relocation_count; i += 1){ - PEDUMP_BaseRelocation *reloc = base_relocations + i; - String8 type_str = pe_str8_from_base_relocation_type(reloc->type); - m4_printf(" {type = %S, voff = 0x%llx},\n", - type_str, reloc->voff); - } - - m4_printf("}\n\n"); - } - - // debug directories - if (debug_directories != 0){ - m4_printf("debug_directories = {\n"); - - for (U64 i = 0; i < debug_directory_count; i += 1){ - PE_DebugDirectory *dbgdir = debug_directories + i; - - String8 type_str = pe_str8_from_debug_type(dbgdir->type); - - m4_printf(" {\n"); - m4_printf(" time_stamp = %u,\n", dbgdir->time_stamp); - m4_printf(" version_major = %u,\n", dbgdir->version_major); - m4_printf(" version_minor = %u,\n", dbgdir->version_minor); - m4_printf(" type = %S,\n", type_str); - m4_printf(" size = %$u,\n", dbgdir->size); - m4_printf(" voff = 0x%x,\n", dbgdir->voff); - m4_printf(" foff = 0x%x,\n", dbgdir->foff); - m4_printf(" },\n"); - } - - m4_printf("}\n\n"); - } - - // pdb path - if (pdb_path.size > 0){ - m4_printf("pdb_path = \"%S\"\n\n", pdb_path); - } - - // tls table - if (tlsdir32 != 0){ - m4_printf("tls_table = {\n"); - - for (U64 i = 0; i < tlsdir_count; i += 1){ - PE_TLSDirectory32 *tlsdir = tlsdir32 + i; - U32 align = PE_TLSDirectoryFlags_GetAlign(tlsdir->flags); - String8 align_str = pe_str8_from_sec_alignment(align); - - m4_printf(" {\n"); - m4_printf(" raw_data_start_vaddr = 0x%x,\n", tlsdir->raw_data_start_vaddr); - m4_printf(" raw_data_end_vaddr = 0x%x,\n", tlsdir->raw_data_end_vaddr); - m4_printf(" tls_index_vaddr = 0x%x,\n", tlsdir->tls_index_vaddr); - m4_printf(" tls_callback_array_vaddr = 0x%x,\n", tlsdir->tls_callback_array_vaddr); - m4_printf(" zero_fill_size = %u,\n", tlsdir->zero_fill_size); - m4_printf(" flags = %S,\n", align_str); - } - - m4_printf("}\n\n"); - } - else if (tlsdir32plus != 0){ - m4_printf("tls_table = {\n"); - - for (U64 i = 0; i < tlsdir_count; i += 1){ - PE_TLSDirectory32Plus *tlsdir = tlsdir32plus + i; - U32 align = PE_TLSDirectoryFlags_GetAlign(tlsdir->flags); - String8 align_str = pe_str8_from_sec_alignment(align); - - m4_printf(" {\n"); - m4_printf(" raw_data_start_vaddr = 0x%llx,\n", tlsdir->raw_data_start_vaddr); - m4_printf(" raw_data_end_vaddr = 0x%llx,\n", tlsdir->raw_data_end_vaddr); - m4_printf(" tls_index_vaddr = 0x%llx,\n", tlsdir->tls_index_vaddr); - m4_printf(" tls_callback_array_vaddr = 0x%llx,\n", tlsdir->tls_callback_array_vaddr); - m4_printf(" zero_fill_size = %u,\n", tlsdir->zero_fill_size); - m4_printf(" flags = %S,\n", align_str); - m4_printf(" },\n"); - } - - m4_printf("}\n\n"); - } - - // load config - if (loadconfig32 != 0){ - - m4_printf("loadconfig = {\n"); - m4_printf(" reserved0 = %u,\n", loadconfig32->reserved0); - m4_printf(" time_stamp = %u,\n", loadconfig32->time_stamp); - m4_printf(" version_major = %u,\n", loadconfig32->version_major); - m4_printf(" version_minor = %u,\n", loadconfig32->version_minor); - m4_printf(" global_flags_clear = 0x%x,\n", loadconfig32->global_flags_clear); - m4_printf(" global_flags_set = 0x%x,\n", loadconfig32->global_flags_set); - m4_printf(" default_critical_section_timeout = %u,\n", - loadconfig32->default_critical_section_timeout); - m4_printf(" decommit_free_block_threshold = %u,\n", - loadconfig32->decommit_free_block_threshold); - m4_printf(" decommit_total_free_threshold = %u,\n", - loadconfig32->decommit_total_free_threshold); - m4_printf(" lock_prefix_table_vaddr = 0x%x,\n", - loadconfig32->lock_prefix_table_vaddr); - m4_printf(" maximum_allocation_size = %u,\n", - loadconfig32->maximum_allocation_size); - m4_printf(" virtual_memory_threshold = %u,\n", - loadconfig32->virtual_memory_threshold); - m4_printf(" process_affinity_mask = 0x%x,\n", - loadconfig32->process_affinity_mask); - m4_printf(" process_heap_flags = 0x%x,\n", loadconfig32->process_heap_flags); - m4_printf(" csd_version = %u,\n", loadconfig32->csd_version); - m4_printf(" reserved1 = %u,\n", loadconfig32->reserved1); - m4_printf(" reserved2 = %u,\n", loadconfig32->reserved2); - m4_printf(" security_cookie_vaddr = 0x%x,\n", loadconfig32->security_cookie_vaddr); - m4_printf(" seh_table_vaddr = 0x%x,\n", loadconfig32->seh_table_vaddr); - m4_printf(" seh_count = %u,\n", loadconfig32->seh_count); - m4_printf(" control_flow_guard_check_function_vaddr = 0x%x,\n", - loadconfig32->control_flow_guard_check_function_vaddr); - m4_printf(" control_flow_guard_dispatch_function_vaddr = 0x%x,\n", - loadconfig32->control_flow_guard_dispatch_function_vaddr); - m4_printf(" control_flow_guard_function_table_vaddr = 0x%x,\n", - loadconfig32->control_flow_guard_function_table_vaddr); - m4_printf(" control_flow_guard_function_count = %u,\n", - loadconfig32->control_flow_guard_function_count); - m4_printf(" control_flow_guard_flags = 0x%x,\n", - loadconfig32->control_flow_guard_flags); - - m4_printf(" code_integriy = {"); - for (U32 j = 0; j < ArrayCount(loadconfig32->code_integrity); j += 1){ - m4_printf(" 0x%02x,", loadconfig32->code_integrity[j]); - } - m4_printf(" },\n"); - - m4_printf(" guard_address_taken_iat_table_vaddr = 0x%x,\n", - loadconfig32->guard_address_taken_iat_table_vaddr); - m4_printf(" guard_address_taken_iat_count = %u,\n", - loadconfig32->guard_address_taken_iat_count); - m4_printf(" guard_long_jump_target_table_vaddr = 0x%x,\n", - loadconfig32->guard_long_jump_target_table_vaddr); - m4_printf(" guard_long_jump_target_count = %u,\n", - loadconfig32->guard_long_jump_target_count); - - m4_printf("}\n\n"); - - } - - else if (loadconfig64 != 0){ - - m4_printf("loadconfig = {\n"); - m4_printf(" reserved0 = %u,\n", loadconfig64->reserved0); - m4_printf(" time_stamp = %u,\n", loadconfig64->time_stamp); - m4_printf(" version_major = %u,\n", loadconfig64->version_major); - m4_printf(" version_minor = %u,\n", loadconfig64->version_minor); - m4_printf(" global_flags_clear = 0x%x,\n", loadconfig64->global_flags_clear); - m4_printf(" global_flags_set = 0x%x,\n", loadconfig64->global_flags_set); - m4_printf(" default_critical_section_timeout = %u,\n", - loadconfig64->default_critical_section_timeout); - m4_printf(" decommit_free_block_threshold = %llu,\n", - loadconfig64->decommit_free_block_threshold); - m4_printf(" decommit_total_free_threshold = %llu,\n", - loadconfig64->decommit_total_free_threshold); - m4_printf(" lock_prefix_table_vaddr = 0x%llx,\n", - loadconfig64->lock_prefix_table_vaddr); - m4_printf(" maximum_allocation_size = %llu,\n", - loadconfig64->maximum_allocation_size); - m4_printf(" virtual_memory_threshold = %llu,\n", - loadconfig64->virtual_memory_threshold); - m4_printf(" process_affinity_mask = 0x%llx,\n", - loadconfig64->process_affinity_mask); - m4_printf(" process_heap_flags = 0x%x,\n", loadconfig64->process_heap_flags); - m4_printf(" csd_version = %u,\n", loadconfig64->csd_version); - m4_printf(" reserved1 = %u,\n", loadconfig64->reserved1); - m4_printf(" reserved2 = %llu,\n", loadconfig64->reserved2); - m4_printf(" security_cookie_vaddr = 0x%llx,\n", loadconfig64->security_cookie_vaddr); - m4_printf(" seh_table_vaddr = 0x%llx,\n", loadconfig64->seh_table_vaddr); - m4_printf(" seh_count = %llu,\n", loadconfig64->seh_count); - m4_printf(" control_flow_guard_check_function_vaddr = 0x%llx,\n", - loadconfig64->control_flow_guard_check_function_vaddr); - m4_printf(" control_flow_guard_dispatch_function_vaddr = 0x%llx,\n", - loadconfig64->control_flow_guard_dispatch_function_vaddr); - m4_printf(" control_flow_guard_function_table_vaddr = 0x%llx,\n", - loadconfig64->control_flow_guard_function_table_vaddr); - m4_printf(" control_flow_guard_function_count = %llu,\n", - loadconfig64->control_flow_guard_function_count); - m4_printf(" control_flow_guard_flags = 0x%x,\n", - loadconfig64->control_flow_guard_flags); - - m4_printf(" code_integriy = {"); - for (U64 j = 0; j < ArrayCount(loadconfig64->code_integrity); j += 1){ - m4_printf(" 0x%02x,", loadconfig64->code_integrity[j]); - } - m4_printf(" },\n"); - - m4_printf(" guard_address_taken_iat_table_vaddr = 0x%llx,\n", - loadconfig64->guard_address_taken_iat_table_vaddr); - m4_printf(" guard_address_taken_iat_count = %llu,\n", - loadconfig64->guard_address_taken_iat_count); - m4_printf(" guard_long_jump_target_table_vaddr = 0x%llx,\n", - loadconfig64->guard_long_jump_target_table_vaddr); - m4_printf(" guard_long_jump_target_count = %llu,\n", - loadconfig64->guard_long_jump_target_count); - - m4_printf("}\n\n"); - - } - - // dump linker directives - { - m4_printf("linker_directives = {\n"); - for (String8Node *node = directives.first; - node != 0; - node = node->next){ - m4_printf("%S\n", node->string); - } - m4_printf("}\n\n"); - } - - arena_release_scratch(&scratch); - } - - return(0); -} diff --git a/src/binary/pe/mr4th_pe.parse_example.h b/src/binary/pe/mr4th_pe.parse_example.h deleted file mode 100644 index 0c363b3..0000000 --- a/src/binary/pe/mr4th_pe.parse_example.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef MR4TH_PE_PARSE_EXAMPLE_H -#define MR4TH_PE_PARSE_EXAMPLE_H - -//////////////////////////////// -// PE Parse Example Arguments Types - -typedef struct PEDUMP_Arguments{ - String8 input_file_name; -} PEDUMP_Arguments; - -//////////////////////////////// -// PE Parse Example Helper Types - -typedef struct PEDUMP_CoffSymbol{ - String8 name; - U32 val; - S16 sec_number; - PE_CoffSymbolType type; - PE_CoffSymbolStorageClass storage_class; - U8 aux_symbol_count; -} PEDUMP_CoffSymbol; - -typedef struct PEDUMP_ExportSymbol{ - U32 voff; - String8 fwd; - String8 name; -} PEDUMP_ExportSymbol; - -typedef struct PEDUMP_ImportSymbol{ - U16 ordinal; - String8 name; -} PEDUMP_ImportSymbol; - -typedef struct PEDUMP_ImportTable{ - struct PEDUMP_ImportTable *next; - - U32 time_stamp; - U32 first_forwarder_idx; - - String8 name; - - PEDUMP_ImportSymbol *syms; - U64 lookup_count; -} PEDUMP_ImportTable; - -typedef struct PEDUMP_BaseRelocation{ - U32 type; - U32 voff; -} PEDUMP_BaseRelocation; - -typedef struct PEDUMP_UnwindCode{ - struct PEDUMP_UnwindCode *next; - U8 offset; - U8 opcode; - U8 opinfo; - U8 extra_slot_count; - U32 x; -} PEDUMP_UnwindCode; - -typedef struct PEDUMP_UnwindInfo{ - U8 version; - U8 flags; - U8 prolog_size; - U8 code_slot_count; - U8 code_count; - U8 frame_reg; - U8 frame_off; - PEDUMP_UnwindCode *first_code; - PEDUMP_UnwindCode *last_code; -} PEDUMP_UnwindInfo; - -//////////////////////////////// -// PE Parse Example Arguments Functions - -function PEDUMP_Arguments* pedump_args(Arena *arena, String8List *args); - -//////////////////////////////// -// Entry Point - -int main(int argc, char **argv); - -#endif //MR4TH_PE_PARSE_EXAMPLE_H diff --git a/src/binary/pe/mr4th_pe.table.c b/src/binary/pe/mr4th_pe.table.c deleted file mode 100644 index 4c60d28..0000000 --- a/src/binary/pe/mr4th_pe.table.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -** PE Tabulator -*/ - -#include "mr4th_base.h" -#include "mr4th_base.stdio.h" -#include "mr4th_keywords.h" - -#include "mr4th_pe.h" -#include "mr4th_stream.h" -#include "mr4th_ascii.h" - -#include "mr4th_pe.table.h" - -#include "mr4th_base.c" -#include "mr4th_pe.c" -#include "mr4th_stream.c" -#include "mr4th_ascii.c" - -//////////////////////////////// -// PE Tabulator Argument Functions - -function PETAB_Args* -petab_args(Arena *arena, String8List *command_line_args){ - // parse - CMDLN *cmdln = cmdln_from_args(arena, command_line_args); - - // setup args - PETAB_Args *args = push_array(arena, PETAB_Args, 1); - - // get input file name - args->input_file_name = cmdln_input_from_idx(cmdln, 0); - - return(args); -} - -//////////////////////////////// -// Entry Point - -int main(int argc, char **argv){ - os_main_init(argc, argv); - Arena *arena = arena_alloc(); - - // arguments - String8List command_line_args = os_command_line_arguments(); - PETAB_Args *args = petab_args(arena, &command_line_args); - - // load input file - String8 data = os_file_read(arena, args->input_file_name); - - - ///////////////// - ///// PARSE ///// - ///////////////// - - // extract dos header - PE_DosHeader *dos_header = 0; - if (sizeof(*dos_header) <= data.size){ - dos_header = (PE_DosHeader*)(data.str); - if (dos_header->magic != PE_MSDOS_MAGIC){ - dos_header = 0; - } - } - - // extract coff file offset - U32 coff_file_offset = 0; - if (dos_header != 0){ - coff_file_offset = dos_header->coff_file_offset; - } - - // extract pe signature - U32 pe_signature = 0; - U32 coff_header_offset = 0; - if (0 < coff_file_offset && - coff_file_offset + sizeof(pe_signature) <= data.size){ - pe_signature = *(U32*)(data.str + coff_file_offset); - if (pe_signature == PE_SIGNATURE){ - coff_header_offset = coff_file_offset + sizeof(pe_signature); - } - } - - // extract coff header - PE_CoffHeader *coff_header = 0; - U64 coff_header_opl = 0; - if (When(dos_header != 0, 0 < coff_header_offset) && - coff_header_offset + sizeof(*coff_header) <= data.size){ - coff_header = (PE_CoffHeader*)(data.str + coff_header_offset); - coff_header_opl = coff_header_offset + sizeof(*coff_header); - } - - // optional header - U64 optional_header_opl = coff_header_opl; - if (coff_header != 0 && - coff_header->optional_header_size > 0){ - optional_header_opl = coff_header_opl + coff_header->optional_header_size; - } - - // determine if this is an image file - B32 is_image = (coff_header_offset != 0); - - // parse section table - PE_SectionHeader *section_table = 0; - U64 section_count = 0; - if (coff_header != 0){ - U64 section_table_offset = optional_header_opl; - U64 section_table_opl = section_table_offset + coff_header->section_count*sizeof(PE_SectionHeader); - if (section_table_opl <= data.size){ - section_table = (PE_SectionHeader*)(data.str + section_table_offset); - section_count = coff_header->section_count; - } - } - - - ///////////////// - ///// PRINT ///// - ///////////////// - - STREAM *stream = stream_new(); - STREAM *tempstr = stream_new(); - - { - TABLE *table = table_begin(arena); - - { - table_default_align(table, TABLE_CellFlag_CenterAlign); - - // TODO(allen): conditionals on columns - table_row(arena, table); - table_cellf(arena, table, "#"); - table_cellf(arena, table, "Name"); - table_cellf(arena, table, "V.Size"); - table_cellf(arena, table, "V.Off"); - table_cellf(arena, table, "F.Size"); - table_cellf(arena, table, "F.Off"); - table_cellf(arena, table, "Mem"); - table_cellf(arena, table, "#Relocs"); - table_cellf(arena, table, "#Lines"); - table_hz_separator(arena, table); - - table_default_align(table, TABLE_CellFlag_LeftAlign); - } - - { - PE_SectionHeader *sec = section_table; - for (U64 i = 0; i < section_count; i += 1, sec += 1){ - table_row(arena, table); - - table_cellf(arena, table, "%u", i + 1); - table_cell_align(table, TABLE_CellFlag_RightAlign); - - table_cellf(arena, table, "%.*s", ArrayCount(sec->name), sec->name); - - table_default_align(table, TABLE_CellFlag_RightAlign); - table_cellf(arena, table, "%$u", sec->vsize); - table_cellf(arena, table, "0x%x", sec->voff); - table_cellf(arena, table, "%$u", sec->fsize); - table_cellf(arena, table, "0x%x", sec->foff); - table_default_align(table, TABLE_CellFlag_LeftAlign); - - // memory flags - // TODO(allen): here we want to be able to write this cell - // by writing into a stream - { - stream_clear(tempstr); - stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_READ )?"r":"-"); - stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_WRITE )?"w":"-"); - stream_printf(tempstr, (sec->flags & PE_SectionFlag_MEM_EXECUTE)?"x":"-"); - table_cell(arena, table, stream_read(arena, tempstr)); - } - - table_default_align(table, TABLE_CellFlag_RightAlign); - table_cellf(arena, table, "%u", sec->relocation_count); - table_cellf(arena, table, "%u", sec->line_number_count); - table_default_align(table, TABLE_CellFlag_LeftAlign); - } - } - - stream_printf(stream, "SECTIONS: (Total %u)\n", section_count); - table_print(stream, table, &table_wire_style); - stream_printf(stream, "\n"); - } - - stream_fprint(stdout, stream); - - return(0); -} diff --git a/src/binary/pe/mr4th_pe.table.h b/src/binary/pe/mr4th_pe.table.h deleted file mode 100644 index 6329ccf..0000000 --- a/src/binary/pe/mr4th_pe.table.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef MR4TH_PE_TABLE_H -#define MR4TH_PE_TABLE_H - -//////////////////////////////// -// PE Tabulator Argument Types - -typedef struct PETAB_Args{ - String8 input_file_name; -} PETAB_Args; - -//////////////////////////////// -// PE Tabulator Argument Functions - -function PETAB_Args* petab_args(Arena *arena, String8List *args); - -//////////////////////////////// -// Entry Point - -int main(int argc, char **argv); - -#endif //MR4TH_PE_TABLE_H diff --git a/src/symbol_set.define.h b/src/symbol_set.define.h index 90bd0fd..a399112 100644 --- a/src/symbol_set.define.h +++ b/src/symbol_set.define.h @@ -5,8 +5,8 @@ static SYMBOL__TYPE(SYMBOL_SET_DEFINE) SYMBOL__SYM(SYMBOL_SET_DEFINE,0); # pragma SYMBOL__CL_PRAGMA #endif BEFORE_MAIN(){ - RangePtr image = os_this_image(); - RangePtr range = selfimg_get_section(image, str8_lit(GLUE(SYMBOL_SET_DEFINE,_section))); + void *image = os_this_image(); + RangePtr range = self_img_get_section(image, str8_lit(GLUE(SYMBOL_SET_DEFINE,_section))); SymbolCount(SYMBOL_SET_DEFINE) = (range.opl - range.first)/sizeof(SYMBOL__TYPE(SYMBOL_SET_DEFINE)); SymbolBasePtr(SYMBOL_SET_DEFINE) = (SYMBOL__TYPE(SYMBOL_SET_DEFINE)*)(range.first); } diff --git a/todo.txt b/todo.txt index 156dbd8..753118d 100644 --- a/todo.txt +++ b/todo.txt @@ -30,7 +30,9 @@ OSs: Win32, Linux, Mac Development: +[ ] experiment with __ImageBase pseudo variable (linker variable) [ ] Small as possible binary parser for "selfimg" purposes + [x] PE