mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-03 04:28:12 +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:
+71
-71
@@ -13,12 +13,12 @@ internal RC_Context
|
||||
rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
|
||||
if (cmdl->inputs.node_count > 2) {
|
||||
fprintf(stderr, "error: too many input files on the command line.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
B32 is_pe_present = 0;
|
||||
B32 is_pdb_present = 0;
|
||||
B32 is_elf_present = 0;
|
||||
@@ -31,7 +31,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
String8 elf_data = {0};
|
||||
String8 elf_debug_name = {0};
|
||||
String8 elf_debug_data = {0};
|
||||
|
||||
|
||||
//
|
||||
// Set typed inputs
|
||||
//
|
||||
@@ -71,7 +71,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
}
|
||||
is_elf_debug_present = 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Pick conversion driver
|
||||
//
|
||||
@@ -87,18 +87,18 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
os_abort(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Load inputs
|
||||
//
|
||||
for (String8Node *input_n = cmdl->inputs.first; input_n != 0; input_n = input_n->next) {
|
||||
String8 input_data = os_data_from_file_path(arena, input_n->string);
|
||||
|
||||
|
||||
if (input_data.size == 0) {
|
||||
fprintf(stderr, "unable to read input %.*s\n", str8_varg(input_n->string));
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
if (pe_check_magic(input_data)) {
|
||||
if (is_pe_present) {
|
||||
fprintf(stderr, "error: too many PE files are specified on the command line\n");
|
||||
@@ -139,7 +139,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
fprintf(stderr, "error: unknown file format %.*s\n", str8_varg(input_n->string));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Validate input combos
|
||||
//
|
||||
@@ -159,54 +159,54 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
}
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
if (is_pe_present && (is_elf_present || is_elf_debug_present)) {
|
||||
fprintf(stderr, "error: command line has too many image types specified.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
ImageType image = Image_Null;
|
||||
|
||||
|
||||
ExecutableImageKind image = ExecutableImageKind_Null;
|
||||
String8 image_name = {0};
|
||||
String8 image_data = {0};
|
||||
String8 debug_name = {0};
|
||||
String8 debug_data = {0};
|
||||
|
||||
|
||||
B32 check_guid = 0;
|
||||
Guid pe_pdb_guid = {0};
|
||||
|
||||
|
||||
B32 elf_has_debug_link = 0;
|
||||
ELF_GnuDebugLink debug_link = {0};
|
||||
|
||||
|
||||
//
|
||||
// Input has PE/COFF
|
||||
//
|
||||
if (is_pe_present) {
|
||||
image = Image_CoffPe;
|
||||
image = ExecutableImageKind_CoffPe;
|
||||
image_name = pe_name;
|
||||
image_data = 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]);
|
||||
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) {
|
||||
PE_DebugInfo *debug = &debug_n->v;
|
||||
if (debug->header.type == PE_DebugDirectoryType_CODEVIEW) {
|
||||
if (debug->u.codeview.magic == PE_CODEVIEW_PDB70_MAGIC) {
|
||||
check_guid = 1;
|
||||
pe_pdb_guid = debug->u.codeview.pdb70.header.guid;
|
||||
|
||||
|
||||
if (!is_pdb_present) {
|
||||
pdb_name = debug->u.codeview.pdb70.path;
|
||||
pdb_data = rc_data_from_file_path(arena, pdb_name);
|
||||
is_pdb_present = 1;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (driver == RC_Driver_Null || driver == RC_Driver_Dwarf) {
|
||||
PE_BinInfo pe = pe_bin_info_from_data(scratch.arena, pe_data);
|
||||
String8 raw_section_table = str8_substr(pe_data, pe.section_table_range);
|
||||
@@ -224,19 +224,19 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (is_elf_present || is_elf_debug_present) {
|
||||
if (driver != RC_Driver_Null && driver != RC_Driver_Dwarf) {
|
||||
fprintf(stderr, "error: ELF inputs are only supported when using DWARF driver.\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Load image ELF
|
||||
//
|
||||
ELF_BinInfo elf = elf_bin_from_data(elf_data);
|
||||
B32 has_elf_dwarf = dw_is_dwarf_present_elf_section_table(elf_data, &elf);
|
||||
|
||||
|
||||
//
|
||||
// ELF doesn't have debug info and no .debug was specified on command line,
|
||||
// try to load .debug via debug link
|
||||
@@ -248,54 +248,54 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
elf_debug_data = rc_data_from_file_path(arena, debug_link.path);
|
||||
is_elf_debug_present = 1;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Load .debug ELF
|
||||
//
|
||||
ELF_BinInfo elf_debug = elf_bin_from_data(elf_debug_data);
|
||||
B32 has_elf_debug_dwarf = dw_is_dwarf_present_elf_section_table(elf_debug_data, &elf_debug);
|
||||
|
||||
|
||||
//
|
||||
// Input is image ELF and .debug ELF
|
||||
//
|
||||
B32 is_split_elf = is_elf_present && is_elf_debug_present && !has_elf_dwarf && has_elf_debug_dwarf;
|
||||
if (is_split_elf) {
|
||||
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_data = elf_data;
|
||||
debug_name = elf_debug_name;
|
||||
debug_data = elf_debug_data;
|
||||
goto driver_found;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Input ELF is image with debug info
|
||||
//
|
||||
B32 is_monolithic_elf = is_elf_present && !is_elf_debug_present && has_elf_dwarf;
|
||||
if (is_monolithic_elf) {
|
||||
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_data = elf_data;
|
||||
debug_name = elf_name;
|
||||
debug_data = elf_data;
|
||||
goto driver_found;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Input ELF is .debug
|
||||
//
|
||||
B32 is_debug_elf = !is_elf_present && is_elf_debug_present && has_elf_debug_dwarf;
|
||||
if (is_debug_elf) {
|
||||
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_data = elf_debug_data;
|
||||
goto driver_found;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Input is PDB
|
||||
//
|
||||
@@ -312,9 +312,9 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
InvalidPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
driver_found:;
|
||||
|
||||
|
||||
//
|
||||
// Handle -out param
|
||||
//
|
||||
@@ -332,8 +332,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
out_name = path_replace_file_extension(arena, debug_name, str8_lit("rdi"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Validate driver input
|
||||
//
|
||||
@@ -342,8 +342,8 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
fprintf(stderr, "error: DWARF is an invalid input for PDB driver\n");
|
||||
os_abort(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
RC_Context ctx = {0};
|
||||
ctx.driver = driver;
|
||||
ctx.image = image;
|
||||
@@ -352,23 +352,23 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
ctx.debug_name = debug_name;
|
||||
ctx.debug_data = debug_data;
|
||||
ctx.flags = RC_Flag_Strings|
|
||||
RC_Flag_IndexRuns|
|
||||
RC_Flag_BinarySections|
|
||||
RC_Flag_Units|
|
||||
RC_Flag_Procedures|
|
||||
RC_Flag_GlobalVariables|
|
||||
RC_Flag_ThreadVariables|
|
||||
RC_Flag_Scopes|
|
||||
RC_Flag_Locals|
|
||||
RC_Flag_Types|
|
||||
RC_Flag_UDTs|
|
||||
RC_Flag_LineInfo|
|
||||
RC_Flag_GlobalVariableNameMap|
|
||||
RC_Flag_ThreadVariableNameMap|
|
||||
RC_Flag_ProcedureNameMap|
|
||||
RC_Flag_TypeNameMap|
|
||||
RC_Flag_LinkNameProcedureNameMap|
|
||||
RC_Flag_NormalSourcePathNameMap;
|
||||
RC_Flag_IndexRuns|
|
||||
RC_Flag_BinarySections|
|
||||
RC_Flag_Units|
|
||||
RC_Flag_Procedures|
|
||||
RC_Flag_GlobalVariables|
|
||||
RC_Flag_ThreadVariables|
|
||||
RC_Flag_Scopes|
|
||||
RC_Flag_Locals|
|
||||
RC_Flag_Types|
|
||||
RC_Flag_UDTs|
|
||||
RC_Flag_LineInfo|
|
||||
RC_Flag_GlobalVariableNameMap|
|
||||
RC_Flag_ThreadVariableNameMap|
|
||||
RC_Flag_ProcedureNameMap|
|
||||
RC_Flag_TypeNameMap|
|
||||
RC_Flag_LinkNameProcedureNameMap|
|
||||
RC_Flag_NormalSourcePathNameMap;
|
||||
if (check_guid) {
|
||||
ctx.flags |= RC_Flag_CheckPdbGuid;
|
||||
ctx.guid = pe_pdb_guid;
|
||||
@@ -378,7 +378,7 @@ rc_context_from_cmd_line(Arena *arena, CmdLine *cmdl)
|
||||
ctx.debug_link = debug_link;
|
||||
}
|
||||
ctx.out_name = out_name;
|
||||
|
||||
|
||||
scratch_end(scratch);
|
||||
return ctx;
|
||||
}
|
||||
@@ -387,40 +387,40 @@ internal String8List
|
||||
rc_run(Arena *arena, RC_Context *rc)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
|
||||
|
||||
ProfBegin("Convert");
|
||||
RDIM_LocalState *local_state = rdim_local_init();
|
||||
RDIM_BakeParams *convert2bake = 0;
|
||||
switch (rc->driver) {
|
||||
case RC_Driver_Null: break;
|
||||
case RC_Driver_Dwarf: convert2bake = d2r_convert(scratch.arena, local_state, rc); break;
|
||||
case RC_Driver_Pdb: convert2bake = p2r_convert(scratch.arena, local_state, rc); break;
|
||||
case RC_Driver_Null: break;
|
||||
case RC_Driver_Dwarf: convert2bake = d2r_convert(scratch.arena, local_state, rc); break;
|
||||
case RC_Driver_Pdb: convert2bake = p2r_convert(scratch.arena, local_state, rc); break;
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
|
||||
if (rc->errors.node_count) {
|
||||
NotImplemented;
|
||||
}
|
||||
|
||||
|
||||
ProfBegin("Bake");
|
||||
RDIM_BakeResults bake2srlz = rdim_bake(local_state, convert2bake);
|
||||
ProfEnd();
|
||||
|
||||
|
||||
ProfBegin("Serialize Bake");
|
||||
RDIM_SerializedSectionBundle srlz2file = rdim_serialized_section_bundle_from_bake_results(&bake2srlz);
|
||||
ProfEnd();
|
||||
|
||||
|
||||
RDIM_SerializedSectionBundle srlz2file_compressed = srlz2file;
|
||||
if (rc->flags & RC_Flag_Compress) {
|
||||
ProfBegin("Compress");
|
||||
srlz2file_compressed = rdim_compress(scratch.arena, &srlz2file);
|
||||
ProfEnd();
|
||||
}
|
||||
|
||||
|
||||
ProfBegin("Serialize");
|
||||
String8List raw_rdi = rdim_file_blobs_from_section_bundle(scratch.arena, &srlz2file_compressed);
|
||||
ProfEnd();
|
||||
|
||||
|
||||
scratch_end(scratch);
|
||||
return raw_rdi;
|
||||
}
|
||||
@@ -456,25 +456,25 @@ rc_main(CmdLine *cmdl)
|
||||
fprintf(stderr, " -driver:<PDB|DWARF> Sets converter for debug info\n");
|
||||
} else {
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
|
||||
|
||||
// make converter context
|
||||
RC_Context rc = rc_context_from_cmd_line(scratch.arena, cmdl);
|
||||
|
||||
|
||||
// make RDI from context
|
||||
String8List raw_rdi = rc_run(scratch.arena, &rc);
|
||||
|
||||
|
||||
// output RDI
|
||||
if (rc.errors.node_count == 0) {
|
||||
if (!os_write_data_list_to_file_path(rc.out_name, raw_rdi)) {
|
||||
str8_list_pushf(scratch.arena, &rc.errors, "no write access to path %.*s", str8_varg(rc.out_name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// report any errors
|
||||
for (String8Node *error_n = rc.errors.first; error_n != 0; error_n = error_n->next) {
|
||||
fprintf(stderr, "error: %.*s\n", str8_varg(error_n->string));
|
||||
}
|
||||
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ typedef enum
|
||||
|
||||
typedef struct RC_Context
|
||||
{
|
||||
ImageType image;
|
||||
ExecutableImageKind image;
|
||||
RC_Driver driver;
|
||||
String8 image_name;
|
||||
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;
|
||||
}
|
||||
|
||||
internal RDIM_Rng1U64List
|
||||
internal RDIM_Rng1U64ChunkList
|
||||
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);
|
||||
if (voff_list_idx < map.count) {
|
||||
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;
|
||||
}
|
||||
|
||||
internal RDIM_BakeParams *
|
||||
internal RDIM_BakeParams
|
||||
d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
||||
{
|
||||
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};
|
||||
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);
|
||||
|
||||
// get image arch
|
||||
@@ -1111,7 +1111,7 @@ d2r_convert(Arena *arena, RDIM_LocalState *local_state, RC_Context *in)
|
||||
|
||||
// make DWARF input
|
||||
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);
|
||||
|
||||
// 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);
|
||||
bake_params->top_level_info = top_level_info;
|
||||
bake_params->binary_sections = binary_sections;
|
||||
bake_params->units = units;
|
||||
bake_params->types = types;
|
||||
bake_params->udts = udts;
|
||||
bake_params->src_files = src_files;
|
||||
bake_params->line_tables = line_tables;
|
||||
bake_params->global_variables = gvars;
|
||||
bake_params->thread_variables = tvars;
|
||||
bake_params->procedures = procs;
|
||||
bake_params->scopes = scopes;
|
||||
bake_params->inline_sites = inline_sites;
|
||||
RDIM_BakeParams bake_params = {0};
|
||||
bake_params.top_level_info = top_level_info;
|
||||
bake_params.binary_sections = binary_sections;
|
||||
bake_params.units = units;
|
||||
bake_params.types = types;
|
||||
bake_params.udts = udts;
|
||||
bake_params.src_files = src_files;
|
||||
bake_params.line_tables = line_tables;
|
||||
bake_params.global_variables = gvars;
|
||||
bake_params.thread_variables = tvars;
|
||||
bake_params.procedures = procs;
|
||||
bake_params.scopes = scopes;
|
||||
bake_params.inline_sites = inline_sites;
|
||||
|
||||
scratch_end(scratch);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ typedef struct D2R_TagNode
|
||||
|
||||
typedef struct D2R_CompUnitContribMap
|
||||
{
|
||||
U64 count;
|
||||
U64 *info_off_arr;
|
||||
RDIM_Rng1U64List *voff_range_arr;
|
||||
U64 count;
|
||||
U64 *info_off_arr;
|
||||
RDIM_Rng1U64ChunkList *voff_range_arr;
|
||||
} D2R_CompUnitContribMap;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user