From c8a5fc48065bfa851a61507a5c00ad5ce9131c26 Mon Sep 17 00:00:00 2001 From: Nikita Smith Date: Thu, 17 Oct 2024 18:51:35 -0700 Subject: [PATCH] Changed debug directory parser to handle multiple entries. Added parser for RDI debug info entry. Changed debug info lookup order so debugger tries to load path specified in exe first and if debug info is missing then debugger will do heuristic searches. --- src/ctrl/ctrl_core.c | 117 +++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 54 deletions(-) diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index 61c8f997..6faf6fc9 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -3472,7 +3472,13 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ U64 pdatas_count = 0; U64 entry_point_voff = 0; Rng1U64 tls_vaddr_range = {0}; - String8 builtin_debug_info_path = {0}; + U32 pdb_dbg_time = 0; + U32 pdb_dbg_age = 0; + OS_Guid pdb_dbg_guid = {0}; + String8 pdb_dbg_path = str8_zero(); + U32 rdi_dbg_time = 0; + OS_Guid rdi_dbg_guid = {0}; + String8 rdi_dbg_path = str8_zero(); ProfScope("unpack relevant PE info") { B32 is_valid = 1; @@ -3608,65 +3614,62 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ tls_vaddr_range = r1u64(tls_header.index_address, tls_header.index_address+sizeof(U32)); // rjf: grab data about debug info - U32 dbg_time = 0; - U32 dbg_age = 0; - OS_Guid dbg_guid = {0}; + if(data_dir_count > PE_DataDirectoryIndex_DEBUG) { // rjf: read data dir PE_DataDirectory dir = {0}; dmn_process_read_struct(process.dmn_handle, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_DEBUG, &dir); - // rjf: read debug directory - PE_DebugDirectory dbg_data = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min+(U64)dir.virt_off, &dbg_data); - - // rjf: extract external file info from codeview header - if(dbg_data.type == PE_DebugDirectoryType_CODEVIEW) + U64 dbg_dir_count = dir.virt_size / sizeof(PE_DebugDirectory); + for(U64 dbg_dir_idx = 0; dbg_dir_idx < dbg_dir_count; dbg_dir_idx += 1) { - U64 dbg_path_off = 0; - U64 dbg_path_size = 0; - U64 cv_offset = dbg_data.voff; - U32 cv_magic = 0; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min+cv_offset, &cv_magic); - switch(cv_magic) + // rjf: read debug directory + U64 dir_addr = vaddr_range.min + dir.virt_off + dbg_dir_idx * sizeof(PE_DebugDirectory); + PE_DebugDirectory dbg_data = {0}; + dmn_process_read_struct(process.dmn_handle, dir_addr, &dbg_data); + + // rjf: extract external file info from codeview header + if(dbg_data.type == PE_DebugDirectoryType_CODEVIEW) { - default:break; - case PE_CODEVIEW_PDB20_MAGIC: + U32 cv_magic = 0; + dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv_magic); + switch(cv_magic) { - PE_CvHeaderPDB20 cv = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min+cv_offset, &cv); - dbg_time = cv.time; - dbg_age = cv.age; - dbg_path_off = cv_offset + sizeof(cv); - }break; - case PE_CODEVIEW_PDB70_MAGIC: - { - PE_CvHeaderPDB70 cv = {0}; - dmn_process_read_struct(process.dmn_handle, vaddr_range.min+cv_offset, &cv); - dbg_guid = cv.guid; - dbg_age = cv.age; - dbg_path_off = cv_offset + sizeof(cv); - }break; - } - if(dbg_path_off > 0) - { - Temp scratch = scratch_begin(0, 0); - String8List parts = {0}; - for(U64 off = dbg_path_off;; off += 256) - { - U8 bytes[256] = {0}; - dmn_process_read(process.dmn_handle, r1u64(vaddr_range.min+off, vaddr_range.min+off+sizeof(bytes)), bytes); - U64 size = cstring8_length(&bytes[0]); - String8 part = str8(bytes, size); - str8_list_push(scratch.arena, &parts, part); - if(size < sizeof(bytes)) + default:break; + case PE_CODEVIEW_PDB20_MAGIC: { - break; - } + PE_CvHeaderPDB20 cv; + U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min+dbg_data.voff, &cv); + if(read_size == sizeof(cv)) + { + pdb_dbg_time = cv.time; + pdb_dbg_age = cv.age; + pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + } + }break; + case PE_CODEVIEW_PDB70_MAGIC: + { + PE_CvHeaderPDB70 cv; + U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); + if(read_size == sizeof(cv)) + { + pdb_dbg_guid = cv.guid; + pdb_dbg_age = cv.age; + pdb_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + } + }break; + case PE_CODEVIEW_RDI_MAGIC: + { + PE_CvHeaderRDI cv; + U64 read_size = dmn_process_read_struct(process.dmn_handle, vaddr_range.min + dbg_data.voff, &cv); + if(read_size == sizeof(cv)) + { + rdi_dbg_guid = cv.guid; + rdi_dbg_path = dmn_process_read_cstring(arena, process.dmn_handle, vaddr_range.min + dbg_data.voff + sizeof(cv)); + } + }break; } - builtin_debug_info_path = str8_list_join(arena, &parts, 0); - scratch_end(scratch); } } } @@ -3676,16 +3679,22 @@ ctrl_thread__module_open(CTRL_Handle process, CTRL_Handle module, Rng1U64 vaddr_ ////////////////////////////// //- rjf: pick default initial debug info path // - String8 initial_debug_info_path = builtin_debug_info_path; + String8 initial_debug_info_path = str8_zero(); { Temp scratch = scratch_begin(0, 0); String8 exe_folder = str8_chop_last_slash(path); - String8 builtin_debug_info_path__absolute = builtin_debug_info_path; - String8 builtin_debug_info_path__relative = push_str8f(scratch.arena, "%S/%S", exe_folder, builtin_debug_info_path); + String8 rdi_path__absolute = rdi_dbg_path; + String8 rdi_path__relative = push_str8f(scratch.arena, "%S/%S", exe_folder, rdi_dbg_path); + String8 pdb_path__absolute = pdb_dbg_path; + String8 pdb_path__relative = push_str8f(scratch.arena, "%S/%S", exe_folder, pdb_dbg_path); String8 dbg_path_candidates[] = { - /* inferred (treated as relative): */ builtin_debug_info_path__relative, - /* inferred (treated as absolute): */ builtin_debug_info_path__absolute, + /* inferred (treated as absolute): */ rdi_path__absolute, + /* inferred (treated as relative): */ rdi_path__relative, + /* inferred (treated as absolute): */ pdb_path__absolute, + /* inferred (treated as relative): */ pdb_path__relative, + /* "foo.exe" -> "foo.rdi" */ push_str8f(scratch.arena, "%S.rdi", str8_chop_last_dot(path)), + /* "foo.exe" -> "foo.exe.rdi" */ push_str8f(scratch.arena, "%S.rdi", path), /* "foo.exe" -> "foo.pdb" */ push_str8f(scratch.arena, "%S.pdb", str8_chop_last_dot(path)), /* "foo.exe" -> "foo.exe.pdb" */ push_str8f(scratch.arena, "%S.pdb", path), };