diff --git a/project.4coder b/project.4coder index c9063119..0c9adfff 100644 --- a/project.4coder +++ b/project.4coder @@ -81,6 +81,15 @@ commands = .save_dirty_files = true, .cursor_at_end = false, }, + .build_raddbg_release_telemetry = + { + .win = "build raddbg release telemetry", + .linux = "", + .out = "*compilation*", + .footer_panel = true, + .save_dirty_files = true, + .cursor_at_end = false, + }, .build_raddbg_from_pdb = { .win = "build raddbg_from_pdb", diff --git a/src/df/core/df_core.c b/src/df/core/df_core.c index c4ab9e95..494a140d 100644 --- a/src/df/core/df_core.c +++ b/src/df/core/df_core.c @@ -1358,7 +1358,6 @@ df_entity_fuzzy_item_array_from_entity_array_needle(Arena *arena, DF_EntityArray { DF_Entity *entity = array->v[src_idx]; String8 display_string = df_display_string_from_entity(scratch.arena, entity); - String8 search_tags = df_search_tags_from_entity(scratch.arena, entity); FuzzyMatchRangeList matches = fuzzy_match_find(arena, needle, display_string); if(matches.count >= matches.needle_part_count) { @@ -1366,14 +1365,18 @@ df_entity_fuzzy_item_array_from_entity_array_needle(Arena *arena, DF_EntityArray result.v[result_idx].matches = matches; result_idx += 1; } - else if(search_tags.size != 0) + else { - FuzzyMatchRangeList tag_matches = fuzzy_match_find(scratch.arena, needle, search_tags); - if(tag_matches.count >= tag_matches.needle_part_count) + String8 search_tags = df_search_tags_from_entity(scratch.arena, entity); + if(search_tags.size != 0) { - result.v[result_idx].entity = entity; - result.v[result_idx].matches = matches; - result_idx += 1; + FuzzyMatchRangeList tag_matches = fuzzy_match_find(scratch.arena, needle, search_tags); + if(tag_matches.count >= tag_matches.needle_part_count) + { + result.v[result_idx].entity = entity; + result.v[result_idx].matches = matches; + result_idx += 1; + } } } } @@ -3532,6 +3535,7 @@ df_type_num_from_binary_name(DF_Entity *binary, String8 name) internal DF_Entity * df_module_from_process_vaddr(DF_Entity *process, U64 vaddr) { + ProfBeginFunction(); DF_Entity *module = &df_g_nil_entity; for(DF_Entity *child = process->first; !df_entity_is_nil(child); child = child->next) { @@ -3541,6 +3545,7 @@ df_module_from_process_vaddr(DF_Entity *process, U64 vaddr) break; } } + ProfEnd(); return module; } @@ -3553,15 +3558,15 @@ df_module_from_thread(DF_Entity *thread) } internal U64 -df_tls_base_vaddr_from_thread(DF_Entity *thread) +df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr) { + ProfBeginFunction(); U64 base_vaddr = 0; Temp scratch = scratch_begin(0, 0); DBGI_Scope *scope = dbgi_scope_open(); //- rjf: unpack thread info - DF_Entity *module = df_module_from_thread(thread); - DF_Entity *process = df_entity_ancestor_from_kind(thread, DF_EntityKind_Process); + DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); DF_Entity *binary = df_binary_file_from_module(module); DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary); String8 bin_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size); @@ -3573,7 +3578,6 @@ df_tls_base_vaddr_from_thread(DF_Entity *thread) Rng1U64 tls_vaddr_range = pe_tls_rng_from_bin_base_vaddr(bin_data, bin, df_base_vaddr_from_module(module)); //- rjf: read module's TLS index - // TODO(allen): migrate all of this logic into DEMON U64 tls_index = 0; { U64 bytes_read = ctrl_process_read(process->ctrl_machine_id, process->ctrl_handle, tls_vaddr_range, &tls_index); @@ -3586,7 +3590,7 @@ df_tls_base_vaddr_from_thread(DF_Entity *thread) //- rjf: PE path if(bin_is_pe) { - U64 thread_info_addr = ctrl_tls_root_vaddr_from_thread(thread->ctrl_machine_id, thread->ctrl_handle); + U64 thread_info_addr = root_vaddr; U64 tls_addr_off = tls_index*addr_size; U64 tls_addr_array = 0; CTRL_ProcessMemorySlice tls_addr_array_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, r1u64(thread_info_addr, thread_info_addr+addr_size), 0); @@ -3639,6 +3643,7 @@ df_tls_base_vaddr_from_thread(DF_Entity *thread) dbgi_scope_close(scope); scratch_end(scratch); + ProfEnd(); return base_vaddr; } @@ -4125,6 +4130,7 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ //- rjf: unpack arguments DF_Entity *thread = df_entity_from_handle(ctrl_ctx->thread); + U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(thread->ctrl_machine_id, thread->ctrl_handle); DF_Entity *process = thread->parent; U64 unwind_count = ctrl_ctx->unwind_count; CTRL_Unwind unwind = df_query_cached_unwind_from_thread(thread); @@ -4148,7 +4154,7 @@ df_eval_from_string(Arena *arena, DBGI_Scope *scope, DF_CtrlCtx *ctrl_ctx, EVAL_ //- rjf: unpack module info & produce eval machine DF_Entity *module = df_module_from_process_vaddr(process, thread_unwind_ip_vaddr); U64 module_base = df_base_vaddr_from_module(module); - U64 tls_base = df_tls_base_vaddr_from_thread(thread); + U64 tls_base = df_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, thread_unwind_ip_vaddr); EVAL_Machine machine = {0}; machine.u = (void *)thread->parent; machine.arch = arch; @@ -6227,6 +6233,44 @@ df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count) return result; } +internal U64 +df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr) +{ + U64 result = 0; + { + DF_RunTLSBaseCache *cache = &df_state->tls_base_cache; + if(cache->slots_count == 0) + { + cache->slots_count = 256; + cache->slots = push_array(cache->arena, DF_RunTLSBaseCacheSlot, cache->slots_count); + } + DF_Handle handle = df_handle_from_entity(process); + U64 hash = df_hash_from_seed_string(df_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr)); + U64 slot_idx = hash%cache->slots_count; + DF_RunTLSBaseCacheSlot *slot = &cache->slots[slot_idx]; + DF_RunTLSBaseCacheNode *node = 0; + for(DF_RunTLSBaseCacheNode *n = slot->first; n != 0; n = n->hash_next) + { + if(df_handle_match(n->process, handle) && n->root_vaddr == root_vaddr && n->rip_vaddr == rip_vaddr) + { + node = n; + break; + } + } + if(node == 0) + { + node = push_array(cache->arena, DF_RunTLSBaseCacheNode, 1); + SLLQueuePush_N(slot->first, slot->last, node, hash_next); + node->process = handle; + node->root_vaddr = root_vaddr; + node->rip_vaddr = rip_vaddr; + node->tls_base_vaddr = df_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); + } + result = node->tls_base_vaddr; + } + return result; +} + internal EVAL_String2NumMap * df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff) { @@ -6385,6 +6429,7 @@ df_core_init(String8 user_path, String8 profile_path, DF_StateDeltaHistory *hist // rjf: set up per-run caches df_state->unwind_cache.arena = arena_alloc(); + df_state->tls_base_cache.arena = arena_alloc(); df_state->locals_cache.arena = arena_alloc(); df_state->member_cache.arena = arena_alloc(); @@ -6867,6 +6912,19 @@ df_core_begin_frame(Arena *arena, DF_CmdList *cmds, F32 dt) df_state->unwind_cache_reggen_idx = new_reggen_idx; } + //- rjf: clear tls base cache + if((df_state->tls_base_cache_reggen_idx != new_reggen_idx || + df_state->tls_base_cache_memgen_idx != new_memgen_idx) && + !df_ctrl_targets_running()) + { + DF_RunTLSBaseCache *cache = &df_state->tls_base_cache; + arena_clear(cache->arena); + cache->slots_count = 0; + cache->slots = 0; + df_state->tls_base_cache_reggen_idx = new_reggen_idx; + df_state->tls_base_cache_memgen_idx = new_memgen_idx; + } + //- rjf: clear locals cache if(df_state->locals_cache_reggen_idx != new_reggen_idx && !df_ctrl_targets_running()) { diff --git a/src/df/core/df_core.h b/src/df/core/df_core.h index b200d9a2..9627b556 100644 --- a/src/df/core/df_core.h +++ b/src/df/core/df_core.h @@ -939,6 +939,7 @@ struct DF_RunUnwindCacheNode DF_RunUnwindCacheNode *hash_next; DF_Handle thread; CTRL_Unwind unwind; + U64 tls_base_vaddr; }; typedef struct DF_RunUnwindCacheSlot DF_RunUnwindCacheSlot; @@ -956,6 +957,33 @@ struct DF_RunUnwindCache DF_RunUnwindCacheSlot *table; }; +//- rjf: per-run tls-base-vaddr cache + +typedef struct DF_RunTLSBaseCacheNode DF_RunTLSBaseCacheNode; +struct DF_RunTLSBaseCacheNode +{ + DF_RunTLSBaseCacheNode *hash_next; + DF_Handle process; + U64 root_vaddr; + U64 rip_vaddr; + U64 tls_base_vaddr; +}; + +typedef struct DF_RunTLSBaseCacheSlot DF_RunTLSBaseCacheSlot; +struct DF_RunTLSBaseCacheSlot +{ + DF_RunTLSBaseCacheNode *first; + DF_RunTLSBaseCacheNode *last; +}; + +typedef struct DF_RunTLSBaseCache DF_RunTLSBaseCache; +struct DF_RunTLSBaseCache +{ + Arena *arena; + U64 slots_count; + DF_RunTLSBaseCacheSlot *slots; +}; + //- rjf: per-run locals cache typedef struct DF_RunLocalsCacheNode DF_RunLocalsCacheNode; @@ -1108,6 +1136,9 @@ struct DF_State U64 unwind_cache_reggen_idx; U64 unwind_cache_memgen_idx; DF_RunUnwindCache unwind_cache; + U64 tls_base_cache_reggen_idx; + U64 tls_base_cache_memgen_idx; + DF_RunTLSBaseCache tls_base_cache; U64 locals_cache_reggen_idx; DF_RunLocalsCache locals_cache; U64 member_cache_reggen_idx; @@ -1512,7 +1543,7 @@ internal U64 df_type_num_from_binary_name(DF_Entity *binary, String8 name); //- rjf: thread info extraction helpers internal DF_Entity *df_module_from_process_vaddr(DF_Entity *process, U64 vaddr); internal DF_Entity *df_module_from_thread(DF_Entity *thread); -internal U64 df_tls_base_vaddr_from_thread(DF_Entity *thread); +internal U64 df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr); internal Architecture df_architecture_from_entity(DF_Entity *entity); internal CTRL_Unwind df_push_unwind_from_thread(Arena *arena, DF_Entity *thread); internal U64 df_rip_from_thread(DF_Entity *thread); @@ -1647,6 +1678,7 @@ internal DF_EntityList df_push_active_target_list(Arena *arena); internal CTRL_Unwind df_query_cached_unwind_from_thread(DF_Entity *thread); internal U64 df_query_cached_rip_from_thread(DF_Entity *thread); internal U64 df_query_cached_rip_from_thread_unwind(DF_Entity *thread, U64 unwind_count); +internal U64 df_query_cached_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64 rip_vaddr); internal EVAL_String2NumMap *df_query_cached_locals_map_from_binary_voff(DF_Entity *binary, U64 voff); internal EVAL_String2NumMap *df_query_cached_member_map_from_binary_voff(DF_Entity *binary, U64 voff); diff --git a/src/df/gfx/df_gfx.c b/src/df/gfx/df_gfx.c index a2f76343..e0089233 100644 --- a/src/df/gfx/df_gfx.c +++ b/src/df/gfx/df_gfx.c @@ -8750,8 +8750,9 @@ df_entity_tooltips(DF_Entity *entity) } internal void -df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *name_matches) +df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *name_matches, String8 fuzzy_query) { + ProfBeginFunction(); Temp scratch = scratch_begin(0, 0); if(entity->kind == DF_EntityKind_Thread) { @@ -8875,8 +8876,9 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *nam CTRL_Unwind unwind = df_query_cached_unwind_from_thread(entity); DF_Entity *process = df_entity_ancestor_from_kind(entity, DF_EntityKind_Process); U64 idx = 0; + U64 limit = 3; ui_spacer(ui_em(1.f, 1.f)); - for(CTRL_UnwindFrame *f = unwind.last; f != 0 && idx < 3; f = f->prev) + for(CTRL_UnwindFrame *f = unwind.last; f != 0 && idx < limit; f = f->prev) { U64 rip_vaddr = f->rip; DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr); @@ -8885,12 +8887,25 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *nam String8 procedure_name = df_symbol_name_from_binary_voff(scratch.arena, binary, rip_voff); if(procedure_name.size != 0) { + FuzzyMatchRangeList fuzzy_matches = {0}; + if(fuzzy_query.size != 0) + { + fuzzy_matches = fuzzy_match_find(scratch.arena, fuzzy_query, procedure_name); + } if(idx != 0) { UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) UI_PrefWidth(ui_em(2.f, 1.f)) ui_label(str8_lit(">")); } - UI_PrefWidth(ui_text_dim(10.f, 0.f)) ui_label(procedure_name); + UI_PrefWidth(ui_text_dim(10.f, 0.f)) + { + UI_Box *label_box = ui_label(procedure_name).box; + ui_box_equip_fuzzy_match_ranges(label_box, &fuzzy_matches); + } idx += 1; + if(idx == limit) + { + UI_TextColor(df_rgba_from_theme_color(DF_ThemeColor_WeakText)) UI_PrefWidth(ui_text_dim(10.f, 1.f)) ui_label(str8_lit("> ...")); + } } } } @@ -8938,6 +8953,7 @@ df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *nam } } scratch_end(scratch); + ProfEnd(); } internal void diff --git a/src/df/gfx/df_gfx.h b/src/df/gfx/df_gfx.h index cac9faca..e8f701c3 100644 --- a/src/df/gfx/df_gfx.h +++ b/src/df/gfx/df_gfx.h @@ -1029,7 +1029,7 @@ internal void df_cmd_list_menu_buttons(DF_Window *ws, U64 count, DF_CoreCmdKind internal UI_Signal df_icon_button(DF_IconKind kind, FuzzyMatchRangeList *matches, String8 string); internal UI_Signal df_icon_buttonf(DF_IconKind kind, FuzzyMatchRangeList *matches, char *fmt, ...); internal void df_entity_tooltips(DF_Entity *entity); -internal void df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *name_matches); +internal void df_entity_desc_button(DF_Window *ws, DF_Entity *entity, FuzzyMatchRangeList *name_matches, String8 fuzzy_query); internal void df_entity_src_loc_button(DF_Window *ws, DF_Entity *entity, TxtPt point); //////////////////////////////// diff --git a/src/df/gfx/df_views.c b/src/df/gfx/df_views.c index a04e0a6f..2e3a46d6 100644 --- a/src/df/gfx/df_views.c +++ b/src/df/gfx/df_views.c @@ -3390,7 +3390,7 @@ DF_VIEW_UI_FUNCTION_DEF(Targets) // rjf: target name UI_WidthFill UI_FocusHot((row_selected && cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, target, &targets.v[row_idx-1].matches); + df_entity_desc_button(ws, target, &targets.v[row_idx-1].matches, query); } // rjf: controls @@ -3815,48 +3815,51 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler) //- rjf: produce list of items; no query -> all entities, in tree; query -> only show threads DF_EntityFuzzyItemArray items = {0}; - if(query.size == 0) + ProfScope("query -> entities") { - //- rjf: build flat array of entities, arranged into row order - DF_EntityArray entities = {0}; + if(query.size == 0) { - entities.count = machines.count+processes.count+threads.count; - entities.v = push_array_no_zero(scratch.arena, DF_Entity *, entities.count); - U64 idx = 0; - for(DF_EntityNode *machine_n = machines.first; machine_n != 0; machine_n = machine_n->next) + //- rjf: build flat array of entities, arranged into row order + DF_EntityArray entities = {0}; { - DF_Entity *machine = machine_n->entity; - entities.v[idx] = machine; - idx += 1; - for(DF_EntityNode *process_n = processes.first; process_n != 0; process_n = process_n->next) + entities.count = machines.count+processes.count+threads.count; + entities.v = push_array_no_zero(scratch.arena, DF_Entity *, entities.count); + U64 idx = 0; + for(DF_EntityNode *machine_n = machines.first; machine_n != 0; machine_n = machine_n->next) { - DF_Entity *process = process_n->entity; - if(df_entity_ancestor_from_kind(process, DF_EntityKind_Machine) != machine) - { - continue; - } - entities.v[idx] = process; + DF_Entity *machine = machine_n->entity; + entities.v[idx] = machine; idx += 1; - for(DF_EntityNode *thread_n = threads.first; thread_n != 0; thread_n = thread_n->next) + for(DF_EntityNode *process_n = processes.first; process_n != 0; process_n = process_n->next) { - DF_Entity *thread = thread_n->entity; - if(df_entity_ancestor_from_kind(thread, DF_EntityKind_Process) != process) + DF_Entity *process = process_n->entity; + if(df_entity_ancestor_from_kind(process, DF_EntityKind_Machine) != machine) { continue; } - entities.v[idx] = thread; + entities.v[idx] = process; idx += 1; + for(DF_EntityNode *thread_n = threads.first; thread_n != 0; thread_n = thread_n->next) + { + DF_Entity *thread = thread_n->entity; + if(df_entity_ancestor_from_kind(thread, DF_EntityKind_Process) != process) + { + continue; + } + entities.v[idx] = thread; + idx += 1; + } } } } + + //- rjf: entities -> fuzzy-filtered entities + items = df_entity_fuzzy_item_array_from_entity_array_needle(scratch.arena, &entities, query); + } + else + { + items = df_entity_fuzzy_item_array_from_entity_list_needle(scratch.arena, &threads, query); } - - //- rjf: entities -> fuzzy-filtered entities - items = df_entity_fuzzy_item_array_from_entity_array_needle(scratch.arena, &entities, query); - } - else - { - items = df_entity_fuzzy_item_array_from_entity_list_needle(scratch.arena, &threads, query); } //- rjf: selected column/entity -> selected cursor @@ -3945,7 +3948,7 @@ DF_VIEW_UI_FUNCTION_DEF(Scheduler) UI_TableCellSized(ui_pct(1, 0)) UI_FocusHot((row_is_selected && desc_col_rng.min <= cursor.x && cursor.x <= desc_col_rng.max) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, entity, &items.v[idx].matches); + df_entity_desc_button(ws, entity, &items.v[idx].matches, query); } switch(entity->kind) { @@ -4169,7 +4172,7 @@ DF_VIEW_UI_FUNCTION_DEF(CallStack) } else { - df_entity_desc_button(ws, module, 0); + df_entity_desc_button(ws, module, 0, str8_zero()); } } @@ -4430,7 +4433,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules) { UI_TableCellSized(ui_pct(1, 0)) UI_FocusHot((row_is_selected) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, entity, &items.v[idx].matches); + df_entity_desc_button(ws, entity, &items.v[idx].matches, query); } } idx_in_process = 0; @@ -4444,7 +4447,7 @@ DF_VIEW_UI_FUNCTION_DEF(Modules) } UI_TableCell UI_FocusHot((row_is_selected && cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, entity, &items.v[idx].matches); + df_entity_desc_button(ws, entity, &items.v[idx].matches, query); } UI_TableCell UI_Font(df_font_from_slot(DF_FontSlot_Code)) UI_FocusHot((row_is_selected && cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { @@ -8355,7 +8358,7 @@ DF_VIEW_UI_FUNCTION_DEF(Breakpoints) } UI_TableCell UI_FocusHot((row_is_selected && cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, entity, &entities.v[idx-1].matches); + df_entity_desc_button(ws, entity, &entities.v[idx-1].matches, query); } UI_TableCell UI_FocusHot((row_is_selected && cursor.x == 2) ? UI_FocusKind_On : UI_FocusKind_Off) { @@ -8516,7 +8519,7 @@ DF_VIEW_UI_FUNCTION_DEF(WatchPins) { UI_TableCell UI_FocusHot((row_is_selected && cursor.x == 0) ? UI_FocusKind_On : UI_FocusKind_Off) { - df_entity_desc_button(ws, entity, &entities.v[idx-1].matches); + df_entity_desc_button(ws, entity, &entities.v[idx-1].matches, query); } UI_TableCell UI_FocusHot((row_is_selected && cursor.x == 1) ? UI_FocusKind_On : UI_FocusKind_Off) { diff --git a/src/raddbg/raddbg.h b/src/raddbg/raddbg.h index b58a910e..54cdf7e7 100644 --- a/src/raddbg/raddbg.h +++ b/src/raddbg/raddbg.h @@ -281,6 +281,7 @@ // [ ] Fancy View Rules // [ ] table column boundaries should be checked against *AFTER* table // contents, not before +// [ ] `array:(x, y)` - multidimensional array // [ ] `text[:lang]` - interpret memory as text, in lang `lang` // [ ] `disasm:arch` - interpret memory as machine code for isa `arch` // [ ] `memory` - view memory in usual memory hex-editor view @@ -306,6 +307,7 @@ // // [ ] @feature processor/data breakpoints // [ ] @feature automatically snap to search matches when searching source files +// [ ] automatically start search query with selected text // [ ] @feature entity views: filtering & reordering ////////////////////////////////