plug in thin pdb analysis to determine if waiting on a full RDI conversion is necessary - do not wait if RDI is determined to be unnecessary given breakpoints!

This commit is contained in:
Ryan Fleury
2025-06-19 14:48:13 -07:00
parent b28b730788
commit bfe90f5906
7 changed files with 208 additions and 115 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ commands =
.f1 = { .win = "raddbg_stable --ipc kill_all && build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [scratch]
.f2 = { .win = "raddbg_stable --ipc kill_all && build radbin", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
.f2 = { .win = "raddbg_stable --ipc kill_all && build radbin release telemetry && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
//- rjf: [textperf]
// .f1 = { .win = "raddbg_stable --ipc kill_all && build no_meta telemetry textperf && raddbg_stable --ipc bring_to_front && raddbg_stable --ipc run", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
+101 -14
View File
@@ -3803,13 +3803,14 @@ internal void
ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *eval_scope, CTRL_Handle process, CTRL_Handle module, CTRL_UserBreakpointList *user_bps, DMN_TrapChunkList *traps_out)
{
if(user_bps->first == 0) { return; }
ProfBeginFunction();
Temp scratch = scratch_begin(&arena, 1);
DI_Scope *di_scope = eval_scope->di_scope;
CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx;
CTRL_Entity *module_entity = ctrl_entity_from_handle(entity_ctx, module);
CTRL_Entity *debug_info_path_entity = ctrl_entity_child_from_kind(module_entity, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {debug_info_path_entity->string, debug_info_path_entity->timestamp};
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, max_U64);
RDI_Parsed *rdi = di_rdi_from_key(di_scope, &dbgi_key, 1, 0);
U64 base_vaddr = module_entity->vaddr_range.min;
for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next)
{
@@ -3885,6 +3886,7 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_EvalScope *
}
}
scratch_end(scratch);
ProfEnd();
}
internal void
@@ -4717,7 +4719,8 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
// modules (a very bad heuristic that may or may not inform us that we are
// dealing with insane-town projects)
//
if(event->kind == DMN_EventKind_LoadModule &&
if(0 &&
event->kind == DMN_EventKind_LoadModule &&
(entity_ctx->entity_kind_counts[CTRL_EntityKind_Module] > 256 ||
entity_ctx->entity_kind_counts[CTRL_EntityKind_Module] == 1))
{
@@ -4864,6 +4867,14 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
DI_Key key = {push_str8f(scratch.arena, "%S/%S", t->path, info.name), info.props.modified};
di_open(&key);
di_key_list_push(scratch.arena, &preemptively_loaded_keys, &key);
if(preemptively_loaded_keys.count >= Max(1, async_thread_count()/2))
{
for(DI_KeyNode *n = preemptively_loaded_keys.first; n != 0; n = n->next)
{
di_close(&n->v);
}
MemoryZeroStruct(&preemptively_loaded_keys);
}
}
}
os_file_iter_end(it);
@@ -4871,12 +4882,6 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
}
}
}
//- rjf: close each pre-emptively loaded key
for(DI_KeyNode *n = preemptively_loaded_keys.first; n != 0; n = n->next)
{
di_close(&n->v);
}
}
}
@@ -4963,7 +4968,7 @@ ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
//- rjf: control thread eval scopes
internal CTRL_EvalScope *
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, CTRL_Entity *thread)
{
CTRL_EntityCtx *entity_ctx = &ctrl_state->ctrl_thread_entity_store->ctx;
CTRL_EvalScope *scope = push_array(arena, CTRL_EvalScope, 1);
@@ -5005,8 +5010,90 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread)
if(mod->kind != CTRL_EntityKind_Module) { continue; }
CTRL_Entity *dbg_path = ctrl_entity_child_from_kind(mod, CTRL_EntityKind_DebugInfoPath);
DI_Key dbgi_key = {dbg_path->string, dbg_path->timestamp};
//- rjf: try to obtain this module's RDI
RDI_Parsed *rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, 1, 0);
//- rjf: if this RDI is not yet ready => determine if we need to wait for it
B32 rdi_is_necessary = 1;
if(rdi == &rdi_parsed_nil) ProfScope("determine if RDI is necessary")
{
OS_Handle file = os_file_open(OS_AccessFlag_Read|OS_AccessFlag_ShareRead, dbgi_key.path);
{
//- rjf: determine if file is PDB
B32 file_is_pdb = 0;
if(!file_is_pdb)
{
U8 msf70_magic_maybe[sizeof(msf_msf70_magic)] = {0};
os_file_read(file, r1u64(0, sizeof(msf70_magic_maybe)), msf70_magic_maybe);
if(MemoryMatch(msf70_magic_maybe, msf_msf70_magic, sizeof(msf70_magic_maybe)))
{
file_is_pdb = 1;
}
}
if(!file_is_pdb)
{
U8 msf20_magic_maybe[sizeof(msf_msf20_magic)] = {0};
os_file_read(file, r1u64(0, sizeof(msf20_magic_maybe)), msf20_magic_maybe);
if(MemoryMatch(msf20_magic_maybe, msf_msf20_magic, sizeof(msf20_magic_maybe)))
{
file_is_pdb = 1;
}
}
//- rjf: file is PDB -> do thin parse & lookup of all breakpoint files/symbols.
// if any are found in the PDB, then this RDI is necessary.
if(file_is_pdb)
{
Temp scratch = scratch_begin(&arena, 1);
// rjf: gather breakpoint-referenced symbols
String8List symbols = {0};
{
// TODO(rjf)
}
// rjf: gather breakpoint-referenced file paths
String8List files = {0};
{
for(CTRL_UserBreakpointNode *n = user_bps->first; n != 0; n = n->next)
{
if(n->v.kind != CTRL_UserBreakpointKind_FileNameAndLineColNumber)
{
continue;
}
str8_list_push(scratch.arena, &files, n->v.string);
}
}
// rjf: check file
{
FileProperties props = os_properties_from_file(file);
OS_Handle map = os_file_map_open(OS_AccessFlag_Read, file);
void *file_base = os_file_map_view_open(map, OS_AccessFlag_Read, r1u64(0, props.size));
String8 file_data = str8(file_base, props.size);
{
rdi_is_necessary = pdb_has_symbol_or_file_ref(file_data, symbols, files);
}
os_file_map_view_close(map, file_base, r1u64(0, props.size));
os_file_map_close(map);
}
scratch_end(scratch);
}
}
os_file_close(file);
}
//- rjf: if this RDI is necessary, but we do not have it => wait for it forever
if(rdi == &rdi_parsed_nil && rdi_is_necessary)
{
rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, 1, max_U64);
}
//- rjf: fill evaluation module info
eval_modules[eval_module_idx].arch = arch;
eval_modules[eval_module_idx].rdi = di_rdi_from_key(scope->di_scope, &dbgi_key, 1, max_U64);
eval_modules[eval_module_idx].rdi = rdi;
eval_modules[eval_module_idx].vaddr_range = mod->vaddr_range;
eval_modules[eval_module_idx].space = e_space_make(CTRL_EvalSpaceKind_Entity);
eval_modules[eval_module_idx].space.u64_0 = (U64)process;
@@ -5440,7 +5527,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
DMN_TrapChunkList user_traps = {0};
{
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, target_thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread);
for(CTRL_Entity *machine = entity_ctx->root->first;
machine != &ctrl_entity_nil;
machine = machine->next)
@@ -5732,7 +5819,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
}break;
case DMN_EventKind_CreateProcess:
{
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &ctrl_entity_nil);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, &ctrl_entity_nil);
{
DMN_TrapChunkList new_traps = {0};
ctrl_thread__append_resolved_process_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), &msg->user_bps, &new_traps);
@@ -5755,7 +5842,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
case DMN_EventKind_LoadModule:
{
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, ctrl_handle_make(CTRL_MachineID_Local, event->thread));
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(scratch.arena, &msg->user_bps, thread);
{
DMN_TrapChunkList new_traps = {0};
ctrl_thread__append_resolved_module_user_bp_traps(scratch.arena, eval_scope, ctrl_handle_make(CTRL_MachineID_Local, event->process), ctrl_handle_make(CTRL_MachineID_Local, event->module), &msg->user_bps, &new_traps);
@@ -6152,7 +6239,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
// rjf: evaluate hit stop conditions
if(conditions.node_count != 0) ProfScope("evaluate hit stop conditions")
{
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, thread);
CTRL_EvalScope *eval_scope = ctrl_thread__eval_scope_begin(temp.arena, &msg->user_bps, thread);
for(String8Node *condition_n = conditions.first; condition_n != 0; condition_n = condition_n->next)
{
// rjf: evaluate
+1 -1
View File
@@ -1099,7 +1099,7 @@ internal DMN_Event *ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_
internal B32 ctrl_eval_space_read(void *u, E_Space space, void *out, Rng1U64 vaddr_range);
//- rjf: control thread eval scopes
internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_Entity *thread);
internal CTRL_EvalScope *ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, CTRL_Entity *thread);
internal void ctrl_thread__eval_scope_end(CTRL_EvalScope *scope);
//- rjf: log flusher
+99
View File
@@ -1067,3 +1067,102 @@ pdb_strtbl_off_from_string(PDB_Strtbl *strtbl, String8 string)
return result;
}
////////////////////////////////
//~ rjf: Thin Lookup Fast Paths
internal B32
pdb_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
String8 dbi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Dbi);
PDB_DbiParsed *dbi = pdb_dbi_from_data(scratch.arena, dbi_data);
if(dbi)
{
String8 gsi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->gsi_sn);
PDB_GsiParsed *gsi_parsed = pdb_gsi_from_data(scratch.arena, gsi_data);
if(gsi_parsed)
{
String8 symbol_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->sym_sn);
for(String8Node *symbol_n = symbol_list.first; symbol_n != 0; symbol_n = symbol_n->next)
{
U64 symbol_off = pdb_gsi_symbol_from_string(gsi_parsed, symbol_data, symbol_n->string);
if(symbol_off < symbol_data.size)
{
has_ref = 1;
break;
}
}
}
}
scratch_end(scratch);
return has_ref;
}
internal B32
pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
String8 info_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Info);
PDB_Info *info = pdb_info_from_data(scratch.arena, info_data);
if(info)
{
PDB_NamedStreamTable *named_streams = pdb_named_stream_table_from_info(scratch.arena, info);
if(named_streams)
{
MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable];
String8 strtbl_data = msf_data_from_stream_number(scratch.arena, msf_data, st, strtbl_sn);
PDB_Strtbl *strtbl = pdb_strtbl_from_data(scratch.arena, strtbl_data);
if(strtbl)
{
for(String8Node *file_n = file_list.first; file_n != 0; file_n = file_n->next)
{
Temp temp = temp_begin(scratch.arena);
String8 path = file_n->string;
String8 path_pdbstyle = path_convert_slashes(temp.arena, path, PathStyle_WindowsAbsolute);
U32 off = pdb_strtbl_off_from_string(strtbl, path_pdbstyle);
temp_end(temp);
if(off != max_U32)
{
has_ref = 1;
break;
}
}
}
}
}
scratch_end(scratch);
return has_ref;
}
internal B32
pdb_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data);
if(!has_ref && symbol_list.node_count)
{
has_ref = pdb_has_symbol_ref(msf_data, symbol_list, st);
}
if(!has_ref && file_list.node_count)
{
has_ref = pdb_has_file_ref(msf_data, file_list, st);
}
scratch_end(scratch);
return has_ref;
}
+6 -1
View File
@@ -242,6 +242,11 @@ internal String8 pdb_strtbl_string_from_index(PDB_Strtbl *strtbl,
PDB_StringIndex idx);
internal U32 pdb_strtbl_off_from_string(PDB_Strtbl *strtbl, String8 string);
////////////////////////////////
//~ rjf: Thin Lookup Fast Paths
internal B32 pdb_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st);
internal B32 pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st);
internal B32 pdb_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list);
#endif // PDB_PARSE_H
-92
View File
@@ -4387,95 +4387,3 @@ p2r_convert(Arena *arena, ASYNC_Root *async_root, P2R_ConvertParams *in)
////////////////////////////////
internal B32
p2r_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
String8 dbi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Dbi);
PDB_DbiParsed *dbi = pdb_dbi_from_data(scratch.arena, dbi_data);
if(dbi)
{
String8 gsi_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->gsi_sn);
PDB_GsiParsed *gsi_parsed = pdb_gsi_from_data(scratch.arena, gsi_data);
if(gsi_parsed)
{
String8 symbol_data = msf_data_from_stream_number(scratch.arena, msf_data, st, dbi->sym_sn);
for(String8Node *symbol_n = symbol_list.first; symbol_n != 0; symbol_n = symbol_n->next)
{
U64 symbol_off = pdb_gsi_symbol_from_string(gsi_parsed, symbol_data, symbol_n->string);
if(symbol_off < symbol_data.size)
{
has_ref = 1;
break;
}
}
}
}
scratch_end(scratch);
return has_ref;
}
internal B32
p2r_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
String8 info_data = msf_data_from_stream_number(scratch.arena, msf_data, st, PDB_FixedStream_Info);
PDB_Info *info = pdb_info_from_data(scratch.arena, info_data);
if(info)
{
PDB_NamedStreamTable *named_streams = pdb_named_stream_table_from_info(scratch.arena, info);
if(named_streams)
{
MSF_StreamNumber strtbl_sn = named_streams->sn[PDB_NamedStream_StringTable];
String8 strtbl_data = msf_data_from_stream_number(scratch.arena, msf_data, st, strtbl_sn);
PDB_Strtbl *strtbl = pdb_strtbl_from_data(scratch.arena, strtbl_data);
if(strtbl)
{
for(String8Node *file_n = file_list.first; file_n != 0; file_n = file_n->next)
{
U32 off = pdb_strtbl_off_from_string(strtbl, file_n->string);
if(off != max_U32)
{
has_ref = 1;
break;
}
}
}
}
}
scratch_end(scratch);
return has_ref;
}
internal B32
p2r_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list)
{
Temp scratch = scratch_begin(0,0);
B32 has_ref = 0;
MSF_RawStreamTable *st = msf_raw_stream_table_from_data(scratch.arena, msf_data);
if(!has_ref && symbol_list.node_count)
{
has_ref = p2r_has_symbol_ref(msf_data, symbol_list, st);
}
if(!has_ref && file_list.node_count)
{
has_ref = p2r_has_file_ref(msf_data, file_list, st);
}
scratch_end(scratch);
return has_ref;
}
-6
View File
@@ -356,10 +356,4 @@ ASYNC_WORK_DEF(p2r_symbol_stream_convert_work);
internal RDIM_BakeParams p2r_convert(Arena *arena, ASYNC_Root *async_root, P2R_ConvertParams *in);
////////////////////////////////
internal B32 p2r_has_symbol_ref(String8 msf_data, String8List symbol_list, MSF_RawStreamTable *st);
internal B32 p2r_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st);
internal B32 p2r_has_symbol_or_file_ref(String8 msf_data, String8List symbol_list, String8List file_list);
#endif // RDI_FROM_PDB_H