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:
Ryan Fleury
2025-06-10 08:53:57 -07:00
parent 638adad93b
commit 49de09883e
29 changed files with 1524 additions and 1019 deletions
+71 -71
View File
@@ -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
View File
@@ -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
View File
@@ -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;
}
+3 -3
View File
@@ -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;
////////////////////////////////