mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-07-25 08:57:51 +00:00
begin process of moving pe unwinding info into pe layer; more demon2 work checkpoint
This commit is contained in:
@@ -691,15 +691,6 @@ ctrl_halt(void)
|
||||
demon_halt(0, 0);
|
||||
}
|
||||
|
||||
//- rjf: entity introspection
|
||||
|
||||
internal U32
|
||||
ctrl_id_from_machine_entity(CTRL_MachineID id, DEMON_Handle handle)
|
||||
{
|
||||
U32 result = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: exe -> dbg path mapping
|
||||
|
||||
internal String8
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
//- rjf: entity id -> hash
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
internal U64
|
||||
dmn_w32_hash_from_string(String8 string)
|
||||
@@ -23,6 +21,9 @@ dmn_w32_hash_from_id(U64 id)
|
||||
return dmn_w32_hash_from_string(str8_struct(&id));
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Helpers
|
||||
|
||||
//- rjf: entity <-> handle
|
||||
|
||||
internal DMN_Handle
|
||||
@@ -198,7 +199,107 @@ dmn_w32_entity_from_kind_id(DMN_W32_EntityKind kind, U64 id)
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: win32-level process reads/writes
|
||||
////////////////////////////////
|
||||
//~ rjf: Module Info Extraction
|
||||
|
||||
internal String8
|
||||
dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
//- rjf: extract path from module
|
||||
String16 path16 = {0};
|
||||
String8 path8 = {0};
|
||||
{
|
||||
// rjf: handle -> full path
|
||||
if(module->handle != 0)
|
||||
{
|
||||
DWORD cap16 = GetFinalPathNameByHandleW(module->handle, 0, 0, VOLUME_NAME_DOS);
|
||||
U16 *buffer16 = push_array_no_zero(scratch.arena, U16, cap16);
|
||||
DWORD size16 = GetFinalPathNameByHandleW(module->handle, (WCHAR*)buffer16, cap16, VOLUME_NAME_DOS);
|
||||
path16 = str16(buffer16, size16);
|
||||
}
|
||||
|
||||
// rjf: fallback (main module only): process -> full path
|
||||
if(path16.size == 0 && module->module.is_main)
|
||||
{
|
||||
DMN_W32_Entity *process = module->parent;
|
||||
DWORD size = KB(4);
|
||||
U16 *buf = push_array_no_zero(scratch.arena, U16, size);
|
||||
if(QueryFullProcessImageNameW(process->handle, 0, (WCHAR*)buf, &size))
|
||||
{
|
||||
path16 = str16(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fallback (any module - no guarantee): address_of_name -> full path
|
||||
if(path16.size == 0 && module->module.address_of_name_pointer != 0)
|
||||
{
|
||||
DMN_W32_Entity *process = module->parent;
|
||||
U64 ptr_size = bit_size_from_arch(process->arch)/8;
|
||||
U64 name_pointer = 0;
|
||||
if(dmn_w32_process_read(process->handle, r1u64(module->module.address_of_name_pointer, module->module.address_of_name_pointer+ptr_size), &name_pointer))
|
||||
{
|
||||
if(name_pointer != 0)
|
||||
{
|
||||
if(module->module.name_is_unicode)
|
||||
{
|
||||
path16 = dmn_w32_read_memory_str16(scratch.arena, process->handle, name_pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
path8 = dmn_w32_read_memory_str(scratch.arena, process->handle, name_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: produce finalized result
|
||||
String8 result = {0};
|
||||
{
|
||||
if(path16.size > 0)
|
||||
{
|
||||
// rjf: skip the extended path thing if necessary
|
||||
if(path16.size >= 4 &&
|
||||
path16.str[0] == L'\\' &&
|
||||
path16.str[1] == L'\\' &&
|
||||
path16.str[2] == L'?' &&
|
||||
path16.str[3] == L'\\')
|
||||
{
|
||||
path16.size -= 4;
|
||||
path16.str += 4;
|
||||
}
|
||||
|
||||
// rjf: convert to UTF-8
|
||||
result = str8_from_16(arena, path16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rjf: skip the extended path thing if necessary
|
||||
if (path8.size >= 4 &&
|
||||
path8.str[0] == L'\\' &&
|
||||
path8.str[1] == L'\\' &&
|
||||
path8.str[2] == L'?' &&
|
||||
path8.str[3] == L'\\')
|
||||
{
|
||||
path8.size -= 4;
|
||||
path8.str += 4;
|
||||
}
|
||||
|
||||
// rjf: copy to output arena
|
||||
result = push_str8_copy(arena, path8);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Win32-Level Process/Thread Reads/Writes
|
||||
|
||||
//- rjf: processes
|
||||
|
||||
internal U64
|
||||
dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst)
|
||||
@@ -346,7 +447,78 @@ dmn_w32_read_memory_str16(Arena *arena, HANDLE process_handle, U64 address)
|
||||
return(result);
|
||||
}
|
||||
|
||||
//- rjf: win32-level thread register reads/writes
|
||||
internal DMN_W32_ImageInfo
|
||||
dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
|
||||
{
|
||||
// rjf: find PE offset
|
||||
U32 pe_offset = 0;
|
||||
{
|
||||
U64 dos_magic_off = base_vaddr;
|
||||
U16 dos_magic = 0;
|
||||
dmn_w32_process_read_struct(process, dos_magic_off, &dos_magic);
|
||||
if(dos_magic == PE_DOS_MAGIC)
|
||||
{
|
||||
U64 pe_offset_off = base_vaddr + OffsetOf(PE_DosHeader, coff_file_offset);
|
||||
dmn_w32_process_read_struct(process, pe_offset_off, &pe_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get COFF header
|
||||
B32 got_coff_header = 0;
|
||||
U64 coff_header_off = 0;
|
||||
COFF_Header coff_header = {0};
|
||||
if(pe_offset > 0)
|
||||
{
|
||||
U64 pe_magic_off = base_vaddr + pe_offset;
|
||||
U32 pe_magic = 0;
|
||||
dmn_w32_process_read_struct(process, pe_magic_off, &pe_magic);
|
||||
if(pe_magic == PE_MAGIC)
|
||||
{
|
||||
coff_header_off = pe_magic_off + sizeof(pe_magic);
|
||||
if(dmn_w32_process_read_struct(process, coff_header_off, &coff_header))
|
||||
{
|
||||
got_coff_header = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get arch and size
|
||||
DMN_W32_ImageInfo result = zero_struct;
|
||||
if(got_coff_header)
|
||||
{
|
||||
U64 optional_size_off = 0;
|
||||
Architecture arch = Architecture_Null;
|
||||
switch(coff_header.machine)
|
||||
{
|
||||
case COFF_MachineType_X86:
|
||||
{
|
||||
arch = Architecture_x86;
|
||||
optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image);
|
||||
}break;
|
||||
case COFF_MachineType_X64:
|
||||
{
|
||||
arch = Architecture_x64;
|
||||
optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image);
|
||||
}break;
|
||||
default:
|
||||
{}break;
|
||||
}
|
||||
if(arch != Architecture_Null)
|
||||
{
|
||||
U64 optional_off = coff_header_off + sizeof(coff_header);
|
||||
U32 size = 0;
|
||||
if(dmn_w32_process_read_struct(process, optional_off+optional_size_off, &size) >= sizeof(size))
|
||||
{
|
||||
result.arch = arch;
|
||||
result.size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: threads
|
||||
|
||||
internal U16
|
||||
dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave)
|
||||
@@ -872,7 +1044,7 @@ dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: win32-level thread injection
|
||||
//- rjf: remote thread injection
|
||||
|
||||
internal DWORD
|
||||
dmn_w32_inject_thread(HANDLE process, U64 start_address)
|
||||
@@ -887,175 +1059,6 @@ dmn_w32_inject_thread(HANDLE process, U64 start_address)
|
||||
return thread_id;
|
||||
}
|
||||
|
||||
//- rjf: module image analysis
|
||||
|
||||
internal DMN_W32_ImageInfo
|
||||
dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr)
|
||||
{
|
||||
// rjf: find PE offset
|
||||
U32 pe_offset = 0;
|
||||
{
|
||||
U64 dos_magic_off = base_vaddr;
|
||||
U16 dos_magic = 0;
|
||||
dmn_w32_process_read_struct(process, dos_magic_off, &dos_magic);
|
||||
if(dos_magic == PE_DOS_MAGIC)
|
||||
{
|
||||
U64 pe_offset_off = base_vaddr + OffsetOf(PE_DosHeader, coff_file_offset);
|
||||
dmn_w32_process_read_struct(process, pe_offset_off, &pe_offset);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get COFF header
|
||||
B32 got_coff_header = 0;
|
||||
U64 coff_header_off = 0;
|
||||
COFF_Header coff_header = {0};
|
||||
if(pe_offset > 0)
|
||||
{
|
||||
U64 pe_magic_off = base_vaddr + pe_offset;
|
||||
U32 pe_magic = 0;
|
||||
dmn_w32_process_read_struct(process, pe_magic_off, &pe_magic);
|
||||
if(pe_magic == PE_MAGIC)
|
||||
{
|
||||
coff_header_off = pe_magic_off + sizeof(pe_magic);
|
||||
if(dmn_w32_process_read_struct(process, coff_header_off, &coff_header))
|
||||
{
|
||||
got_coff_header = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: get arch and size
|
||||
DMN_W32_ImageInfo result = zero_struct;
|
||||
if(got_coff_header)
|
||||
{
|
||||
U64 optional_size_off = 0;
|
||||
Architecture arch = Architecture_Null;
|
||||
switch(coff_header.machine)
|
||||
{
|
||||
case COFF_MachineType_X86:
|
||||
{
|
||||
arch = Architecture_x86;
|
||||
optional_size_off = OffsetOf(PE_OptionalHeader32, sizeof_image);
|
||||
}break;
|
||||
case COFF_MachineType_X64:
|
||||
{
|
||||
arch = Architecture_x64;
|
||||
optional_size_off = OffsetOf(PE_OptionalHeader32Plus, sizeof_image);
|
||||
}break;
|
||||
default:
|
||||
{}break;
|
||||
}
|
||||
if(arch != Architecture_Null)
|
||||
{
|
||||
U64 optional_off = coff_header_off + sizeof(coff_header);
|
||||
U32 size = 0;
|
||||
if(dmn_w32_process_read_struct(process, optional_off+optional_size_off, &size) >= sizeof(size))
|
||||
{
|
||||
result.arch = arch;
|
||||
result.size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//- rjf: module full path extraction
|
||||
|
||||
internal String8
|
||||
dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
//- rjf: extract path from module
|
||||
String16 path16 = {0};
|
||||
String8 path8 = {0};
|
||||
{
|
||||
// rjf: handle -> full path
|
||||
if(module->handle != 0)
|
||||
{
|
||||
DWORD cap16 = GetFinalPathNameByHandleW(module->handle, 0, 0, VOLUME_NAME_DOS);
|
||||
U16 *buffer16 = push_array_no_zero(scratch.arena, U16, cap16);
|
||||
DWORD size16 = GetFinalPathNameByHandleW(module->handle, (WCHAR*)buffer16, cap16, VOLUME_NAME_DOS);
|
||||
path16 = str16(buffer16, size16);
|
||||
}
|
||||
|
||||
// rjf: fallback (main module only): process -> full path
|
||||
if(path16.size == 0 && module->module.is_main)
|
||||
{
|
||||
DMN_W32_Entity *process = module->parent;
|
||||
DWORD size = KB(4);
|
||||
U16 *buf = push_array_no_zero(scratch.arena, U16, size);
|
||||
if(QueryFullProcessImageNameW(process->handle, 0, (WCHAR*)buf, &size))
|
||||
{
|
||||
path16 = str16(buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fallback (any module - no guarantee): address_of_name -> full path
|
||||
if(path16.size == 0 && module->module.address_of_name_pointer != 0)
|
||||
{
|
||||
DMN_W32_Entity *process = module->parent;
|
||||
U64 ptr_size = bit_size_from_arch(process->arch)/8;
|
||||
U64 name_pointer = 0;
|
||||
if(dmn_w32_process_read(process->handle, r1u64(module->module.address_of_name_pointer, module->module.address_of_name_pointer+ptr_size), &name_pointer))
|
||||
{
|
||||
if(name_pointer != 0)
|
||||
{
|
||||
if(module->module.name_is_unicode)
|
||||
{
|
||||
path16 = dmn_w32_read_memory_str16(scratch.arena, process->handle, name_pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
path8 = dmn_w32_read_memory_str(scratch.arena, process->handle, name_pointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: produce finalized result
|
||||
String8 result = {0};
|
||||
{
|
||||
if(path16.size > 0)
|
||||
{
|
||||
// rjf: skip the extended path thing if necessary
|
||||
if(path16.size >= 4 &&
|
||||
path16.str[0] == L'\\' &&
|
||||
path16.str[1] == L'\\' &&
|
||||
path16.str[2] == L'?' &&
|
||||
path16.str[3] == L'\\')
|
||||
{
|
||||
path16.size -= 4;
|
||||
path16.str += 4;
|
||||
}
|
||||
|
||||
// rjf: convert to UTF-8
|
||||
result = str8_from_16(arena, path16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// rjf: skip the extended path thing if necessary
|
||||
if (path8.size >= 4 &&
|
||||
path8.str[0] == L'\\' &&
|
||||
path8.str[1] == L'\\' &&
|
||||
path8.str[2] == L'?' &&
|
||||
path8.str[3] == L'\\')
|
||||
{
|
||||
path8.size -= 4;
|
||||
path8.str += 4;
|
||||
}
|
||||
|
||||
// rjf: copy to output arena
|
||||
result = push_str8_copy(arena, path8);
|
||||
}
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: @dmn_os_hooks Main Layer Initialization (Implemented Per-OS)
|
||||
|
||||
|
||||
@@ -229,12 +229,14 @@ global DMN_W32_Entity dmn_w32_entity_nil = {&dmn_w32_entity_nil, &dmn_w32_entity
|
||||
global DMN_W32_GetThreadDescriptionFunctionType *dmn_w32_GetThreadDescription = 0;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
//~ rjf: Basic Helpers
|
||||
|
||||
//- rjf: hashes
|
||||
internal U64 dmn_w32_hash_from_string(String8 string);
|
||||
internal U64 dmn_w32_hash_from_id(U64 id);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entity Helpers
|
||||
|
||||
//- rjf: entity <-> handle
|
||||
internal DMN_Handle dmn_w32_handle_from_entity(DMN_W32_Entity *entity);
|
||||
internal DMN_W32_Entity *dmn_w32_entity_from_handle(DMN_Handle handle);
|
||||
@@ -246,27 +248,30 @@ internal void dmn_w32_entity_release(DMN_W32_Entity *entity);
|
||||
//- rjf: kind*id -> entity
|
||||
internal DMN_W32_Entity *dmn_w32_entity_from_kind_id(DMN_W32_EntityKind kind, U64 id);
|
||||
|
||||
//- rjf: win32-level process reads/writes
|
||||
////////////////////////////////
|
||||
//~ rjf: Module Info Extraction
|
||||
|
||||
internal String8 dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Win32-Level Process/Thread Reads/Writes
|
||||
|
||||
//- rjf: processes
|
||||
internal U64 dmn_w32_process_read(HANDLE process, Rng1U64 range, void *dst);
|
||||
internal B32 dmn_w32_process_write(HANDLE process, Rng1U64 range, void *src);
|
||||
internal String8 dmn_w32_read_memory_str(Arena *arena, HANDLE process_handle, U64 address);
|
||||
internal String16 dmn_w32_read_memory_str16(Arena *arena, HANDLE process_handle, U64 address);
|
||||
#define dmn_w32_process_read_struct(process, vaddr, ptr) dmn_w32_process_read((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
|
||||
#define dmn_w32_process_write_struct(process, vaddr, ptr) dmn_w32_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
|
||||
internal DMN_W32_ImageInfo dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr);
|
||||
|
||||
//- rjf: win32-level thread register reads/writes
|
||||
//- rjf: threads
|
||||
internal U16 dmn_w32_real_tag_word_from_xsave(XSAVE_FORMAT *fxsave);
|
||||
internal U16 dmn_w32_xsave_tag_word_from_real_tag_word(U16 ftw);
|
||||
internal B32 dmn_w32_thread_read_reg_block(Architecture arch, HANDLE thread, void *reg_block);
|
||||
internal B32 dmn_w32_thread_write_reg_block(Architecture arch, HANDLE thread, void *reg_block);
|
||||
|
||||
//- rjf: win32-level thread injection
|
||||
//- rjf: remote thread injection
|
||||
internal DWORD dmn_w32_inject_thread(HANDLE process, U64 start_address);
|
||||
|
||||
//- rjf: module image analysis
|
||||
internal DMN_W32_ImageInfo dmn_w32_image_info_from_process_base_vaddr(HANDLE process, U64 base_vaddr);
|
||||
|
||||
//- rjf: module full path extraction
|
||||
internal String8 dmn_w32_full_path_from_module(Arena *arena, DMN_W32_Entity *module);
|
||||
|
||||
#endif // DEMON2_CORE_WIN32_H
|
||||
|
||||
+52
-44
@@ -1,6 +1,54 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Basic Enum Functions
|
||||
|
||||
internal U32
|
||||
pe_slot_count_from_unwind_op_code(PE_UnwindOpCode opcode)
|
||||
{
|
||||
U32 result = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case PE_UnwindOpCode_PUSH_NONVOL: result = 1; break;
|
||||
case PE_UnwindOpCode_ALLOC_LARGE: result = 2; break;
|
||||
case PE_UnwindOpCode_ALLOC_SMALL: result = 1; break;
|
||||
case PE_UnwindOpCode_SET_FPREG: result = 1; break;
|
||||
case PE_UnwindOpCode_SAVE_NONVOL: result = 2; break;
|
||||
case PE_UnwindOpCode_SAVE_NONVOL_FAR: result = 3; break;
|
||||
case PE_UnwindOpCode_EPILOG: result = 2; break;
|
||||
case PE_UnwindOpCode_SPARE_CODE: result = 3; break;
|
||||
case PE_UnwindOpCode_SAVE_XMM128: result = 2; break;
|
||||
case PE_UnwindOpCode_SAVE_XMM128_FAR: result = 3; break;
|
||||
case PE_UnwindOpCode_PUSH_MACHFRAME: result = 1; break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
pe_string_from_windows_subsystem(PE_WindowsSubsystem subsystem)
|
||||
{
|
||||
String8 result = {0};
|
||||
switch(subsystem)
|
||||
{
|
||||
default:{}break;
|
||||
case PE_WindowsSubsystem_UNKNOWN: result = str8_lit("UNKNOWN"); break;
|
||||
case PE_WindowsSubsystem_NATIVE: result = str8_lit("NATIVE"); break;
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: result = str8_lit("WINDOWS_GUI"); break;
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: result = str8_lit("WINDOWS_CUI"); break;
|
||||
case PE_WindowsSubsystem_OS2_CUI: result = str8_lit("OS2_CUI"); break;
|
||||
case PE_WindowsSubsystem_POSIX_CUI: result = str8_lit("POSIX_CUI"); break;
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS: result = str8_lit("NATIVE_WINDOWS"); break;
|
||||
case PE_WindowsSubsystem_WINDOWS_CE_GUI: result = str8_lit("WINDOWS_CE_GUID"); break;
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION: result = str8_lit("EFI_APPLICATION"); break;
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: result = str8_lit("EFI_BOOT_SERVICE_DRIVER"); break;
|
||||
case PE_WindowsSubsystem_EFI_ROM: result = str8_lit("EFI_ROM"); break;
|
||||
case PE_WindowsSubsystem_XBOX: result = str8_lit("XBOX"); break;
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: result = str8_lit("WINDOWS_BOOT_APPLICATION"); break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parser Functions
|
||||
|
||||
@@ -535,7 +583,7 @@ pe_resource_dir_push_dir_node(Arena *arena, PE_ResourceDir *dir, COFF_ResourceID
|
||||
|
||||
PE_Resource *res = &res_node->data;
|
||||
res->id = id;
|
||||
res->type = PE_ResData_DIR;
|
||||
res->kind = PE_ResDataKind_DIR;
|
||||
res->u.dir = sub_dir;
|
||||
|
||||
return res_node;
|
||||
@@ -558,7 +606,7 @@ pe_resource_dir_push_entry_node(Arena *arena, PE_ResourceDir *dir, COFF_Resource
|
||||
|
||||
PE_Resource *res = &res_node->data;
|
||||
res->id = id;
|
||||
res->type = PE_ResData_COFF_RESOURCE;
|
||||
res->kind = PE_ResDataKind_COFF_RESOURCE;
|
||||
res->u.coff_res.type = type;
|
||||
res->u.coff_res.data_version = data_version;
|
||||
res->u.coff_res.version = version;
|
||||
@@ -716,7 +764,7 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data)
|
||||
|
||||
entry->id.type = COFF_ResourceIDType_STRING;
|
||||
entry->id.u.string = str8_from_16(arena, name16);
|
||||
entry->type = is_dir ? PE_ResData_DIR : PE_ResData_COFF_LEAF;
|
||||
entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF;
|
||||
|
||||
if (is_dir) {
|
||||
struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1);
|
||||
@@ -745,7 +793,7 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data)
|
||||
|
||||
entry->id.type = COFF_ResourceIDType_NUMBER;
|
||||
entry->id.u.number = coff_entry.name.id;
|
||||
entry->type = is_dir ? PE_ResData_DIR : PE_ResData_COFF_LEAF;
|
||||
entry->kind = is_dir ? PE_ResDataKind_DIR : PE_ResDataKind_COFF_LEAF;
|
||||
|
||||
if (is_dir) {
|
||||
struct stack_s *frame = push_array(scratch.arena, struct stack_s, 1);
|
||||
@@ -766,43 +814,3 @@ pe_resource_table_from_directory_data(Arena *arena, String8 data)
|
||||
scratch_end(scratch);
|
||||
return bottom_frame->table;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
pe_get_dos_program(void)
|
||||
{
|
||||
// generated from pe/dos_program.asm
|
||||
static U8 program[] = {
|
||||
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, 0x24, 0x00, 0x00
|
||||
};
|
||||
return str8(program, sizeof(program));
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8
|
||||
pe_string_from_subsystem(PE_WindowsSubsystem subsystem)
|
||||
{
|
||||
switch (subsystem) {
|
||||
case PE_WindowsSubsystem_UNKNOWN: return str8_lit("UNKNOWN");
|
||||
case PE_WindowsSubsystem_NATIVE: return str8_lit("NATIVE");
|
||||
case PE_WindowsSubsystem_WINDOWS_GUI: return str8_lit("WINDOWS_GUI");
|
||||
case PE_WindowsSubsystem_WINDOWS_CUI: return str8_lit("WINDOWS_CUI");
|
||||
case PE_WindowsSubsystem_OS2_CUI: return str8_lit("OS2_CUI");
|
||||
case PE_WindowsSubsystem_POSIX_CUI: return str8_lit("POSIX_CUI");
|
||||
case PE_WindowsSubsystem_NATIVE_WINDOWS: return str8_lit("NATIVE_WINDOWS");
|
||||
case PE_WindowsSubsystem_WINDOWS_CE_GUI: return str8_lit("WINDOWS_CE_GUID");
|
||||
case PE_WindowsSubsystem_EFI_APPLICATION: return str8_lit("EFI_APPLICATION");
|
||||
case PE_WindowsSubsystem_EFI_BOOT_SERVICE_DRIVER: return str8_lit("EFI_BOOT_SERVICE_DRIVER");
|
||||
case PE_WindowsSubsystem_EFI_ROM: return str8_lit("EFI_ROM");
|
||||
case PE_WindowsSubsystem_XBOX: return str8_lit("XBOX");
|
||||
case PE_WindowsSubsystem_WINDOWS_BOOT_APPLICATION: return str8_lit("WINDOWS_BOOT_APPLICATION");
|
||||
default: break;
|
||||
}
|
||||
return str8(0,0);
|
||||
}
|
||||
|
||||
|
||||
+268
-167
@@ -1,13 +1,11 @@
|
||||
// Copyright (c) 2024 Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
/* date = September 6th 2023 8:54 am */
|
||||
|
||||
#ifndef PE_H
|
||||
#define PE_H
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: PE Format Types
|
||||
//~ rjf: PE Format-Defined Types/Constants
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
@@ -287,7 +285,7 @@ enum
|
||||
PE_GlobalFlags_HEAP_ENABLE_TAG_BY_DLL = (1 << 15),
|
||||
PE_GlobalFlags_DISABLE_STACK_EXTENSION = (1 << 16),
|
||||
PE_GlobalFlags_ENABLE_CSRDEBUG = (1 << 17),
|
||||
PE_GlobalFlags_ENABLE_KDEBUG_SYMBOL_LOAD = (1 << 18),
|
||||
PE_GlobalFlags_ENABLE_KDEBUG_SYMBOL_LOAD = (1 << 18),
|
||||
PE_GlobalFlags_DISABLE_PAGE_KERNEL_STACKS = (1 << 19),
|
||||
PE_GlobalFlags_ENABLE_SYSTEM_CRIT_BREAKS = (1 << 20),
|
||||
PE_GlobalFlags_HEAP_DISABLE_COALESCING = (1 << 21),
|
||||
@@ -445,11 +443,273 @@ struct PE_TLSHeader64
|
||||
U32 characteristics; // COFF_SectionFlags but only align flags are used.
|
||||
};
|
||||
|
||||
#define PE_RES_ALIGN 4u
|
||||
|
||||
global read_only U8 PE_RES_MAGIC[] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x20, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
typedef U32 PE_ResourceKind;
|
||||
enum
|
||||
{
|
||||
PE_ResourceKind_CURSOR = 0x1,
|
||||
PE_ResourceKind_BITMAP = 0x2,
|
||||
PE_ResourceKind_ICON = 0x3,
|
||||
PE_ResourceKind_MENU = 0x4,
|
||||
PE_ResourceKind_DIALOG = 0x5,
|
||||
PE_ResourceKind_STRING = 0x6,
|
||||
PE_ResourceKind_FONTDIR = 0x7,
|
||||
PE_ResourceKind_FONT = 0x8,
|
||||
PE_ResourceKind_ACCELERATOR = 0x9,
|
||||
PE_ResourceKind_RCDATA = 0xA,
|
||||
PE_ResourceKind_MESSAGETABLE = 0xB,
|
||||
PE_ResourceKind_GROUP_CURSOR = 0xC,
|
||||
PE_ResourceKind_GROUP_ICON = 0xE,
|
||||
PE_ResourceKind_VERSION = 0x10,
|
||||
PE_ResourceKind_DLGINCLUDE = 0x11,
|
||||
PE_ResourceKind_PLUGPLAY = 0x13,
|
||||
PE_ResourceKind_VXD = 0x14,
|
||||
PE_ResourceKind_ANICURSOR = 0x15,
|
||||
PE_ResourceKind_ANIICON = 0x16,
|
||||
PE_ResourceKind_HTML = 0x17,
|
||||
PE_ResourceKind_MANIFEST = 0x18,
|
||||
PE_ResourceKind_BITMAP_NEW = 0x2002,
|
||||
PE_ResourceKind_MENU_NEW = 0x2004,
|
||||
PE_ResourceKind_DIALOG_NEW = 0x2005,
|
||||
};
|
||||
|
||||
typedef enum PE_ResDataKind
|
||||
{
|
||||
PE_ResDataKind_NULL,
|
||||
PE_ResDataKind_DIR,
|
||||
PE_ResDataKind_COFF_LEAF,
|
||||
PE_ResDataKind_COFF_RESOURCE,
|
||||
}
|
||||
PE_ResDataKind;
|
||||
|
||||
typedef struct PE_ResourceHeader PE_ResourceHeader;
|
||||
struct PE_ResourceHeader
|
||||
{
|
||||
COFF_ResourceHeaderPrefix prefix;
|
||||
U16 type;
|
||||
U16 pad0;
|
||||
U16 name;
|
||||
U16 pad1;
|
||||
U32 data_version;
|
||||
COFF_ResourceMemoryFlags memory_flags;
|
||||
U16 language_id;
|
||||
U32 version;
|
||||
U32 characteristics;
|
||||
};
|
||||
|
||||
typedef U16 PE_BaseRelocKind;
|
||||
enum
|
||||
{
|
||||
PE_BaseRelocKind_ABSOLUTE = 0, // No reallocation is applied. Can be used as padding.
|
||||
PE_BaseRelocKind_HIGH = 1,
|
||||
PE_BaseRelocKind_LOW = 2,
|
||||
PE_BaseRelocKind_HIGHLOW = 3,
|
||||
PE_BaseRelocKind_HIGHADJ = 4,
|
||||
PE_BaseRelocKind_MIPS_JMPADDR = 5,
|
||||
PE_BaseRelocKind_ARM_MOV32 = 5,
|
||||
PE_BaseRelocKind_RISCV_HIGH20 = 5,
|
||||
// 6 is reserved
|
||||
PE_BaseRelocKind_THUMB_MOV32 = 7,
|
||||
PE_BaseRelocKind_RISCV_LOW12I = 7,
|
||||
PE_BaseRelocKind_RISCV_LOW12S = 8,
|
||||
PE_BaseRelocKind_LOONGARCH32_MARK_LA = 8,
|
||||
PE_BaseRelocKind_LOONGARCH64_MARK_LA = 8,
|
||||
PE_BaseRelocKind_MIPS_JMPADDR16 = 9,
|
||||
PE_BaseRelocKind_DIR64 = 10,
|
||||
};
|
||||
#define PE_BaseRelocOffsetFromEntry(x) ((x) & 0x1fff)
|
||||
#define PE_BaseRelocKindFromEntry(x) (((x) >> 12) & 0xf)
|
||||
#define PE_BaseRelocMake(k, off) ((((U16)(k) & 0xf) << 12) | (U16)((off) & 0x1fff))
|
||||
|
||||
typedef U32 PE_UnwindOpCode;
|
||||
enum
|
||||
{
|
||||
PE_UnwindOpCode_PUSH_NONVOL = 0,
|
||||
PE_UnwindOpCode_ALLOC_LARGE = 1,
|
||||
PE_UnwindOpCode_ALLOC_SMALL = 2,
|
||||
PE_UnwindOpCode_SET_FPREG = 3,
|
||||
PE_UnwindOpCode_SAVE_NONVOL = 4,
|
||||
PE_UnwindOpCode_SAVE_NONVOL_FAR = 5,
|
||||
PE_UnwindOpCode_EPILOG = 6,
|
||||
PE_UnwindOpCode_SPARE_CODE = 7,
|
||||
PE_UnwindOpCode_SAVE_XMM128 = 8,
|
||||
PE_UnwindOpCode_SAVE_XMM128_FAR = 9,
|
||||
PE_UnwindOpCode_PUSH_MACHFRAME = 10,
|
||||
};
|
||||
|
||||
typedef U8 PE_UnwindGprRegX64;
|
||||
enum
|
||||
{
|
||||
PE_UnwindGprRegX64_RAX = 0,
|
||||
PE_UnwindGprRegX64_RCX = 1,
|
||||
PE_UnwindGprRegX64_RDX = 2,
|
||||
PE_UnwindGprRegX64_RBX = 3,
|
||||
PE_UnwindGprRegX64_RSP = 4,
|
||||
PE_UnwindGprRegX64_RBP = 5,
|
||||
PE_UnwindGprRegX64_RSI = 6,
|
||||
PE_UnwindGprRegX64_RDI = 7,
|
||||
PE_UnwindGprRegX64_R8 = 8,
|
||||
PE_UnwindGprRegX64_R9 = 9,
|
||||
PE_UnwindGprRegX64_R10 = 10,
|
||||
PE_UnwindGprRegX64_R11 = 11,
|
||||
PE_UnwindGprRegX64_R12 = 12,
|
||||
PE_UnwindGprRegX64_R13 = 13,
|
||||
PE_UnwindGprRegX64_R14 = 14,
|
||||
PE_UnwindGprRegX64_R15 = 15,
|
||||
};
|
||||
|
||||
typedef U8 PE_UnwindInfoFlags;
|
||||
enum
|
||||
{
|
||||
PE_UnwindInfoFlag_EHANDLER = (1<<0),
|
||||
PE_UnwindInfoFlag_UHANDLER = (1<<1),
|
||||
PE_UnwindInfoFlag_FHANDLER = 3,
|
||||
PE_UnwindInfoFlag_CHAINED = (1<<2),
|
||||
};
|
||||
|
||||
#define PE_UNWIND_OPCODE_FROM_FLAGS(f) ((f)&0xF)
|
||||
#define PE_UNWIND_INFO_FROM_FLAGS(f) (((f) >> 4)&0xF)
|
||||
|
||||
typedef union PE_UnwindCode PE_UnwindCode;
|
||||
union PE_UnwindCode
|
||||
{
|
||||
struct
|
||||
{
|
||||
U8 off_in_prolog;
|
||||
U8 flags;
|
||||
};
|
||||
U16 u16;
|
||||
};
|
||||
|
||||
#define PE_UNWIND_INFO_VERSION_FROM_HDR(x) ((x)&0x7)
|
||||
#define PE_UNWIND_INFO_FLAGS_FROM_HDR(x) (((x) >> 3)&0x1F)
|
||||
#define PE_UNWIND_INFO_REG_FROM_FRAME(x) ((x)&0xF)
|
||||
#define PE_UNWIND_INFO_OFF_FROM_FRAME(x) (((x) >> 4)&0xF)
|
||||
|
||||
typedef struct PE_UnwindInfo PE_UnwindInfo;
|
||||
struct PE_UnwindInfo
|
||||
{
|
||||
U8 header;
|
||||
U8 prolog_size;
|
||||
U8 codes_num;
|
||||
U8 frame;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: DOS Program
|
||||
|
||||
// generated from pe/dos_program.asm
|
||||
read_only global U8 pe_dos_program_data[] =
|
||||
{
|
||||
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, 0x24, 0x00, 0x00
|
||||
};
|
||||
read_only global String8 pe_dos_program = {pe_dos_program_data, sizeof(pe_dos_program_data)};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsed Info Types
|
||||
|
||||
//- rjf: relocation blocks
|
||||
|
||||
typedef struct PE_BaseRelocBlock PE_BaseRelocBlock;
|
||||
struct PE_BaseRelocBlock
|
||||
{
|
||||
U64 page_virt_off;
|
||||
U64 entry_count;
|
||||
U16 *entries;
|
||||
};
|
||||
|
||||
typedef struct PE_BaseRelocBlockNode PE_BaseRelocBlockNode;
|
||||
struct PE_BaseRelocBlockNode
|
||||
{
|
||||
PE_BaseRelocBlockNode *next;
|
||||
PE_BaseRelocBlock v;
|
||||
};
|
||||
|
||||
typedef struct PE_BaseRelocBlockList PE_BaseRelocBlockList;
|
||||
struct PE_BaseRelocBlockList
|
||||
{
|
||||
PE_BaseRelocBlockNode *first;
|
||||
PE_BaseRelocBlockNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
//- rjf: resources
|
||||
|
||||
typedef struct PE_Resource PE_Resource;
|
||||
struct PE_Resource
|
||||
{
|
||||
COFF_ResourceID id;
|
||||
PE_ResDataKind kind;
|
||||
union
|
||||
{
|
||||
COFF_ResourceDataEntry leaf;
|
||||
struct PE_ResourceDir *dir;
|
||||
struct
|
||||
{
|
||||
COFF_ResourceID type;
|
||||
U32 data_version;
|
||||
U32 version;
|
||||
COFF_ResourceMemoryFlags memory_flags;
|
||||
String8 data;
|
||||
}
|
||||
coff_res;
|
||||
}
|
||||
u;
|
||||
};
|
||||
|
||||
typedef struct PE_ResourceNode PE_ResourceNode;
|
||||
struct PE_ResourceNode
|
||||
{
|
||||
PE_ResourceNode *next;
|
||||
PE_Resource data;
|
||||
};
|
||||
|
||||
typedef struct PE_ResourceList PE_ResourceList;
|
||||
struct PE_ResourceList
|
||||
{
|
||||
PE_ResourceNode *first;
|
||||
PE_ResourceNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct PE_ResourceArray PE_ResourceArray;
|
||||
struct PE_ResourceArray
|
||||
{
|
||||
PE_Resource *v;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
typedef struct PE_ResourceDir PE_ResourceDir;
|
||||
struct PE_ResourceDir
|
||||
{
|
||||
U32 characteristics;
|
||||
COFF_TimeStamp time_stamp;
|
||||
U16 major_version;
|
||||
U16 minor_version;
|
||||
PE_ResourceList named_list;
|
||||
PE_ResourceList id_list;
|
||||
};
|
||||
|
||||
//- rjf: bundle
|
||||
|
||||
typedef struct PE_BinInfo PE_BinInfo;
|
||||
struct PE_BinInfo
|
||||
{
|
||||
@@ -475,161 +735,10 @@ struct PE_BinInfo
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parsed Info Extraction Helper Types
|
||||
//~ rjf: Basic Enum Functions
|
||||
|
||||
typedef U16 PE_BaseRelocKind;
|
||||
enum
|
||||
{
|
||||
PE_BaseRelocKind_ABSOLUTE = 0, // No reallocation is applied. Can be used as padding.
|
||||
PE_BaseRelocKind_HIGH = 1,
|
||||
PE_BaseRelocKind_LOW = 2,
|
||||
PE_BaseRelocKind_HIGHLOW = 3,
|
||||
PE_BaseRelocKind_HIGHADJ = 4,
|
||||
PE_BaseRelocKind_MIPS_JMPADDR = 5,
|
||||
PE_BaseRelocKind_ARM_MOV32 = 5,
|
||||
PE_BaseRelocKind_RISCV_HIGH20 = 5,
|
||||
// 6 is reserved
|
||||
PE_BaseRelocKind_THUMB_MOV32 = 7,
|
||||
PE_BaseRelocKind_RISCV_LOW12I = 7,
|
||||
PE_BaseRelocKind_RISCV_LOW12S = 8,
|
||||
PE_BaseRelocKind_LOONGARCH32_MARK_LA = 8,
|
||||
PE_BaseRelocKind_LOONGARCH64_MARK_LA = 8,
|
||||
PE_BaseRelocKind_MIPS_JMPADDR16 = 9,
|
||||
PE_BaseRelocKind_DIR64 = 10,
|
||||
};
|
||||
#define PE_BaseRelocOffsetFromEntry(x) ((x) & 0x1fff)
|
||||
#define PE_BaseRelocKindFromEntry(x) (((x) >> 12) & 0xf)
|
||||
#define PE_BaseRelocMake(k, off) ((((U16)(k) & 0xf) << 12) | (U16)((off) & 0x1fff))
|
||||
|
||||
typedef struct PE_BaseRelocBlock PE_BaseRelocBlock;
|
||||
struct PE_BaseRelocBlock
|
||||
{
|
||||
U64 page_virt_off;
|
||||
U64 entry_count;
|
||||
U16 *entries;
|
||||
};
|
||||
|
||||
typedef struct PE_BaseRelocBlockNode PE_BaseRelocBlockNode;
|
||||
struct PE_BaseRelocBlockNode
|
||||
{
|
||||
PE_BaseRelocBlockNode *next;
|
||||
PE_BaseRelocBlock v;
|
||||
};
|
||||
|
||||
typedef struct PE_BaseRelocBlockList PE_BaseRelocBlockList;
|
||||
struct PE_BaseRelocBlockList
|
||||
{
|
||||
PE_BaseRelocBlockNode *first;
|
||||
PE_BaseRelocBlockNode *last;
|
||||
U64 count;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ Resources
|
||||
|
||||
#define PE_RES_ALIGN 4u
|
||||
|
||||
read_only U8 PE_RES_MAGIC[] = { 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
enum
|
||||
{
|
||||
PE_Resource_CURSOR = 0x1,
|
||||
PE_Resource_BITMAP = 0x2,
|
||||
PE_Resource_ICON = 0x3,
|
||||
PE_Resource_MENU = 0x4,
|
||||
PE_Resource_DIALOG = 0x5,
|
||||
PE_Resource_STRING = 0x6,
|
||||
PE_Resource_FONTDIR = 0x7,
|
||||
PE_Resource_FONT = 0x8,
|
||||
PE_Resource_ACCELERATOR = 0x9,
|
||||
PE_Resource_RCDATA = 0xA,
|
||||
PE_Resource_MESSAGETABLE = 0xB,
|
||||
PE_Resource_GROUP_CURSOR = 0xC,
|
||||
PE_Resource_GROUP_ICON = 0xE,
|
||||
PE_Resource_VERSION = 0x10,
|
||||
PE_Resource_DLGINCLUDE = 0x11,
|
||||
PE_Resource_PLUGPLAY = 0x13,
|
||||
PE_Resource_VXD = 0x14,
|
||||
PE_Resource_ANICURSOR = 0x15,
|
||||
PE_Resource_ANIICON = 0x16,
|
||||
PE_Resource_HTML = 0x17,
|
||||
PE_Resource_MANIFEST = 0x18,
|
||||
PE_Resource_BITMAP_NEW = 0x2002,
|
||||
PE_Resource_MENU_NEW = 0x2004,
|
||||
PE_Resource_DIALOG_NEW = 0x2005,
|
||||
};
|
||||
typedef U32 PE_ResourceType;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct PE_ResourceHeader
|
||||
{
|
||||
COFF_ResourceHeaderPrefix prefix;
|
||||
U16 type;
|
||||
U16 pad0;
|
||||
U16 name;
|
||||
U16 pad1;
|
||||
U32 data_version;
|
||||
COFF_ResourceMemoryFlags memory_flags;
|
||||
U16 language_id;
|
||||
U32 version;
|
||||
U32 characteristics;
|
||||
} PE_ResourceHeader;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PE_ResData_NULL,
|
||||
PE_ResData_DIR,
|
||||
PE_ResData_COFF_LEAF,
|
||||
PE_ResData_COFF_RESOURCE,
|
||||
} PE_ResDataType;
|
||||
|
||||
typedef struct PE_Resource
|
||||
{
|
||||
COFF_ResourceID id;
|
||||
PE_ResDataType type;
|
||||
union {
|
||||
COFF_ResourceDataEntry leaf;
|
||||
struct PE_ResourceDir *dir;
|
||||
struct {
|
||||
COFF_ResourceID type;
|
||||
U32 data_version;
|
||||
U32 version;
|
||||
COFF_ResourceMemoryFlags memory_flags;
|
||||
String8 data;
|
||||
} coff_res;
|
||||
} u;
|
||||
} PE_Resource;
|
||||
|
||||
typedef struct PE_ResourceNode
|
||||
{
|
||||
struct PE_ResourceNode *next;
|
||||
PE_Resource data;
|
||||
} PE_ResourceNode;
|
||||
|
||||
typedef struct PE_ResourceList
|
||||
{
|
||||
U64 count;
|
||||
PE_ResourceNode *first;
|
||||
PE_ResourceNode *last;
|
||||
} PE_ResourceList;
|
||||
|
||||
typedef struct PE_ResourceArray
|
||||
{
|
||||
U64 count;
|
||||
PE_Resource *v;
|
||||
} PE_ResourceArray;
|
||||
|
||||
typedef struct PE_ResourceDir
|
||||
{
|
||||
U32 characteristics;
|
||||
COFF_TimeStamp time_stamp;
|
||||
U16 major_version;
|
||||
U16 minor_version;
|
||||
PE_ResourceList named_list;
|
||||
PE_ResourceList id_list;
|
||||
} PE_ResourceDir;
|
||||
internal U32 pe_slot_count_from_unwind_op_code(PE_UnwindOpCode opcode);
|
||||
internal String8 pe_string_from_windows_subsystem(PE_WindowsSubsystem subsystem);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Parser Functions
|
||||
@@ -661,12 +770,4 @@ internal PE_Resource * pe_resource_dir_search(PE_ResourceDir *dir, COFF_Reso
|
||||
internal PE_ResourceArray pe_resource_list_to_array(Arena *arena, PE_ResourceList *list);
|
||||
internal PE_ResourceDir * pe_resource_table_from_directory_data(Arena *arena, String8 data);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8 pe_get_dos_program(void);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8 pe_string_from_subsystem(PE_WindowsSubsystem subsystem);
|
||||
|
||||
#endif //PE_H
|
||||
#endif // PE_H
|
||||
|
||||
@@ -43,10 +43,10 @@
|
||||
#include "regs/raddbgi/regs_raddbgi.h"
|
||||
#include "type_graph/type_graph.h"
|
||||
#include "dbgi/dbgi.h"
|
||||
#include "demon/demon_inc.h"
|
||||
#include "demon2/demon2_inc.h"
|
||||
#include "eval/eval_inc.h"
|
||||
#include "unwind/unwind.h"
|
||||
#include "ctrl/ctrl_inc.h"
|
||||
#include "ctrl2/ctrl2_inc.h"
|
||||
|
||||
//- rjf: [c]
|
||||
#include "base/base_inc.c"
|
||||
@@ -71,10 +71,10 @@
|
||||
#include "regs/raddbgi/regs_raddbgi.c"
|
||||
#include "type_graph/type_graph.c"
|
||||
#include "dbgi/dbgi.c"
|
||||
#include "demon/demon_inc.c"
|
||||
#include "demon2/demon2_inc.c"
|
||||
#include "eval/eval_inc.c"
|
||||
#include "unwind/unwind.c"
|
||||
#include "ctrl/ctrl_inc.c"
|
||||
#include "ctrl2/ctrl2_inc.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Entry Point
|
||||
|
||||
Reference in New Issue
Block a user