mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-07 06:18:42 +00:00
plug in dwarf converter to radbin; hook up to both rdi generation & breakpad generation; radbin exe -> pdb / elf -> dwarf inferences; cleanup / unification passes
This commit is contained in:
@@ -111,7 +111,6 @@ pushd build
|
|||||||
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
|
if "%raddbg%"=="1" set didbuild=1 && %compile% ..\src\raddbg\raddbg_main.c %compile_link% %link_icon% %out%raddbg.exe || exit /b 1
|
||||||
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
|
if "%radlink%"=="1" set didbuild=1 && %compile% ..\src\linker\lnk.c %compile_link% %linker% /NOIMPLIB %linker% /NATVIS:"%~dp0\src\linker\linker.natvis" %out%radlink.exe || exit /b 1
|
||||||
if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1
|
if "%radbin%"=="1" set didbuild=1 && %compile% ..\src\radbin\radbin_main.c %compile_link% %out%radbin.exe || exit /b 1
|
||||||
if "%radcon%"=="1" set didbuild=1 && %compile% ..\src\radcon\radcon_main.c %compile_link% %out%radcon.exe || exit /b 1
|
|
||||||
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
|
if "%raddump%"=="1" set didbuild=1 && %compile% ..\src\raddump\raddump_main.c %compile_link% %out%raddump.exe || exit /b 1
|
||||||
if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1
|
if "%tester%"=="1" set didbuild=1 && %compile% ..\src\tester\tester_main.c %compile_link% %out%tester.exe || exit /b 1
|
||||||
if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1
|
if "%ryan_scratch%"=="1" set didbuild=1 && %compile% ..\src\scratch\ryan_scratch.c %compile_link% %out%ryan_scratch.exe || exit /b 1
|
||||||
|
|||||||
@@ -487,14 +487,16 @@ typedef enum OperatingSystem
|
|||||||
}
|
}
|
||||||
OperatingSystem;
|
OperatingSystem;
|
||||||
|
|
||||||
typedef enum ImageType
|
typedef enum ExecutableImageKind
|
||||||
{
|
{
|
||||||
Image_Null,
|
ExecutableImageKind_Null,
|
||||||
Image_CoffPe,
|
ExecutableImageKind_CoffPe,
|
||||||
Image_Elf32,
|
ExecutableImageKind_Elf32,
|
||||||
Image_Elf64,
|
ExecutableImageKind_Elf64,
|
||||||
Image_Macho
|
ExecutableImageKind_Macho,
|
||||||
} ImageType;
|
ExecutableImageKind_COUNT
|
||||||
|
}
|
||||||
|
ExecutableImageKind;
|
||||||
|
|
||||||
typedef enum Arch
|
typedef enum Arch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3989,13 +3989,8 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
|
|||||||
file_header_off + sizeof(COFF_FileHeader) + opt_ext_size);
|
file_header_off + sizeof(COFF_FileHeader) + opt_ext_size);
|
||||||
|
|
||||||
//- rjf: read optional header
|
//- rjf: read optional header
|
||||||
U16 optional_magic = 0;
|
|
||||||
U64 image_base = 0;
|
|
||||||
U64 entry_point = 0;
|
U64 entry_point = 0;
|
||||||
U32 data_dir_count = 0;
|
U32 data_dir_count = 0;
|
||||||
U64 virt_section_align = 0;
|
|
||||||
U64 file_section_align = 0;
|
|
||||||
Rng1U64 *data_dir_franges = 0;
|
|
||||||
if(opt_ext_size > 0)
|
if(opt_ext_size > 0)
|
||||||
{
|
{
|
||||||
// rjf: read magic number
|
// rjf: read magic number
|
||||||
@@ -4011,10 +4006,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
|
|||||||
{
|
{
|
||||||
PE_OptionalHeader32 pe_optional = {0};
|
PE_OptionalHeader32 pe_optional = {0};
|
||||||
dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional);
|
dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional);
|
||||||
image_base = pe_optional.image_base;
|
|
||||||
entry_point = pe_optional.entry_point_va;
|
entry_point = pe_optional.entry_point_va;
|
||||||
virt_section_align = pe_optional.section_alignment;
|
|
||||||
file_section_align = pe_optional.file_alignment;
|
|
||||||
reported_data_dir_offset = sizeof(pe_optional);
|
reported_data_dir_offset = sizeof(pe_optional);
|
||||||
reported_data_dir_count = pe_optional.data_dir_count;
|
reported_data_dir_count = pe_optional.data_dir_count;
|
||||||
}break;
|
}break;
|
||||||
@@ -4022,10 +4014,7 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_
|
|||||||
{
|
{
|
||||||
PE_OptionalHeader32Plus pe_optional = {0};
|
PE_OptionalHeader32Plus pe_optional = {0};
|
||||||
dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional);
|
dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min, &pe_optional);
|
||||||
image_base = pe_optional.image_base;
|
|
||||||
entry_point = pe_optional.entry_point_va;
|
entry_point = pe_optional.entry_point_va;
|
||||||
virt_section_align = pe_optional.section_alignment;
|
|
||||||
file_section_align = pe_optional.file_alignment;
|
|
||||||
reported_data_dir_offset = sizeof(pe_optional);
|
reported_data_dir_offset = sizeof(pe_optional);
|
||||||
reported_data_dir_count = pe_optional.data_dir_count;
|
reported_data_dir_count = pe_optional.data_dir_count;
|
||||||
}break;
|
}break;
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ dw_is_dwarf_present_elf_section_table(String8 raw_image, ELF_BinInfo *bin)
|
|||||||
return is_dwarf_present;
|
return is_dwarf_present;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define SINFL_IMPLEMENTATION
|
||||||
|
#include "third_party/sinfl/sinfl.h"
|
||||||
|
|
||||||
internal DW_Input
|
internal DW_Input
|
||||||
dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin)
|
dw_input_from_elf_section_table(Arena *arena, String8 raw_image, ELF_BinInfo *bin)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -83,18 +83,20 @@ void raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *f
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Win32 Implementations
|
//~ Win32 Implementations
|
||||||
|
|
||||||
#if defined(RADDBG_MARKUP_IMPLEMENTATION) && !defined(RADDBG_MARKUP_STUBS)
|
#if defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS)
|
||||||
#if defined(_WIN32)
|
|
||||||
|
//- section allocating
|
||||||
|
#pragma section(".raddbg", read, write)
|
||||||
|
#define raddbg_exe_data __declspec(allocate(".raddbg"))
|
||||||
|
|
||||||
|
//- one-time implementations
|
||||||
|
#if defined(RADDBG_MARKUP_IMPLEMENTATION)
|
||||||
|
|
||||||
//- default includes
|
//- default includes
|
||||||
#if RADDBG_MARKUP_DEFAULT_VSNPRINTF
|
#if RADDBG_MARKUP_DEFAULT_VSNPRINTF
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//- section allocating
|
|
||||||
#pragma section(".raddbg", read, write)
|
|
||||||
#define raddbg_exe_data __declspec(allocate(".raddbg"))
|
|
||||||
|
|
||||||
//- first byte of exe data section -> is attached
|
//- first byte of exe data section -> is attached
|
||||||
static raddbg_exe_data unsigned char raddbg_is_attached_byte_marker[1];
|
static raddbg_exe_data unsigned char raddbg_is_attached_byte_marker[1];
|
||||||
|
|
||||||
@@ -459,8 +461,8 @@ raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, .
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // defined(_WIN32)
|
|
||||||
#endif // defined(RADDBG_MARKUP_IMPLEMENTATION)
|
#endif // defined(RADDBG_MARKUP_IMPLEMENTATION)
|
||||||
|
#endif // defined(_WIN32) && !defined(RADDBG_MARKUP_STUBS)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Win32 STL Type Views
|
//~ Win32 STL Type Views
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ bucket_list_pop(BucketList *list)
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
|
#define XXH_STATIC_LINKING_ONLY
|
||||||
|
#include "third_party/xxHash/xxhash.c"
|
||||||
|
#include "third_party/xxHash/xxhash.h"
|
||||||
|
|
||||||
internal U64
|
internal U64
|
||||||
hash_table_hasher(String8 string)
|
hash_table_hasher(String8 string)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -151,6 +151,27 @@ os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal String8
|
||||||
|
os_file_read_cstring(Arena *arena, OS_Handle file, U64 off)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
String8List block_list = {0};
|
||||||
|
for(U64 cursor = off, stride = 256;; cursor += stride)
|
||||||
|
{
|
||||||
|
U8 *raw_block = push_array_no_zero(scratch.arena, U8, stride);
|
||||||
|
U64 read_size = os_file_read(file, r1u64(cursor, cursor + stride), raw_block);
|
||||||
|
String8 block = str8_cstring_capped(raw_block, raw_block+read_size);
|
||||||
|
str8_list_push(scratch.arena, &block_list, block);
|
||||||
|
if(read_size != stride || (block.size+1 <= read_size && block.str[block.size] == 0))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String8 result = str8_list_join(arena, &block_list, 0);
|
||||||
|
scratch_end(scratch);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Process Launcher Helpers
|
//~ rjf: Process Launcher Helpers
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ internal B32 os_append_data_to_file_path(String8 path, String8 data);
|
|||||||
internal OS_FileID os_id_from_file_path(String8 path);
|
internal OS_FileID os_id_from_file_path(String8 path);
|
||||||
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
internal S64 os_file_id_compare(OS_FileID a, OS_FileID b);
|
||||||
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
internal String8 os_string_from_file_range(Arena *arena, OS_Handle file, Rng1U64 range);
|
||||||
|
internal String8 os_file_read_cstring(Arena *arena, OS_Handle file, U64 off);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Process Launcher Helpers
|
//~ rjf: Process Launcher Helpers
|
||||||
|
|||||||
+37
-58
@@ -543,7 +543,7 @@ pe_bin_info_from_data(Arena *arena, String8 data)
|
|||||||
data_dir_count = ClampTop(reported_data_dir_count, data_dir_max);
|
data_dir_count = ClampTop(reported_data_dir_count, data_dir_max);
|
||||||
|
|
||||||
// rjf: convert PE directories to ranges
|
// rjf: convert PE directories to ranges
|
||||||
data_dir_franges = push_array(arena, Rng1U64, data_dir_count);
|
data_dir_franges = push_array(arena, Rng1U64, Max(data_dir_count, PE_DataDirectoryIndex_COUNT));
|
||||||
for(U32 dir_idx = 0; dir_idx < data_dir_count; dir_idx += 1)
|
for(U32 dir_idx = 0; dir_idx < data_dir_count; dir_idx += 1)
|
||||||
{
|
{
|
||||||
U64 dir_offset = optional_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*dir_idx;
|
U64 dir_offset = optional_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*dir_idx;
|
||||||
@@ -620,87 +620,66 @@ pe_bin_info_from_data(Arena *arena, String8 data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal PE_DebugInfoList
|
internal PE_DebugInfoList
|
||||||
pe_parse_debug_directory(Arena *arena, String8 raw_image, String8 raw_debug_dir)
|
pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir)
|
||||||
{
|
{
|
||||||
PE_DebugInfoList result = {0};
|
PE_DebugInfoList result = {0};
|
||||||
|
|
||||||
PE_DebugDirectory *debug_entry = str8_deserial_get_raw_ptr(raw_debug_dir, 0, sizeof(*debug_entry));
|
PE_DebugDirectory *debug_entry = str8_deserial_get_raw_ptr(raw_debug_dir, 0, sizeof(*debug_entry));
|
||||||
PE_DebugDirectory *debug_entry_opl = debug_entry + raw_debug_dir.size/sizeof(*debug_entry_opl);
|
PE_DebugDirectory *debug_entry_opl = debug_entry + raw_debug_dir.size/sizeof(*debug_entry_opl);
|
||||||
for (PE_DebugDirectory *entry = debug_entry; entry < debug_entry_opl; ++entry) {
|
for(PE_DebugDirectory *entry = debug_entry; entry < debug_entry_opl; entry += 1)
|
||||||
switch (entry->type) {
|
{
|
||||||
default: {
|
|
||||||
PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1);
|
PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1);
|
||||||
n->v.header = *entry;
|
|
||||||
n->v.u.raw_data = str8_substr(raw_image, rng_1u64(entry->foff, entry->foff + entry->size));
|
|
||||||
|
|
||||||
SLLQueuePush(result.first, result.last, n);
|
SLLQueuePush(result.first, result.last, n);
|
||||||
++result.count;
|
result.count += 1;
|
||||||
} break;
|
n->v.header = *entry;
|
||||||
case PE_DebugDirectoryType_CODEVIEW: {
|
switch(entry->type)
|
||||||
U32 cv_magic = 0;
|
{
|
||||||
str8_deserial_read_struct(raw_image, entry->foff, &cv_magic);
|
default:{}break;
|
||||||
|
case PE_DebugDirectoryType_CODEVIEW:
|
||||||
switch (cv_magic) {
|
{
|
||||||
case PE_CODEVIEW_PDB20_MAGIC: {
|
str8_deserial_read_struct(raw_image, entry->foff, &n->v.cv_magic);
|
||||||
|
switch(n->v.cv_magic)
|
||||||
|
{
|
||||||
|
case PE_CODEVIEW_PDB20_MAGIC:
|
||||||
|
{
|
||||||
PE_CvHeaderPDB20 cv = {0};
|
PE_CvHeaderPDB20 cv = {0};
|
||||||
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
||||||
if (cv_read_size == sizeof(cv)) {
|
if(cv_read_size == sizeof(cv))
|
||||||
|
{
|
||||||
String8 path = {0};
|
String8 path = {0};
|
||||||
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
||||||
|
n->v.cv_pdb20_header = cv;
|
||||||
PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1);
|
n->v.path = path;
|
||||||
n->v.header = *entry;
|
|
||||||
n->v.u.codeview.pdb20.header = cv;
|
|
||||||
n->v.u.codeview.pdb20.path = path;
|
|
||||||
|
|
||||||
SLLQueuePush(result.first, result.last, n);
|
|
||||||
++result.count;
|
|
||||||
} else {
|
|
||||||
Assert(!"unable to read PE_CvHeaderPDB20");
|
|
||||||
}
|
}
|
||||||
} break;
|
}break;
|
||||||
case PE_CODEVIEW_PDB70_MAGIC: {
|
case PE_CODEVIEW_PDB70_MAGIC:
|
||||||
|
{
|
||||||
PE_CvHeaderPDB70 cv = {0};
|
PE_CvHeaderPDB70 cv = {0};
|
||||||
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
||||||
if (cv_read_size == sizeof(cv)) {
|
if(cv_read_size == sizeof(cv))
|
||||||
|
{
|
||||||
String8 path = {0};
|
String8 path = {0};
|
||||||
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
||||||
|
n->v.cv_pdb70_header = cv;
|
||||||
PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1);
|
n->v.path = path;
|
||||||
n->v.header = *entry;
|
|
||||||
n->v.u.codeview.pdb70.header = cv;
|
|
||||||
n->v.u.codeview.pdb70.path = path;
|
|
||||||
|
|
||||||
SLLQueuePush(result.first, result.last, n);
|
|
||||||
++result.count;
|
|
||||||
} else {
|
|
||||||
Assert(!"unable to read PE_CvHeaderPDB70");
|
|
||||||
}
|
}
|
||||||
} break;
|
}break;
|
||||||
case PE_CODEVIEW_RDI_MAGIC: {
|
case PE_CODEVIEW_RDI_MAGIC:
|
||||||
|
{
|
||||||
PE_CvHeaderRDI cv = {0};
|
PE_CvHeaderRDI cv = {0};
|
||||||
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
U64 cv_read_size = str8_deserial_read_struct(raw_image, entry->foff, &cv);
|
||||||
if (cv_read_size == sizeof(cv)) {
|
if(cv_read_size == sizeof(cv))
|
||||||
|
{
|
||||||
String8 path = {0};
|
String8 path = {0};
|
||||||
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
str8_deserial_read_cstr(raw_image, entry->foff+sizeof(cv), &path);
|
||||||
|
n->v.cv_rdi_header = cv;
|
||||||
PE_DebugInfoNode *n = push_array(arena, PE_DebugInfoNode, 1);
|
n->v.path = path;
|
||||||
n->v.header = *entry;
|
|
||||||
n->v.u.codeview.rdi.header = cv;
|
|
||||||
n->v.u.codeview.rdi.path = path;
|
|
||||||
|
|
||||||
SLLQueuePush(result.first, result.last, n);
|
|
||||||
++result.count;
|
|
||||||
} else {
|
|
||||||
Assert(!"unable to read PE_CvHeaderRDI");
|
|
||||||
}
|
}
|
||||||
} break;
|
}break;
|
||||||
default: break;
|
default:{}break;
|
||||||
}
|
}
|
||||||
} break;
|
}break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-24
@@ -1012,30 +1012,13 @@ struct PE_BinInfo
|
|||||||
typedef struct PE_DebugInfo
|
typedef struct PE_DebugInfo
|
||||||
{
|
{
|
||||||
PE_DebugDirectory header;
|
PE_DebugDirectory header;
|
||||||
union
|
U32 cv_magic;
|
||||||
{
|
PE_CvHeaderPDB20 cv_pdb20_header;
|
||||||
union
|
PE_CvHeaderPDB70 cv_pdb70_header;
|
||||||
{
|
PE_CvHeaderRDI cv_rdi_header;
|
||||||
U32 magic;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
PE_CvHeaderPDB20 header;
|
|
||||||
String8 path;
|
String8 path;
|
||||||
} pdb20;
|
}
|
||||||
struct
|
PE_DebugInfo;
|
||||||
{
|
|
||||||
PE_CvHeaderPDB70 header;
|
|
||||||
String8 path;
|
|
||||||
} pdb70;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
PE_CvHeaderRDI header;
|
|
||||||
String8 path;
|
|
||||||
} rdi;
|
|
||||||
} codeview;
|
|
||||||
String8 raw_data;
|
|
||||||
} u;
|
|
||||||
} PE_DebugInfo;
|
|
||||||
|
|
||||||
typedef struct PE_DebugInfoNode
|
typedef struct PE_DebugInfoNode
|
||||||
{
|
{
|
||||||
@@ -1075,7 +1058,7 @@ internal String8 pe_string_from_dll_characteristics(Arena *arena, PE_DllCharacte
|
|||||||
internal B32 pe_check_magic(String8 data);
|
internal B32 pe_check_magic(String8 data);
|
||||||
internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data);
|
internal PE_BinInfo pe_bin_info_from_data(Arena *arena, String8 data);
|
||||||
|
|
||||||
internal PE_DebugInfoList pe_parse_debug_directory(Arena *arena, String8 raw_image, String8 raw_debug_dir);
|
internal PE_DebugInfoList pe_debug_info_list_from_raw_debug_dir(Arena *arena, String8 raw_image, String8 raw_debug_dir);
|
||||||
internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
|
internal PE_ParsedStaticImportTable pe_static_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
|
||||||
internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
|
internal PE_ParsedDelayImportTable pe_delay_imports_from_data(Arena *arena, B32 is_pe32, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range);
|
||||||
internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range);
|
internal PE_ParsedExportTable pe_exports_from_data(Arena *arena, U64 section_count, COFF_SectionHeader *sections, String8 raw_data, Rng1U64 dir_file_range, Rng1U64 dir_virt_range);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
//- GENERATED CODE
|
//- GENERATED CODE
|
||||||
|
|
||||||
C_LINKAGE_BEGIN
|
C_LINKAGE_BEGIN
|
||||||
String8 rb_file_format_display_name_table[9] =
|
String8 rb_file_format_display_name_table[10] =
|
||||||
{
|
{
|
||||||
{0},
|
{0},
|
||||||
str8_lit_comp("PDB"),
|
str8_lit_comp("PDB"),
|
||||||
@@ -13,7 +13,8 @@ str8_lit_comp("COFF (OBJ)"),
|
|||||||
str8_lit_comp("COFF (Big OBJ)"),
|
str8_lit_comp("COFF (Big OBJ)"),
|
||||||
str8_lit_comp("COFF (Archive)"),
|
str8_lit_comp("COFF (Archive)"),
|
||||||
str8_lit_comp("COFF (Thin Archive)"),
|
str8_lit_comp("COFF (Thin Archive)"),
|
||||||
str8_lit_comp("ELF"),
|
str8_lit_comp("ELF32"),
|
||||||
|
str8_lit_comp("ELF64"),
|
||||||
str8_lit_comp("RDI"),
|
str8_lit_comp("RDI"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,13 +15,14 @@ RB_FileFormat_COFF_OBJ,
|
|||||||
RB_FileFormat_COFF_BigOBJ,
|
RB_FileFormat_COFF_BigOBJ,
|
||||||
RB_FileFormat_COFF_Archive,
|
RB_FileFormat_COFF_Archive,
|
||||||
RB_FileFormat_COFF_ThinArchive,
|
RB_FileFormat_COFF_ThinArchive,
|
||||||
RB_FileFormat_ELF,
|
RB_FileFormat_ELF32,
|
||||||
|
RB_FileFormat_ELF64,
|
||||||
RB_FileFormat_RDI,
|
RB_FileFormat_RDI,
|
||||||
RB_FileFormat_COUNT,
|
RB_FileFormat_COUNT,
|
||||||
} RB_FileFormat;
|
} RB_FileFormat;
|
||||||
|
|
||||||
C_LINKAGE_BEGIN
|
C_LINKAGE_BEGIN
|
||||||
extern String8 rb_file_format_display_name_table[9];
|
extern String8 rb_file_format_display_name_table[10];
|
||||||
|
|
||||||
C_LINKAGE_END
|
C_LINKAGE_END
|
||||||
|
|
||||||
|
|||||||
+361
-176
@@ -19,21 +19,21 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
log_scope_begin();
|
log_scope_begin();
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: analyze command line input files
|
//- rjf: analyze & load command line input files
|
||||||
//
|
//
|
||||||
typedef struct File File;
|
RB_FileList input_files = {0};
|
||||||
struct File
|
|
||||||
{
|
{
|
||||||
File *next;
|
String8List input_file_path_tasks = str8_list_copy(arena, &cmdline->inputs);
|
||||||
RB_FileFormat format;
|
for(String8Node *n = input_file_path_tasks.first; n != 0; n = n->next)
|
||||||
String8 path;
|
{
|
||||||
};
|
//////////////////////////
|
||||||
File *first_input_file = 0;
|
//- rjf: do thin analysis of file
|
||||||
File *last_input_file = 0;
|
//
|
||||||
for(String8Node *n = cmdline->inputs.first; n != 0; n = n->next)
|
RB_FileFormat file_format = RB_FileFormat_Null;
|
||||||
|
RB_FileFormatFlags file_format_flags = 0;
|
||||||
{
|
{
|
||||||
OS_Handle file = os_file_open(OS_AccessFlag_Read, n->string);
|
OS_Handle file = os_file_open(OS_AccessFlag_Read, n->string);
|
||||||
RB_FileFormat file_format = RB_FileFormat_Null;
|
FileProperties props = os_properties_from_file(file);
|
||||||
|
|
||||||
//- rjf: PDB magic -> PDB input
|
//- rjf: PDB magic -> PDB input
|
||||||
if(file_format == RB_FileFormat_Null)
|
if(file_format == RB_FileFormat_Null)
|
||||||
@@ -111,7 +111,6 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
os_file_read_struct(file, 0, &header_maybe);
|
os_file_read_struct(file, 0, &header_maybe);
|
||||||
U64 section_count = header_maybe.section_count;
|
U64 section_count = header_maybe.section_count;
|
||||||
U64 section_hdr_opl_off = sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader);
|
U64 section_hdr_opl_off = sizeof(header_maybe) + section_count*sizeof(COFF_SectionHeader);
|
||||||
FileProperties props = os_properties_from_file(file);
|
|
||||||
|
|
||||||
// rjf: check if machine type is valid
|
// rjf: check if machine type is valid
|
||||||
B32 machine_type_is_valid = 0;
|
B32 machine_type_is_valid = 0;
|
||||||
@@ -199,7 +198,7 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
identifier_maybe[ELF_Identifier_Mag3] == 'F');
|
identifier_maybe[ELF_Identifier_Mag3] == 'F');
|
||||||
if(is_elf_magic)
|
if(is_elf_magic)
|
||||||
{
|
{
|
||||||
file_format = RB_FileFormat_ELF;
|
file_format = ELF_HdrIs64Bit(identifier_maybe) ? RB_FileFormat_ELF64 : RB_FileFormat_ELF32;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +213,12 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os_file_close(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
//- rjf: log file recognition
|
//- rjf: log file recognition
|
||||||
|
//
|
||||||
if(file_format != RB_FileFormat_Null)
|
if(file_format != RB_FileFormat_Null)
|
||||||
{
|
{
|
||||||
log_infof("%S recognized as %S\n", n->string, rb_file_format_display_name_table[file_format]);
|
log_infof("%S recognized as %S\n", n->string, rb_file_format_display_name_table[file_format]);
|
||||||
@@ -224,22 +228,109 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
log_infof("%S was not recognized as a supported format.\n", n->string);
|
log_infof("%S was not recognized as a supported format.\n", n->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: push to list
|
//////////////////////////
|
||||||
File *file_n = push_array(arena, File, 1);
|
//- rjf: load recognized files
|
||||||
file_n->path = n->string;
|
//
|
||||||
file_n->format = file_format;
|
String8 file_data = {0};
|
||||||
SLLQueuePush(first_input_file, last_input_file, file_n);
|
if(file_format != RB_FileFormat_Null)
|
||||||
|
{
|
||||||
|
file_data = os_data_from_file_path(arena, n->string);
|
||||||
|
}
|
||||||
|
|
||||||
os_file_close(file);
|
//////////////////////////
|
||||||
|
//- rjf: PE format => generate new implicit path tasks for PDBs
|
||||||
|
//
|
||||||
|
if(file_format == RB_FileFormat_PE)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data);
|
||||||
|
String8 raw_debug_dir = str8_substr(file_data, pe_bin_info.data_dir_franges[PE_DataDirectoryIndex_DEBUG]);
|
||||||
|
PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, file_data, raw_debug_dir);
|
||||||
|
for(PE_DebugInfoNode *n = debug_dir.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->v.path.size != 0)
|
||||||
|
{
|
||||||
|
str8_list_push(arena, &input_file_path_tasks, n->v.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
//- rjf: ELF format => generate new implicit path tasks for debug files
|
||||||
|
//
|
||||||
|
if(file_format == RB_FileFormat_ELF32 ||
|
||||||
|
file_format == RB_FileFormat_ELF64)
|
||||||
|
{
|
||||||
|
ELF_BinInfo elf = elf_bin_from_data(file_data);
|
||||||
|
ELF_GnuDebugLink debug_link = {0};
|
||||||
|
if(elf_parse_debug_link(file_data, &elf, &debug_link) &&
|
||||||
|
debug_link.path.size != 0)
|
||||||
|
{
|
||||||
|
str8_list_push(arena, &input_file_path_tasks, debug_link.path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
//- rjf: PE => check if contains DWARF
|
||||||
|
//
|
||||||
|
if(file_format == RB_FileFormat_PE)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
PE_BinInfo pe_bin_info = pe_bin_info_from_data(scratch.arena, file_data);
|
||||||
|
String8 raw_section_table = str8_substr(file_data, pe_bin_info.section_table_range);
|
||||||
|
String8 string_table = str8_substr(file_data, pe_bin_info.string_table_range);
|
||||||
|
U64 section_count = raw_section_table.size / sizeof(COFF_SectionHeader);
|
||||||
|
COFF_SectionHeader *section_table = (COFF_SectionHeader *)raw_section_table.str;
|
||||||
|
if(dw_is_dwarf_present_coff_section_table(file_data, string_table, section_count, section_table))
|
||||||
|
{
|
||||||
|
file_format_flags |= RB_FileFormatFlag_HasDWARF;
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
//- rjf: ELF => check if contains DWARF
|
||||||
|
//
|
||||||
|
if(file_format == RB_FileFormat_ELF32 ||
|
||||||
|
file_format == RB_FileFormat_ELF64)
|
||||||
|
{
|
||||||
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
ELF_BinInfo elf_bin = elf_bin_from_data(file_data);
|
||||||
|
if(dw_is_dwarf_present_elf_section_table(file_data, &elf_bin))
|
||||||
|
{
|
||||||
|
file_format_flags |= RB_FileFormatFlag_HasDWARF;
|
||||||
|
}
|
||||||
|
scratch_end(scratch);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
//- rjf: push to list
|
||||||
|
//
|
||||||
|
{
|
||||||
|
RB_File *f = push_array(arena, RB_File, 1);
|
||||||
|
f->format = file_format;
|
||||||
|
f->format_flags = file_format_flags;
|
||||||
|
f->path = n->string;
|
||||||
|
f->data = file_data;
|
||||||
|
RB_FileNode *file_n = push_array(arena, RB_FileNode, 1);
|
||||||
|
file_n->v = f;
|
||||||
|
SLLQueuePush(input_files.first, input_files.last, file_n);
|
||||||
|
input_files.count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- rjf: bucket input files by format
|
//- rjf: bucket input files by format
|
||||||
//
|
//
|
||||||
String8List input_paths_from_format_table[RB_FileFormat_COUNT] = {0};
|
RB_FileList input_files_from_format_table[RB_FileFormat_COUNT] = {0};
|
||||||
for(File *f = first_input_file; f != 0; f = f->next)
|
for(RB_FileNode *n = input_files.first; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
str8_list_push(arena, &input_paths_from_format_table[f->format], f->path);
|
RB_FileNode *file_n = push_array(arena, RB_FileNode, 1);
|
||||||
|
file_n->v = n->v;
|
||||||
|
SLLQueuePush(input_files_from_format_table[n->v->format].first, input_files_from_format_table[n->v->format].last, file_n);
|
||||||
|
input_files_from_format_table[n->v->format].count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -284,7 +375,7 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: we can infer from the user-specified output path
|
//- rjf: we can infer from the user-specified output path
|
||||||
else if(str8_match(str8_skip_last_dot(output_path), str8_lit("rdi"), StringMatchFlag_CaseInsensitive))
|
if(str8_match(str8_skip_last_dot(output_path), str8_lit("rdi"), StringMatchFlag_CaseInsensitive))
|
||||||
{
|
{
|
||||||
output_kind = OutputKind_RDI;
|
output_kind = OutputKind_RDI;
|
||||||
log_infof("Output path has .rdi extension; performing `%S`\n", output_kind_info[output_kind].title);
|
log_infof("Output path has .rdi extension; performing `%S`\n", output_kind_info[output_kind].title);
|
||||||
@@ -362,37 +453,16 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
}break;
|
}break;
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
//- rjf: RDI -> conversion based on inputs
|
//- rjf: RDI, Breakpad -> conversion based on inputs
|
||||||
//
|
//
|
||||||
case OutputKind_RDI:
|
case OutputKind_RDI:
|
||||||
|
case OutputKind_Breakpad:
|
||||||
{
|
{
|
||||||
//- rjf: unpack subset flags
|
|
||||||
RDIM_SubsetFlags subset_flags = 0xffffffff;
|
|
||||||
{
|
|
||||||
String8List only_names = cmd_line_strings(cmdline, str8_lit("only"));
|
|
||||||
if(only_names.node_count != 0)
|
|
||||||
{
|
|
||||||
subset_flags = 0;
|
|
||||||
}
|
|
||||||
for(String8Node *n = only_names.first; n != 0; n = n->next)
|
|
||||||
{
|
|
||||||
if(0){}
|
|
||||||
#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags |= RDIM_SubsetFlag_##name; }
|
|
||||||
RDIM_Subset_XList
|
|
||||||
#undef X
|
|
||||||
}
|
|
||||||
String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit"));
|
|
||||||
for(String8Node *n = omit_names.first; n != 0; n = n->next)
|
|
||||||
{
|
|
||||||
if(0){}
|
|
||||||
#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags &= ~RDIM_SubsetFlag_##name; }
|
|
||||||
RDIM_Subset_XList
|
|
||||||
#undef X
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: no inputs => help
|
//- rjf: no inputs => help
|
||||||
if(cmdline->inputs.node_count == 0)
|
if(cmdline->inputs.node_count == 0) switch(output_kind)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case OutputKind_RDI:
|
||||||
{
|
{
|
||||||
fprintf(stderr, "The following arguments are accepted:\n\n");
|
fprintf(stderr, "The following arguments are accepted:\n\n");
|
||||||
|
|
||||||
@@ -425,26 +495,196 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
fprintf(stderr, " - type_name_map The name -> user-defined-type table\n");
|
fprintf(stderr, " - type_name_map The name -> user-defined-type table\n");
|
||||||
fprintf(stderr, " - link_name_procedure_name_map The link_name -> procedure table\n");
|
fprintf(stderr, " - link_name_procedure_name_map The link_name -> procedure table\n");
|
||||||
fprintf(stderr, " - normal_source_path_name_map The path -> source file table\n");
|
fprintf(stderr, " - normal_source_path_name_map The path -> source file table\n");
|
||||||
|
}break;
|
||||||
|
case OutputKind_Breakpad:
|
||||||
|
{
|
||||||
|
fprintf(stderr, "All input files specified on the command line will be dumped. The following\n");
|
||||||
|
fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: unpack subset flags
|
||||||
|
RDIM_SubsetFlags subset_flags = 0xffffffff;
|
||||||
|
switch(output_kind)
|
||||||
|
{
|
||||||
|
case OutputKind_RDI:
|
||||||
|
{
|
||||||
|
String8List only_names = cmd_line_strings(cmdline, str8_lit("only"));
|
||||||
|
if(only_names.node_count != 0)
|
||||||
|
{
|
||||||
|
subset_flags = 0;
|
||||||
|
}
|
||||||
|
for(String8Node *n = only_names.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(0){}
|
||||||
|
#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags |= RDIM_SubsetFlag_##name; }
|
||||||
|
RDIM_Subset_XList
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
String8List omit_names = cmd_line_strings(cmdline, str8_lit("omit"));
|
||||||
|
for(String8Node *n = omit_names.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(0){}
|
||||||
|
#define X(name, name_lower) else if(str8_match(n->string, str8_lit(#name_lower), 0)) { subset_flags &= ~RDIM_SubsetFlag_##name; }
|
||||||
|
RDIM_Subset_XList
|
||||||
|
#undef X
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
case OutputKind_Breakpad:
|
||||||
|
{
|
||||||
|
subset_flags = RDIM_SubsetFlag_All & ~(RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs);
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert inputs to RDI info
|
||||||
|
B32 convert_done = 0;
|
||||||
|
RDIM_BakeParams bake_params = {0};
|
||||||
|
{
|
||||||
|
//- rjf: PE inputs w/ DWARF, or ELF inputs => DWARF -> RDI conversion
|
||||||
|
if(!convert_done &&
|
||||||
|
((input_files_from_format_table[RB_FileFormat_PE].count != 0 &&
|
||||||
|
input_files_from_format_table[RB_FileFormat_PE].first->v->format_flags & RB_FileFormatFlag_HasDWARF) ||
|
||||||
|
(input_files_from_format_table[RB_FileFormat_ELF32].count != 0 ||
|
||||||
|
input_files_from_format_table[RB_FileFormat_ELF64].count != 0)))
|
||||||
|
{
|
||||||
|
convert_done = 1;
|
||||||
|
log_infof("PEs w/ DWARF, or ELFs specified; producing RDI by converting DWARF data\n");
|
||||||
|
|
||||||
|
// rjf: convert
|
||||||
|
D2R_ConvertParams convert_params = {0};
|
||||||
|
{
|
||||||
|
B32 got_exe = 0;
|
||||||
|
B32 got_dbg = 0;
|
||||||
|
if(!got_exe && !got_dbg)
|
||||||
|
{
|
||||||
|
for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_PE].first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->v->format_flags & RB_FileFormatFlag_HasDWARF)
|
||||||
|
{
|
||||||
|
got_exe = 1;
|
||||||
|
got_dbg = 1;
|
||||||
|
convert_params.dbg_name = n->v->path;
|
||||||
|
convert_params.dbg_data = n->v->data;
|
||||||
|
convert_params.exe_name = n->v->path;
|
||||||
|
convert_params.exe_data = n->v->data;
|
||||||
|
convert_params.exe_kind = ExecutableImageKind_CoffPe;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!got_exe)
|
||||||
|
{
|
||||||
|
for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
got_exe = 1;
|
||||||
|
convert_params.exe_name = n->v->path;
|
||||||
|
convert_params.exe_data = n->v->data;
|
||||||
|
convert_params.exe_kind = ExecutableImageKind_Elf32;
|
||||||
|
if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!got_exe)
|
||||||
|
{
|
||||||
|
for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
got_exe = 1;
|
||||||
|
convert_params.exe_name = n->v->path;
|
||||||
|
convert_params.exe_data = n->v->data;
|
||||||
|
convert_params.exe_kind = ExecutableImageKind_Elf64;
|
||||||
|
if(!(n->v->format_flags & RB_FileFormatFlag_HasDWARF))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!got_dbg)
|
||||||
|
{
|
||||||
|
for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF32].first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->v->format_flags & RB_FileFormatFlag_HasDWARF)
|
||||||
|
{
|
||||||
|
got_dbg = 1;
|
||||||
|
convert_params.dbg_name = n->v->path;
|
||||||
|
convert_params.dbg_data = n->v->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!got_dbg)
|
||||||
|
{
|
||||||
|
for(RB_FileNode *n = input_files_from_format_table[RB_FileFormat_ELF64].first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
if(n->v->format_flags & RB_FileFormatFlag_HasDWARF)
|
||||||
|
{
|
||||||
|
got_dbg = 1;
|
||||||
|
convert_params.dbg_name = n->v->path;
|
||||||
|
convert_params.dbg_data = n->v->data;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
convert_params.subset_flags = subset_flags;
|
||||||
|
convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic"));
|
||||||
|
}
|
||||||
|
ProfScope("convert") bake_params = d2r_convert(arena, async_root, &convert_params);
|
||||||
|
|
||||||
|
// rjf: no output path? -> pick one based on debug
|
||||||
|
if(output_path.size == 0)
|
||||||
|
{
|
||||||
|
output_path = push_str8f(arena, "%S.rdi", str8_chop_last_dot(convert_params.dbg_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: PDB inputs => PDB -> RDI conversion
|
//- rjf: PDB inputs => PDB -> RDI conversion
|
||||||
else if(input_paths_from_format_table[RB_FileFormat_PDB].node_count != 0)
|
if(!convert_done &&
|
||||||
|
input_files_from_format_table[RB_FileFormat_PDB].count != 0)
|
||||||
{
|
{
|
||||||
|
convert_done = 1;
|
||||||
log_infof("PDBs specified; producing RDI by converting PDB data\n");
|
log_infof("PDBs specified; producing RDI by converting PDB data\n");
|
||||||
|
|
||||||
|
// rjf: get EXE/PDB file data
|
||||||
|
RB_File *exe_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PE]);
|
||||||
|
RB_File *pdb_file = rb_file_list_first(&input_files_from_format_table[RB_FileFormat_PDB]);
|
||||||
|
String8 exe_path = exe_file->path;
|
||||||
|
String8 pdb_path = pdb_file->path;
|
||||||
|
String8 exe_data = os_data_from_file_path(arena, exe_path);
|
||||||
|
String8 pdb_data = os_data_from_file_path(arena, pdb_path);
|
||||||
|
|
||||||
// rjf: convert
|
// rjf: convert
|
||||||
P2R_ConvertParams convert_params = {0};
|
P2R_ConvertParams convert_params = {0};
|
||||||
{
|
{
|
||||||
convert_params.input_pdb_name = str8_list_first(&input_paths_from_format_table[RB_FileFormat_PDB]);
|
convert_params.input_pdb_name = pdb_path;
|
||||||
convert_params.input_exe_name = str8_list_first(&input_paths_from_format_table[RB_FileFormat_PE]);
|
convert_params.input_exe_name = exe_path;
|
||||||
convert_params.input_pdb_data = os_data_from_file_path(arena, convert_params.input_pdb_name);
|
convert_params.input_pdb_data = pdb_data;
|
||||||
convert_params.input_exe_data = os_data_from_file_path(arena, convert_params.input_exe_name);
|
convert_params.input_exe_data = exe_data;
|
||||||
convert_params.subset_flags = subset_flags;
|
convert_params.subset_flags = subset_flags;
|
||||||
convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic"));
|
convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic"));
|
||||||
}
|
}
|
||||||
RDIM_BakeParams bake_params = {0};
|
|
||||||
ProfScope("convert") bake_params = p2r_convert(arena, async_root, &convert_params);
|
ProfScope("convert") bake_params = p2r_convert(arena, async_root, &convert_params);
|
||||||
|
|
||||||
|
// rjf: no output path? -> pick one based on PDB
|
||||||
|
if(output_path.size == 0)
|
||||||
|
{
|
||||||
|
output_path = push_str8f(arena, "%S.rdi", str8_chop_last_dot(convert_params.input_pdb_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: no viable input paths
|
||||||
|
if(!convert_done && cmdline->inputs.node_count != 0)
|
||||||
|
{
|
||||||
|
log_user_errorf("Could not load debug info from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF debug info.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: convert done => generate output
|
||||||
|
if(convert_done) switch(output_kind)
|
||||||
|
{
|
||||||
|
//- rjf: generate RDI blobs
|
||||||
|
case OutputKind_RDI:
|
||||||
|
{
|
||||||
// rjf: bake
|
// rjf: bake
|
||||||
RDIM_BakeResults bake_results = {0};
|
RDIM_BakeResults bake_results = {0};
|
||||||
ProfScope("bake") bake_results = rdim_bake(arena, async_root, &bake_params);
|
ProfScope("bake") bake_results = rdim_bake(arena, async_root, &bake_params);
|
||||||
@@ -463,95 +703,28 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
// rjf: serialize
|
// rjf: serialize
|
||||||
String8List blobs = rdim_file_blobs_from_section_bundle(arena, &serialized_section_bundle__compressed);
|
String8List blobs = rdim_file_blobs_from_section_bundle(arena, &serialized_section_bundle__compressed);
|
||||||
str8_list_concat_in_place(&output_blobs, &blobs);
|
str8_list_concat_in_place(&output_blobs, &blobs);
|
||||||
|
|
||||||
// rjf: no output path? -> pick one based on PDB
|
|
||||||
if(output_path.size == 0)
|
|
||||||
{
|
|
||||||
output_path = push_str8f(arena, "%S.rdi", str8_chop_last_dot(convert_params.input_pdb_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: no viable input paths
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_user_errorf("Could not create an RDI file from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF information.");
|
|
||||||
}
|
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
////////////////////////////
|
//- rjf: generate breakpad text
|
||||||
//- rjf: dump -> textual dump of inputs
|
|
||||||
//
|
|
||||||
case OutputKind_Dump:
|
|
||||||
{
|
|
||||||
//- rjf: no inputs => help
|
|
||||||
if(cmdline->inputs.node_count == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "All input files specified on the command line will be dumped. The following\n");
|
|
||||||
fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: dump input files in order
|
|
||||||
String8List dump = {0};
|
|
||||||
for(File *f = first_input_file; f != 0; f = f->next)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: join with output
|
|
||||||
str8_list_concat_in_place(&output_blobs, &dump);
|
|
||||||
}break;
|
|
||||||
|
|
||||||
////////////////////////////
|
|
||||||
//- rjf: breakpad -> conversion based on inputs
|
|
||||||
//
|
|
||||||
case OutputKind_Breakpad:
|
case OutputKind_Breakpad:
|
||||||
{
|
|
||||||
//- rjf: no inputs => help
|
|
||||||
if(cmdline->inputs.node_count == 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Pass a path to a PDB file, and optionally its associated PE file, for which\n");
|
|
||||||
fprintf(stderr, "a Breakpad file should be generated.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: PDB inputs => PDB -> Breakpad conversion
|
|
||||||
else if(input_paths_from_format_table[RB_FileFormat_PDB].node_count != 0)
|
|
||||||
{
|
|
||||||
log_infof("PDBs specified; producing Breakpad by converting PDB data\n");
|
|
||||||
|
|
||||||
// rjf: convert
|
|
||||||
P2R_ConvertParams convert_params = {0};
|
|
||||||
{
|
|
||||||
convert_params.input_pdb_name = str8_list_first(&input_paths_from_format_table[RB_FileFormat_PDB]);
|
|
||||||
convert_params.input_exe_name = str8_list_first(&input_paths_from_format_table[RB_FileFormat_PE]);
|
|
||||||
convert_params.input_pdb_data = os_data_from_file_path(arena, convert_params.input_pdb_name);
|
|
||||||
convert_params.input_exe_data = os_data_from_file_path(arena, convert_params.input_exe_name);
|
|
||||||
convert_params.subset_flags = RDIM_SubsetFlag_All & ~(RDIM_SubsetFlag_Types|RDIM_SubsetFlag_UDTs);
|
|
||||||
convert_params.deterministic = cmd_line_has_flag(cmdline, str8_lit("deterministic"));
|
|
||||||
}
|
|
||||||
RDIM_BakeParams bake_params = {0};
|
|
||||||
ProfScope("convert") bake_params = p2r_convert(arena, async_root, &convert_params);
|
|
||||||
|
|
||||||
//- rjf: produce breakpad text
|
|
||||||
String8List dump = {0};
|
|
||||||
ProfScope("dump breakpad text")
|
|
||||||
{
|
{
|
||||||
p2b_async_root = async_root;
|
p2b_async_root = async_root;
|
||||||
RDIM_BakeParams *params = &bake_params;
|
String8List dump = {0};
|
||||||
|
|
||||||
//- rjf: kick off unit vmap baking
|
//- rjf: kick off unit vmap baking
|
||||||
P2B_BakeUnitVMapIn bake_unit_vmap_in = {¶ms->units};
|
P2B_BakeUnitVMapIn bake_unit_vmap_in = {&bake_params.units};
|
||||||
ASYNC_Task *bake_unit_vmap_task = async_task_launch(arena, p2b_bake_unit_vmap_work, .input = &bake_unit_vmap_in);
|
ASYNC_Task *bake_unit_vmap_task = async_task_launch(arena, p2b_bake_unit_vmap_work, .input = &bake_unit_vmap_in);
|
||||||
|
|
||||||
//- rjf: kick off line-table baking
|
//- rjf: kick off line-table baking
|
||||||
P2B_BakeLineTablesIn bake_line_tables_in = {¶ms->line_tables};
|
P2B_BakeLineTablesIn bake_line_tables_in = {&bake_params.line_tables};
|
||||||
ASYNC_Task *bake_line_tables_task = async_task_launch(arena, p2b_bake_line_table_work, .input = &bake_line_tables_in);
|
ASYNC_Task *bake_line_tables_task = async_task_launch(arena, p2b_bake_line_table_work, .input = &bake_line_tables_in);
|
||||||
|
|
||||||
//- rjf: build unit -> line table idx array
|
//- rjf: build unit -> line table idx array
|
||||||
U64 unit_count = params->units.total_count;
|
U64 unit_count = bake_params.units.total_count;
|
||||||
U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1);
|
U32 *unit_line_table_idxs = push_array(arena, U32, unit_count+1);
|
||||||
{
|
{
|
||||||
U64 dst_idx = 1;
|
U64 dst_idx = 1;
|
||||||
for(RDIM_UnitChunkNode *n = params->units.first; n != 0; n = n->next)
|
for(RDIM_UnitChunkNode *n = bake_params.units.first; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1)
|
for(U64 n_idx = 0; n_idx < n->count; n_idx += 1, dst_idx += 1)
|
||||||
{
|
{
|
||||||
@@ -561,12 +734,12 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//- rjf: dump MODULE record
|
//- rjf: dump MODULE record
|
||||||
str8_list_pushf(arena, &dump, "MODULE windows x86_64 %I64x %S\n", params->top_level_info.exe_hash, params->top_level_info.exe_name);
|
str8_list_pushf(arena, &dump, "MODULE windows x86_64 %I64x %S\n", bake_params.top_level_info.exe_hash, bake_params.top_level_info.exe_name);
|
||||||
|
|
||||||
//- rjf: dump FILE records
|
//- rjf: dump FILE records
|
||||||
ProfScope("dump FILE records")
|
ProfScope("dump FILE records")
|
||||||
{
|
{
|
||||||
for(RDIM_SrcFileChunkNode *n = params->src_files.first; n != 0; n = n->next)
|
for(RDIM_SrcFileChunkNode *n = bake_params.src_files.first; n != 0; n = n->next)
|
||||||
{
|
{
|
||||||
for(U64 idx = 0; idx < n->count; idx += 1)
|
for(U64 idx = 0; idx < n->count; idx += 1)
|
||||||
{
|
{
|
||||||
@@ -590,12 +763,12 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
ProfEnd();
|
ProfEnd();
|
||||||
|
|
||||||
//- rjf: kick off FUNC & line record dump tasks
|
//- rjf: kick off FUNC & line record dump tasks
|
||||||
P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, params->procedures.chunk_count);
|
P2B_DumpProcChunkIn *dump_proc_chunk_in = push_array(arena, P2B_DumpProcChunkIn, bake_params.procedures.chunk_count);
|
||||||
ASYNC_Task **dump_proc_chunk_tasks = push_array(arena, ASYNC_Task *, params->procedures.chunk_count);
|
ASYNC_Task **dump_proc_chunk_tasks = push_array(arena, ASYNC_Task *, bake_params.procedures.chunk_count);
|
||||||
ProfScope("kick off FUNC & line record dump tasks")
|
ProfScope("kick off FUNC & line record dump tasks")
|
||||||
{
|
{
|
||||||
U64 task_idx = 0;
|
U64 task_idx = 0;
|
||||||
for(RDIM_SymbolChunkNode *n = params->procedures.first; n != 0; n = n->next, task_idx += 1)
|
for(RDIM_SymbolChunkNode *n = bake_params.procedures.first; n != 0; n = n->next, task_idx += 1)
|
||||||
{
|
{
|
||||||
dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap;
|
dump_proc_chunk_in[task_idx].unit_vmap = unit_vmap;
|
||||||
dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count;
|
dump_proc_chunk_in[task_idx].unit_vmap_count = unit_vmap_count;
|
||||||
@@ -610,30 +783,69 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
//- rjf: join FUNC & line record dump tasks
|
//- rjf: join FUNC & line record dump tasks
|
||||||
ProfScope("join FUNC & line record dump tasks")
|
ProfScope("join FUNC & line record dump tasks")
|
||||||
{
|
{
|
||||||
for(U64 idx = 0; idx < params->procedures.chunk_count; idx += 1)
|
for(U64 idx = 0; idx < bake_params.procedures.chunk_count; idx += 1)
|
||||||
{
|
{
|
||||||
String8List *out = async_task_join_struct(dump_proc_chunk_tasks[idx], String8List);
|
String8List *out = async_task_join_struct(dump_proc_chunk_tasks[idx], String8List);
|
||||||
str8_list_concat_in_place(&dump, out);
|
str8_list_concat_in_place(&dump, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: join with out
|
|
||||||
str8_list_concat_in_place(&output_blobs, &dump);
|
str8_list_concat_in_place(&output_blobs, &dump);
|
||||||
|
}break;
|
||||||
// rjf: no output path? -> pick one based on PDB
|
|
||||||
if(output_path.size == 0)
|
|
||||||
{
|
|
||||||
output_path = push_str8f(arena, "%S.psyms", str8_chop_last_dot(convert_params.input_pdb_name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//- rjf: no viable input paths
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_user_errorf("Could not create a Breakpad file from the specified inputs. You must provide either a valid PDB file or an executable image (PE, ELF) file with DWARF information.");
|
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
//- rjf: dump -> textual dump of inputs
|
||||||
|
//
|
||||||
|
case OutputKind_Dump:
|
||||||
|
{
|
||||||
|
//- rjf: no inputs => help
|
||||||
|
if(cmdline->inputs.node_count == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "All input files specified on the command line will be dumped. The following\n");
|
||||||
|
fprintf(stderr, "formats are currently supported: PE, COFF, RDI, and ELF\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: dump input files in order
|
||||||
|
String8List dump = {0};
|
||||||
|
for(RB_FileNode *n = input_files.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
// TODO(rjf)
|
||||||
|
}
|
||||||
|
|
||||||
|
//- rjf: join with output
|
||||||
|
str8_list_concat_in_place(&output_blobs, &dump);
|
||||||
|
}break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
//- rjf: write outputs
|
||||||
|
//
|
||||||
|
if(output_path.size != 0) ProfScope("write outputs [file]")
|
||||||
|
{
|
||||||
|
OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, output_path);
|
||||||
|
U64 off = 0;
|
||||||
|
for(String8Node *n = output_blobs.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str);
|
||||||
|
off += n->string.size;
|
||||||
|
}
|
||||||
|
os_file_close(output_file);
|
||||||
|
log_infof("Results written to %S", output_path);
|
||||||
|
}
|
||||||
|
else ProfScope("write outputs [stdout]")
|
||||||
|
{
|
||||||
|
for(String8Node *n = output_blobs.first; n != 0; n = n->next)
|
||||||
|
{
|
||||||
|
for(U64 off = 0; off < n->string.size;)
|
||||||
|
{
|
||||||
|
U64 size_to_write = Min(n->string.size - off, GB(2));
|
||||||
|
fwrite(n->string.str + off, size_to_write, 1, stdout);
|
||||||
|
off += size_to_write;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log_info(str8_lit("Results written to stdout"));
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
@@ -656,31 +868,4 @@ rb_entry_point(CmdLine *cmdline)
|
|||||||
fprintf(stderr, "%.*s\n", str8_varg(n->string));
|
fprintf(stderr, "%.*s\n", str8_varg(n->string));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
|
||||||
//- rjf: write outputs
|
|
||||||
//
|
|
||||||
if(output_path.size != 0) ProfScope("write outputs [file]")
|
|
||||||
{
|
|
||||||
OS_Handle output_file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_Write, output_path);
|
|
||||||
U64 off = 0;
|
|
||||||
for(String8Node *n = output_blobs.first; n != 0; n = n->next)
|
|
||||||
{
|
|
||||||
os_file_write(output_file, r1u64(off, off+n->string.size), n->string.str);
|
|
||||||
off += n->string.size;
|
|
||||||
}
|
|
||||||
os_file_close(output_file);
|
|
||||||
}
|
|
||||||
else ProfScope("write outputs [stdout]")
|
|
||||||
{
|
|
||||||
for(String8Node *n = output_blobs.first; n != 0; n = n->next)
|
|
||||||
{
|
|
||||||
for(U64 off = 0; off < n->string.size;)
|
|
||||||
{
|
|
||||||
U64 size_to_write = Min(n->string.size - off, GB(2));
|
|
||||||
fwrite(n->string.str + off, size_to_write, 1, stdout);
|
|
||||||
off += size_to_write;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,42 @@
|
|||||||
|
|
||||||
#include "radbin/generated/radbin.meta.h"
|
#include "radbin/generated/radbin.meta.h"
|
||||||
|
|
||||||
|
////////////////////////////////
|
||||||
|
//~ rjf: File Types
|
||||||
|
|
||||||
|
typedef U32 RB_FileFormatFlags;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RB_FileFormatFlag_HasDWARF = (1<<0),
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RB_File RB_File;
|
||||||
|
struct RB_File
|
||||||
|
{
|
||||||
|
RB_FileFormat format;
|
||||||
|
RB_FileFormatFlags format_flags;
|
||||||
|
String8 path;
|
||||||
|
String8 data;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RB_FileNode RB_FileNode;
|
||||||
|
struct RB_FileNode
|
||||||
|
{
|
||||||
|
RB_FileNode *next;
|
||||||
|
RB_File *v;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct RB_FileList RB_FileList;
|
||||||
|
struct RB_FileList
|
||||||
|
{
|
||||||
|
RB_FileNode *first;
|
||||||
|
RB_FileNode *last;
|
||||||
|
U64 count;
|
||||||
|
};
|
||||||
|
|
||||||
|
read_only global RB_File rb_file_nil = {0};
|
||||||
|
#define rb_file_list_first(list) ((list)->first ? (list)->first->v : &rb_file_nil)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Top-Level Entry Point
|
//~ rjf: Top-Level Entry Point
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ RB_FileFormatTable:
|
|||||||
{ COFF_BigOBJ "COFF (Big OBJ)" }
|
{ COFF_BigOBJ "COFF (Big OBJ)" }
|
||||||
{ COFF_Archive "COFF (Archive)" }
|
{ COFF_Archive "COFF (Archive)" }
|
||||||
{ COFF_ThinArchive "COFF (Thin Archive)" }
|
{ COFF_ThinArchive "COFF (Thin Archive)" }
|
||||||
{ ELF "ELF" }
|
{ ELF32 "ELF32" }
|
||||||
|
{ ELF64 "ELF64" }
|
||||||
{ RDI "RDI" }
|
{ RDI "RDI" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
//- rjf: [h]
|
//- rjf: [h]
|
||||||
#include "base/base_inc.h"
|
#include "base/base_inc.h"
|
||||||
|
#include "linker/hash_table.h"
|
||||||
#include "os/os_inc.h"
|
#include "os/os_inc.h"
|
||||||
#include "path/path.h"
|
#include "path/path.h"
|
||||||
#include "async/async.h"
|
#include "async/async.h"
|
||||||
@@ -28,17 +29,25 @@
|
|||||||
#include "elf/elf_parse.h"
|
#include "elf/elf_parse.h"
|
||||||
#include "codeview/codeview.h"
|
#include "codeview/codeview.h"
|
||||||
#include "codeview/codeview_parse.h"
|
#include "codeview/codeview_parse.h"
|
||||||
|
#include "dwarf/dwarf.h"
|
||||||
|
#include "dwarf/dwarf_parse.h"
|
||||||
|
#include "dwarf/dwarf_coff.h"
|
||||||
|
#include "dwarf/dwarf_elf.h"
|
||||||
#include "msf/msf.h"
|
#include "msf/msf.h"
|
||||||
#include "msf/msf_parse.h"
|
#include "msf/msf_parse.h"
|
||||||
#include "pdb/pdb.h"
|
#include "pdb/pdb.h"
|
||||||
#include "pdb/pdb_parse.h"
|
#include "pdb/pdb_parse.h"
|
||||||
#include "pdb/pdb_stringize.h"
|
#include "pdb/pdb_stringize.h"
|
||||||
|
#include "rdi_from_coff/rdi_from_coff.h"
|
||||||
|
#include "rdi_from_elf/rdi_from_elf.h"
|
||||||
#include "rdi_from_pdb/rdi_from_pdb.h"
|
#include "rdi_from_pdb/rdi_from_pdb.h"
|
||||||
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h"
|
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h"
|
||||||
|
#include "rdi_from_dwarf/rdi_from_dwarf.h"
|
||||||
#include "radbin/radbin.h"
|
#include "radbin/radbin.h"
|
||||||
|
|
||||||
//- rjf: [c]
|
//- rjf: [c]
|
||||||
#include "base/base_inc.c"
|
#include "base/base_inc.c"
|
||||||
|
#include "linker/hash_table.c"
|
||||||
#include "os/os_inc.c"
|
#include "os/os_inc.c"
|
||||||
#include "path/path.c"
|
#include "path/path.c"
|
||||||
#include "async/async.c"
|
#include "async/async.c"
|
||||||
@@ -51,13 +60,20 @@
|
|||||||
#include "elf/elf_parse.c"
|
#include "elf/elf_parse.c"
|
||||||
#include "codeview/codeview.c"
|
#include "codeview/codeview.c"
|
||||||
#include "codeview/codeview_parse.c"
|
#include "codeview/codeview_parse.c"
|
||||||
|
#include "dwarf/dwarf.c"
|
||||||
|
#include "dwarf/dwarf_parse.c"
|
||||||
|
#include "dwarf/dwarf_coff.c"
|
||||||
|
#include "dwarf/dwarf_elf.c"
|
||||||
#include "msf/msf.c"
|
#include "msf/msf.c"
|
||||||
#include "msf/msf_parse.c"
|
#include "msf/msf_parse.c"
|
||||||
#include "pdb/pdb.c"
|
#include "pdb/pdb.c"
|
||||||
#include "pdb/pdb_parse.c"
|
#include "pdb/pdb_parse.c"
|
||||||
#include "pdb/pdb_stringize.c"
|
#include "pdb/pdb_stringize.c"
|
||||||
|
#include "rdi_from_coff/rdi_from_coff.c"
|
||||||
|
#include "rdi_from_elf/rdi_from_elf.c"
|
||||||
#include "rdi_from_pdb/rdi_from_pdb.c"
|
#include "rdi_from_pdb/rdi_from_pdb.c"
|
||||||
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c"
|
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c"
|
||||||
|
#include "rdi_from_dwarf/rdi_from_dwarf.c"
|
||||||
#include "radbin/radbin.c"
|
#include "radbin/radbin.c"
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
+6
-6
@@ -166,7 +166,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ImageType image = Image_Null;
|
ExecutableImageKind image = ExecutableImageKind_Null;
|
||||||
String8 image_name = {0};
|
String8 image_name = {0};
|
||||||
String8 image_data = {0};
|
String8 image_data = {0};
|
||||||
String8 debug_name = {0};
|
String8 debug_name = {0};
|
||||||
@@ -182,13 +182,13 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
|||||||
// Input has PE/COFF
|
// Input has PE/COFF
|
||||||
//
|
//
|
||||||
if (is_pe_present) {
|
if (is_pe_present) {
|
||||||
image = Image_CoffPe;
|
image = ExecutableImageKind_CoffPe;
|
||||||
image_name = pe_name;
|
image_name = pe_name;
|
||||||
image_data = pe_data;
|
image_data = pe_data;
|
||||||
|
|
||||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data);
|
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data);
|
||||||
String8 raw_debug_dir = str8_substr(pe_data, pe.data_dir_franges[PE_DataDirectoryIndex_DEBUG]);
|
String8 raw_debug_dir = str8_substr(pe_data, pe.data_dir_franges[PE_DataDirectoryIndex_DEBUG]);
|
||||||
PE_DebugInfoList debug_dir = pe_parse_debug_directory(scratch.arena, pe_data, raw_debug_dir);
|
PE_DebugInfoList debug_dir = pe_debug_info_list_from_raw_debug_dir(scratch.arena, pe_data, raw_debug_dir);
|
||||||
for (PE_DebugInfoNode *debug_n = debug_dir.first; debug_n != 0; debug_n = debug_n->next) {
|
for (PE_DebugInfoNode *debug_n = debug_dir.first; debug_n != 0; debug_n = debug_n->next) {
|
||||||
PE_DebugInfo *debug = &debug_n->v;
|
PE_DebugInfo *debug = &debug_n->v;
|
||||||
if (debug->header.type == PE_DebugDirectoryType_CODEVIEW) {
|
if (debug->header.type == PE_DebugDirectoryType_CODEVIEW) {
|
||||||
@@ -261,7 +261,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
|||||||
B32 is_split_elf = is_elf_present && is_elf_debug_present && !has_elf_dwarf && has_elf_debug_dwarf;
|
B32 is_split_elf = is_elf_present && is_elf_debug_present && !has_elf_dwarf && has_elf_debug_dwarf;
|
||||||
if (is_split_elf) {
|
if (is_split_elf) {
|
||||||
driver = RC_Driver_Dwarf;
|
driver = RC_Driver_Dwarf;
|
||||||
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? Image_Elf64 : Image_Elf32;
|
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||||
image_name = elf_name;
|
image_name = elf_name;
|
||||||
image_data = elf_data;
|
image_data = elf_data;
|
||||||
debug_name = elf_debug_name;
|
debug_name = elf_debug_name;
|
||||||
@@ -275,7 +275,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
|||||||
B32 is_monolithic_elf = is_elf_present && !is_elf_debug_present && has_elf_dwarf;
|
B32 is_monolithic_elf = is_elf_present && !is_elf_debug_present && has_elf_dwarf;
|
||||||
if (is_monolithic_elf) {
|
if (is_monolithic_elf) {
|
||||||
driver = RC_Driver_Dwarf;
|
driver = RC_Driver_Dwarf;
|
||||||
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? Image_Elf64 : Image_Elf32;
|
image = ELF_HdrIs64Bit(elf.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||||
image_name = elf_name;
|
image_name = elf_name;
|
||||||
image_data = elf_data;
|
image_data = elf_data;
|
||||||
debug_name = elf_name;
|
debug_name = elf_name;
|
||||||
@@ -289,7 +289,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
|||||||
B32 is_debug_elf = !is_elf_present && is_elf_debug_present && has_elf_debug_dwarf;
|
B32 is_debug_elf = !is_elf_present && is_elf_debug_present && has_elf_debug_dwarf;
|
||||||
if (is_debug_elf) {
|
if (is_debug_elf) {
|
||||||
driver = RC_Driver_Dwarf;
|
driver = RC_Driver_Dwarf;
|
||||||
image = ELF_HdrIs64Bit(elf_debug.hdr.e_ident) ? Image_Elf64 : Image_Elf32;
|
image = ELF_HdrIs64Bit(elf_debug.hdr.e_ident) ? ExecutableImageKind_Elf64 : ExecutableImageKind_Elf32;
|
||||||
debug_name = elf_debug_name;
|
debug_name = elf_debug_name;
|
||||||
debug_data = elf_debug_data;
|
debug_data = elf_debug_data;
|
||||||
goto driver_found;
|
goto driver_found;
|
||||||
|
|||||||
+1
-1
@@ -42,7 +42,7 @@ typedef enum
|
|||||||
|
|
||||||
typedef struct RC_Context
|
typedef struct RC_Context
|
||||||
{
|
{
|
||||||
ImageType image;
|
ExecutableImageKind image;
|
||||||
RC_Driver driver;
|
RC_Driver driver;
|
||||||
String8 image_name;
|
String8 image_name;
|
||||||
String8 image_data;
|
String8 image_data;
|
||||||
|
|||||||
+18
-19
@@ -1031,10 +1031,10 @@ d2r_cu_contrib_map_from_aranges(Arena *arena, DW_Input *input, U64 image_base)
|
|||||||
return cm;
|
return cm;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal RDIM_Rng1U64List
|
internal RDIM_Rng1U64ChunkList
|
||||||
d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off)
|
d2r_voff_ranges_from_cu_info_off(D2R_CompUnitContribMap map, U64 info_off)
|
||||||
{
|
{
|
||||||
RDIM_Rng1U64List voff_ranges = {0};
|
RDIM_Rng1U64ChunkList voff_ranges = {0};
|
||||||
U64 voff_list_idx = u64_array_bsearch(map.info_off_arr, map.count, info_off);
|
U64 voff_list_idx = u64_array_bsearch(map.info_off_arr, map.count, info_off);
|
||||||
if (voff_list_idx < map.count) {
|
if (voff_list_idx < map.count) {
|
||||||
voff_ranges = map.voff_range_arr[voff_list_idx];
|
voff_ranges = map.voff_range_arr[voff_list_idx];
|
||||||
@@ -1073,7 +1073,7 @@ d2r_push_scope(Arena *arena, RDIM_ScopeChunkList *scopes, U64 scope_chunk_cap, D
|
|||||||
return scope;
|
return scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal RDIM_BakeParams *
|
internal RDIM_BakeParams
|
||||||
d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
@@ -1091,7 +1091,7 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
|||||||
RDIM_BinarySectionList binary_sections = {0};
|
RDIM_BinarySectionList binary_sections = {0};
|
||||||
DW_Input input = {0};
|
DW_Input input = {0};
|
||||||
|
|
||||||
if (in->image == Image_CoffPe) {
|
if (in->image == ExecutableImageKind_CoffPe) {
|
||||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, in->image_data);
|
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, in->image_data);
|
||||||
|
|
||||||
// get image arch
|
// get image arch
|
||||||
@@ -1111,7 +1111,7 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
|||||||
|
|
||||||
// make DWARF input
|
// make DWARF input
|
||||||
input = dw_input_from_coff_section_table(scratch.arena, in->image_data, string_table, section_count, section_table);
|
input = dw_input_from_coff_section_table(scratch.arena, in->image_data, string_table, section_count, section_table);
|
||||||
} else if (in->image == Image_Elf32 || in->image == Image_Elf64) {
|
} else if (in->image == ExecutableImageKind_Elf32 || in->image == ExecutableImageKind_Elf64) {
|
||||||
ELF_BinInfo elf = elf_bin_from_data(in->debug_data);
|
ELF_BinInfo elf = elf_bin_from_data(in->debug_data);
|
||||||
|
|
||||||
// get image arch
|
// get image arch
|
||||||
@@ -2066,19 +2066,19 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
|||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|
||||||
RDIM_BakeParams *bake_params = push_array(arena, RDIM_BakeParams, 1);
|
RDIM_BakeParams bake_params = {0};
|
||||||
bake_params->top_level_info = top_level_info;
|
bake_params.top_level_info = top_level_info;
|
||||||
bake_params->binary_sections = binary_sections;
|
bake_params.binary_sections = binary_sections;
|
||||||
bake_params->units = units;
|
bake_params.units = units;
|
||||||
bake_params->types = types;
|
bake_params.types = types;
|
||||||
bake_params->udts = udts;
|
bake_params.udts = udts;
|
||||||
bake_params->src_files = src_files;
|
bake_params.src_files = src_files;
|
||||||
bake_params->line_tables = line_tables;
|
bake_params.line_tables = line_tables;
|
||||||
bake_params->global_variables = gvars;
|
bake_params.global_variables = gvars;
|
||||||
bake_params->thread_variables = tvars;
|
bake_params.thread_variables = tvars;
|
||||||
bake_params->procedures = procs;
|
bake_params.procedures = procs;
|
||||||
bake_params->scopes = scopes;
|
bake_params.scopes = scopes;
|
||||||
bake_params->inline_sites = inline_sites;
|
bake_params.inline_sites = inline_sites;
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
return bake_params;
|
return bake_params;
|
||||||
@@ -2148,4 +2148,3 @@ rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U6
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ typedef struct D2R_CompUnitContribMap
|
|||||||
{
|
{
|
||||||
U64 count;
|
U64 count;
|
||||||
U64 *info_off_arr;
|
U64 *info_off_arr;
|
||||||
RDIM_Rng1U64List *voff_range_arr;
|
RDIM_Rng1U64ChunkList *voff_range_arr;
|
||||||
} D2R_CompUnitContribMap;
|
} D2R_CompUnitContribMap;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
//~ rjf: post-0.9.19 TODO notes
|
//~ rjf: post-0.9.19 TODO notes
|
||||||
//
|
//
|
||||||
//- memory view
|
//- memory view
|
||||||
// [x] auto-annotations for non-locals
|
|
||||||
// [ ] have smaller visible range than entire memory
|
// [ ] have smaller visible range than entire memory
|
||||||
// space, within some bounds (e.g. 64KB)
|
// space, within some bounds (e.g. 64KB)
|
||||||
// [ ] dynamically expand memory space, based on
|
// [ ] dynamically expand memory space, based on
|
||||||
@@ -180,6 +179,7 @@
|
|||||||
// [x] if a breakpoint matches the entry point's starting address, its hit count
|
// [x] if a breakpoint matches the entry point's starting address, its hit count
|
||||||
// is not correctly incremented.
|
// is not correctly incremented.
|
||||||
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
|
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
|
||||||
|
// [x] auto-annotations for non-locals
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ rjf: Build Options
|
//~ rjf: Build Options
|
||||||
@@ -203,6 +203,7 @@
|
|||||||
|
|
||||||
//- rjf: [h]
|
//- rjf: [h]
|
||||||
#include "base/base_inc.h"
|
#include "base/base_inc.h"
|
||||||
|
#include "linker/hash_table.h"
|
||||||
#include "os/os_inc.h"
|
#include "os/os_inc.h"
|
||||||
#include "async/async.h"
|
#include "async/async.h"
|
||||||
#include "rdi_format/rdi_format_local.h"
|
#include "rdi_format/rdi_format_local.h"
|
||||||
@@ -225,7 +226,14 @@
|
|||||||
#include "pdb/pdb.h"
|
#include "pdb/pdb.h"
|
||||||
#include "pdb/pdb_parse.h"
|
#include "pdb/pdb_parse.h"
|
||||||
#include "pdb/pdb_stringize.h"
|
#include "pdb/pdb_stringize.h"
|
||||||
|
#include "dwarf/dwarf.h"
|
||||||
|
#include "dwarf/dwarf_parse.h"
|
||||||
|
#include "dwarf/dwarf_coff.h"
|
||||||
|
#include "dwarf/dwarf_elf.h"
|
||||||
|
#include "rdi_from_coff/rdi_from_coff.h"
|
||||||
|
#include "rdi_from_elf/rdi_from_elf.h"
|
||||||
#include "rdi_from_pdb/rdi_from_pdb.h"
|
#include "rdi_from_pdb/rdi_from_pdb.h"
|
||||||
|
#include "rdi_from_dwarf/rdi_from_dwarf.h"
|
||||||
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h"
|
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.h"
|
||||||
#include "radbin/radbin.h"
|
#include "radbin/radbin.h"
|
||||||
#include "regs/regs.h"
|
#include "regs/regs.h"
|
||||||
@@ -249,6 +257,7 @@
|
|||||||
|
|
||||||
//- rjf: [c]
|
//- rjf: [c]
|
||||||
#include "base/base_inc.c"
|
#include "base/base_inc.c"
|
||||||
|
#include "linker/hash_table.c"
|
||||||
#include "os/os_inc.c"
|
#include "os/os_inc.c"
|
||||||
#include "async/async.c"
|
#include "async/async.c"
|
||||||
#include "rdi_format/rdi_format_local.c"
|
#include "rdi_format/rdi_format_local.c"
|
||||||
@@ -271,7 +280,14 @@
|
|||||||
#include "pdb/pdb.c"
|
#include "pdb/pdb.c"
|
||||||
#include "pdb/pdb_parse.c"
|
#include "pdb/pdb_parse.c"
|
||||||
#include "pdb/pdb_stringize.c"
|
#include "pdb/pdb_stringize.c"
|
||||||
|
#include "dwarf/dwarf.c"
|
||||||
|
#include "dwarf/dwarf_parse.c"
|
||||||
|
#include "dwarf/dwarf_coff.c"
|
||||||
|
#include "dwarf/dwarf_elf.c"
|
||||||
|
#include "rdi_from_coff/rdi_from_coff.c"
|
||||||
|
#include "rdi_from_elf/rdi_from_elf.c"
|
||||||
#include "rdi_from_pdb/rdi_from_pdb.c"
|
#include "rdi_from_pdb/rdi_from_pdb.c"
|
||||||
|
#include "rdi_from_dwarf/rdi_from_dwarf.c"
|
||||||
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c"
|
#include "rdi_breakpad_from_pdb/rdi_breakpad_from_pdb.c"
|
||||||
#include "radbin/radbin.c"
|
#include "radbin/radbin.c"
|
||||||
#include "regs/regs.c"
|
#include "regs/regs.c"
|
||||||
|
|||||||
@@ -3043,7 +3043,7 @@ dw_print_debug_str(Arena *arena, String8List *out, String8 indent, DW_Input *inp
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed)
|
dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
DW_Section info = input->sec[DW_Section_Info];
|
DW_Section info = input->sec[DW_Section_Info];
|
||||||
@@ -3190,7 +3190,7 @@ dw_print_debug_loc(Arena *arena, String8List *out, String8 indent, DW_Input *inp
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed)
|
dw_print_debug_ranges(Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed)
|
||||||
{
|
{
|
||||||
NotImplemented;
|
NotImplemented;
|
||||||
#if 0
|
#if 0
|
||||||
@@ -3956,7 +3956,7 @@ dw_print_debug_str_offsets(Arena *arena, String8List *out, String8 indent, DW_In
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
dw_format(Arena *arena, String8List *out, String8 indent, RD_Option opts, DW_Input *input, Arch arch, ImageType image_type)
|
dw_format(Arena *arena, String8List *out, String8 indent, RD_Option opts, DW_Input *input, Arch arch, ExecutableImageKind image_type)
|
||||||
{
|
{
|
||||||
Temp scratch = scratch_begin(&arena, 1);
|
Temp scratch = scratch_begin(&arena, 1);
|
||||||
|
|
||||||
@@ -6610,7 +6610,7 @@ coff_print_obj(Arena *arena, String8List *out, String8 indent, String8 raw_data,
|
|||||||
|
|
||||||
if (opts & RD_Option_Dwarf) {
|
if (opts & RD_Option_Dwarf) {
|
||||||
DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table);
|
DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, header->section_count, section_table);
|
||||||
dw_format(arena, out, indent, opts, &dwarf_input, arch, Image_CoffPe);
|
dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:;
|
exit:;
|
||||||
@@ -7111,7 +7111,7 @@ pe_print_debug_diretory(Arena *arena, String8List *out, String8 indent, String8
|
|||||||
rd_printf("# Debug Directory");
|
rd_printf("# Debug Directory");
|
||||||
rd_indent();
|
rd_indent();
|
||||||
|
|
||||||
PE_DebugInfoList debug_info_list = pe_parse_debug_directory(scratch.arena, raw_data, raw_dir);
|
PE_DebugInfoList debug_info_list = pe_debug_info_list_from_raw_debug_dir(scratch.arena, raw_data, raw_dir);
|
||||||
U64 i = 0;
|
U64 i = 0;
|
||||||
for (PE_DebugInfoNode *entry = debug_info_list.first; entry != 0; entry = entry->next, ++i) {
|
for (PE_DebugInfoNode *entry = debug_info_list.first; entry != 0; entry = entry->next, ++i) {
|
||||||
PE_DebugInfo *de = &entry->v;
|
PE_DebugInfo *de = &entry->v;
|
||||||
@@ -8300,7 +8300,7 @@ pe_print(Arena *arena, String8List *out, String8 indent, String8 raw_data, RD_Op
|
|||||||
|
|
||||||
if (opts & RD_Option_Dwarf) {
|
if (opts & RD_Option_Dwarf) {
|
||||||
DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, file_header->section_count, sections);
|
DW_Input dwarf_input = dw_input_from_coff_section_table(scratch.arena, raw_data, raw_string_table, file_header->section_count, sections);
|
||||||
dw_format(arena, out, indent, opts, &dwarf_input, arch, Image_CoffPe);
|
dw_format(arena, out, indent, opts, &dwarf_input, arch, ExecutableImageKind_CoffPe);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit:;
|
exit:;
|
||||||
@@ -8317,7 +8317,7 @@ elf_print_dwarf_expressions(Arena *arena, String8List *out, String8 indent, Stri
|
|||||||
Arch arch = arch_from_elf_machine(bin.hdr.e_machine);
|
Arch arch = arch_from_elf_machine(bin.hdr.e_machine);
|
||||||
DW_Input dwarf_input = dw_input_from_elf_section_table(scratch.arena, raw_data, &bin);
|
DW_Input dwarf_input = dw_input_from_elf_section_table(scratch.arena, raw_data, &bin);
|
||||||
ELF_Class elf_class = bin.hdr.e_ident[ELF_Identifier_Class];
|
ELF_Class elf_class = bin.hdr.e_ident[ELF_Identifier_Class];
|
||||||
ImageType image_type = elf_class == ELF_Class_32 ? Image_Elf32 : elf_class == ELF_Class_64 ? Image_Elf64 : ELF_Class_None;
|
ExecutableImageKind image_type = elf_class == ELF_Class_32 ? ExecutableImageKind_Elf32 : elf_class == ELF_Class_64 ? ExecutableImageKind_Elf64 : ELF_Class_None;
|
||||||
B32 relaxed = 1;
|
B32 relaxed = 1;
|
||||||
Rng1U64List cu_ranges = dw_unit_ranges_from_data(scratch.arena, dwarf_input.sec[DW_Section_Info].data);
|
Rng1U64List cu_ranges = dw_unit_ranges_from_data(scratch.arena, dwarf_input.sec[DW_Section_Info].data);
|
||||||
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &dwarf_input);
|
DW_ListUnitInput lu_input = dw_list_unit_input_from_input(scratch.arena, &dwarf_input);
|
||||||
|
|||||||
@@ -231,8 +231,8 @@ internal void dw_print_debug_info (Arena *arena, String8List *out, String8
|
|||||||
internal void dw_print_debug_abbrev (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
internal void dw_print_debug_abbrev (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
||||||
internal void dw_print_debug_line (Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_ListUnitInput lu_input, B32 relaxed);
|
internal void dw_print_debug_line (Arena *arena, String8List *out, String8 indent, DW_Input *input, DW_ListUnitInput lu_input, B32 relaxed);
|
||||||
internal void dw_print_debug_str (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
internal void dw_print_debug_str (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
||||||
internal void dw_print_debug_loc (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed);
|
internal void dw_print_debug_loc (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed);
|
||||||
internal void dw_print_debug_ranges (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ImageType image_type, B32 relaxed);
|
internal void dw_print_debug_ranges (Arena *arena, String8List *out, String8 indent, DW_Input *input, Arch arch, ExecutableImageKind image_type, B32 relaxed);
|
||||||
internal void dw_print_debug_aranges (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
internal void dw_print_debug_aranges (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
||||||
internal void dw_print_debug_addr (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
internal void dw_print_debug_addr (Arena *arena, String8List *out, String8 indent, DW_Input *input);
|
||||||
internal void dw_print_debug_loclists (Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_vranges, Arch arch);
|
internal void dw_print_debug_loclists (Arena *arena, String8List *out, String8 indent, DW_Input *input, Rng1U64Array segment_vranges, Arch arch);
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal RDI_Arch
|
||||||
|
c2r_rdi_arch_from_coff_machine(COFF_MachineType machine)
|
||||||
|
{
|
||||||
|
switch (machine) {
|
||||||
|
case COFF_MachineType_X86: return RDI_Arch_X86;
|
||||||
|
case COFF_MachineType_X64: return RDI_Arch_X64;
|
||||||
|
|
||||||
|
case COFF_MachineType_Unknown:
|
||||||
|
case COFF_MachineType_Am33:
|
||||||
|
case COFF_MachineType_Arm:
|
||||||
|
case COFF_MachineType_Arm64:
|
||||||
|
case COFF_MachineType_ArmNt:
|
||||||
|
case COFF_MachineType_Ebc:
|
||||||
|
case COFF_MachineType_Ia64:
|
||||||
|
case COFF_MachineType_M32R:
|
||||||
|
case COFF_MachineType_Mips16:
|
||||||
|
case COFF_MachineType_MipsFpu:
|
||||||
|
case COFF_MachineType_MipsFpu16:
|
||||||
|
case COFF_MachineType_PowerPc:
|
||||||
|
case COFF_MachineType_PowerPcFp:
|
||||||
|
case COFF_MachineType_R4000:
|
||||||
|
case COFF_MachineType_RiscV32:
|
||||||
|
case COFF_MachineType_RiscV64:
|
||||||
|
case COFF_MachineType_Sh3:
|
||||||
|
case COFF_MachineType_Sh3Dsp:
|
||||||
|
case COFF_MachineType_Sh4:
|
||||||
|
case COFF_MachineType_Sh5:
|
||||||
|
case COFF_MachineType_Thumb:
|
||||||
|
case COFF_MachineType_WceMipsV2:
|
||||||
|
NotImplemented;
|
||||||
|
default:
|
||||||
|
return RDI_Arch_NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RDI_BinarySectionFlags
|
||||||
|
c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags)
|
||||||
|
{
|
||||||
|
RDI_BinarySectionFlags result = 0;
|
||||||
|
if(flags & COFF_SectionFlag_MemRead)
|
||||||
|
{
|
||||||
|
result |= RDI_BinarySectionFlag_Read;
|
||||||
|
}
|
||||||
|
if(flags & COFF_SectionFlag_MemWrite)
|
||||||
|
{
|
||||||
|
result |= RDI_BinarySectionFlag_Write;
|
||||||
|
}
|
||||||
|
if(flags & COFF_SectionFlag_MemExecute)
|
||||||
|
{
|
||||||
|
result |= RDI_BinarySectionFlag_Execute;
|
||||||
|
}
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal RDIM_BinarySectionList
|
||||||
|
c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab)
|
||||||
|
{
|
||||||
|
ProfBeginFunction();
|
||||||
|
|
||||||
|
RDIM_BinarySectionList binary_sections = {0};
|
||||||
|
|
||||||
|
for (U64 isec = 0; isec < sectab_count; ++isec) {
|
||||||
|
COFF_SectionHeader *coff_sec = §ab[isec];
|
||||||
|
RDIM_BinarySection *sec = rdim_binary_section_list_push(arena, &binary_sections);
|
||||||
|
|
||||||
|
sec->name = coff_name_from_section_header(string_table, coff_sec);
|
||||||
|
sec->flags = c2r_rdi_binary_section_flags_from_coff_section_flags(coff_sec->flags);
|
||||||
|
sec->voff_first = coff_sec->voff;
|
||||||
|
sec->voff_opl = coff_sec->voff + coff_sec->vsize;
|
||||||
|
sec->foff_first = coff_sec->foff;
|
||||||
|
sec->foff_opl = coff_sec->foff + coff_sec->fsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfEnd();
|
||||||
|
return binary_sections;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef RDI_FROM_COFF_H
|
||||||
|
#define RDI_FROM_COFF_H
|
||||||
|
|
||||||
|
internal RDI_Arch c2r_rdi_arch_from_coff_machine(COFF_MachineType machine);
|
||||||
|
internal RDI_BinarySectionFlags c2r_rdi_binary_section_flags_from_coff_section_flags(COFF_SectionFlags flags);
|
||||||
|
internal RDIM_BinarySectionList c2r_rdi_binary_sections_from_coff_sections(Arena *arena, String8 image_data, String8 string_table, U64 sectab_count, COFF_SectionHeader *sectab);
|
||||||
|
|
||||||
|
#endif // RDI_FROM_COFF_H
|
||||||
+503
-325
File diff suppressed because it is too large
Load Diff
@@ -3,32 +3,23 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef U64 D2R_ConvertFlags;
|
typedef struct D2R_ConvertParams D2R_ConvertParams;
|
||||||
enum
|
struct D2R_ConvertParams
|
||||||
{
|
{
|
||||||
#define X(t,n,k) D2R_ConvertFlag_##t = (1ull << RDI_SectionKind_##t),
|
String8 dbg_name;
|
||||||
RDI_SectionKind_XList
|
String8 dbg_data;
|
||||||
#undef X
|
String8 exe_name;
|
||||||
D2R_ConvertFlag_StrictParse,
|
String8 exe_data;
|
||||||
|
ExecutableImageKind exe_kind;
|
||||||
|
RDIM_SubsetFlags subset_flags;
|
||||||
|
B32 deterministic;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct D2R_User2Convert
|
|
||||||
{
|
|
||||||
String8 input_exe_name;
|
|
||||||
String8 input_exe_data;
|
|
||||||
String8 input_debug_name;
|
|
||||||
String8 input_debug_data;
|
|
||||||
String8 output_name;
|
|
||||||
D2R_ConvertFlags flags;
|
|
||||||
String8List errors;
|
|
||||||
} D2R_User2Convert;
|
|
||||||
|
|
||||||
typedef struct D2R_TypeTable
|
typedef struct D2R_TypeTable
|
||||||
{
|
{
|
||||||
HashTable *ht;
|
HashTable *ht;
|
||||||
RDIM_TypeChunkList *types;
|
RDIM_TypeChunkList *types;
|
||||||
U64 type_chunk_cap;
|
U64 type_chunk_cap;
|
||||||
RDIM_Type *void_type;
|
|
||||||
RDIM_Type *varg_type;
|
RDIM_Type *varg_type;
|
||||||
} D2R_TypeTable;
|
} D2R_TypeTable;
|
||||||
|
|
||||||
@@ -44,26 +35,16 @@ typedef struct D2R_CompUnitContribMap
|
|||||||
{
|
{
|
||||||
U64 count;
|
U64 count;
|
||||||
U64 *info_off_arr;
|
U64 *info_off_arr;
|
||||||
RDIM_Rng1U64List *voff_range_arr;
|
RDIM_Rng1U64ChunkList *voff_range_arr;
|
||||||
} D2R_CompUnitContribMap;
|
} D2R_CompUnitContribMap;
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Command Line -> Conversion Inputs
|
|
||||||
|
|
||||||
internal D2R_User2Convert * d2r_user2convert_from_cmdln(Arena *arena, CmdLine *cmdline);
|
internal RDIM_BakeParams d2r_convert(Arena *arena, ASYNC_Root *async_root, D2R_ConvertParams *params);
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
// Top-Level Conversion Entry Point
|
|
||||||
|
|
||||||
internal RDIM_BakeParams * d2r_convert (Arena *arena, D2R_User2Convert *in);
|
|
||||||
internal RDIM_BakeResults d2r_bake (RDIM_LocalState *state, RDIM_BakeParams *in);
|
|
||||||
internal RDIM_SerializedSectionBundle d2r_compress(Arena *arena, RDIM_SerializedSectionBundle in);
|
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
// Enum Conversion
|
|
||||||
|
|
||||||
internal RDI_Language rdi_language_from_dw_language(DW_Language v);
|
internal RDI_Language rdi_language_from_dw_language(DW_Language v);
|
||||||
internal RDI_RegCodeX86 rdi_reg_from_dw_reg_x86(DW_RegX86 v);
|
internal RDI_RegCodeX86 rdi_reg_from_dw_reg_x86(DW_RegX86 v);
|
||||||
internal B32 rdi_reg_from_dw_reg_x64(DW_RegX64 v, RDI_RegCodeX64 *code_out, U64 *off_out, U64 *size_out);
|
internal B32 rdi_reg_from_dw_reg_x64(DW_RegX64 v, RDI_RegCodeX64 *code_out, U64 *off_out, U64 *size_out);
|
||||||
internal B32 rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U64 *size_out);
|
internal B32 rdi_reg_from_dw_reg(Arch arch, DW_Reg v, RDI_RegCode *code_out, U64 *off_out, U64 *size_out);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
internal RDIM_BinarySectionList
|
||||||
|
e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs)
|
||||||
|
{
|
||||||
|
RDIM_BinarySectionList result = {0};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// Copyright (c) Epic Games Tools
|
||||||
|
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||||
|
|
||||||
|
#ifndef RDI_FROM_ELF_H
|
||||||
|
#define RDI_FROM_ELF_H
|
||||||
|
|
||||||
|
internal RDIM_BinarySectionList e2r_rdi_binary_sections_from_elf_section_table(Arena *arena, ELF_Shdr64Array shdrs);
|
||||||
|
|
||||||
|
#endif // RDI_FROM_ELF_H
|
||||||
Reference in New Issue
Block a user