diff --git a/project.4coder b/project.4coder index a2f9e48f..9da7220b 100644 --- a/project.4coder +++ b/project.4coder @@ -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, }, diff --git a/src/ctrl/ctrl_core.c b/src/ctrl/ctrl_core.c index afeaa858..35dad822 100644 --- a/src/ctrl/ctrl_core.c +++ b/src/ctrl/ctrl_core.c @@ -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 diff --git a/src/ctrl/ctrl_core.h b/src/ctrl/ctrl_core.h index 8bac1f4c..651726ac 100644 --- a/src/ctrl/ctrl_core.h +++ b/src/ctrl/ctrl_core.h @@ -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 diff --git a/src/pdb/pdb_parse.c b/src/pdb/pdb_parse.c index dd4bbd8a..36f5e7ad 100644 --- a/src/pdb/pdb_parse.c +++ b/src/pdb/pdb_parse.c @@ -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; +} diff --git a/src/pdb/pdb_parse.h b/src/pdb/pdb_parse.h index 6b028ef4..9474c1a3 100644 --- a/src/pdb/pdb_parse.h +++ b/src/pdb/pdb_parse.h @@ -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 - diff --git a/src/rdi_from_pdb/rdi_from_pdb.c b/src/rdi_from_pdb/rdi_from_pdb.c index b0025c42..93fc40f4 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.c +++ b/src/rdi_from_pdb/rdi_from_pdb.c @@ -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; -} - diff --git a/src/rdi_from_pdb/rdi_from_pdb.h b/src/rdi_from_pdb/rdi_from_pdb.h index 921d6019..90c61514 100644 --- a/src/rdi_from_pdb/rdi_from_pdb.h +++ b/src/rdi_from_pdb/rdi_from_pdb.h @@ -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