From 132751777fc4bd0aeb27594f3de13c96c2153acd Mon Sep 17 00:00:00 2001 From: Ryan Fleury Date: Mon, 8 Jun 2026 21:06:44 -0700 Subject: [PATCH] eliminate unnecessary info in debug engine entity abstraction / demon events; adjust symbol server / debug info loading such that the debug info loader is the one who decides to kick off downloads based on presence in cache path; use cache path as key, unpack info for download requests --- project.raddbg | 8 +- src/dbg_engine/dbg_engine_core.h | 16 +- src/dbg_engine/dbg_engine_ctrl.c | 43 +---- src/dbg_engine/dbg_engine_ctrl.h | 1 - src/dbg_engine/dbg_engine_user.c | 125 ------------- src/dbg_engine/dbg_engine_user.h | 9 +- src/dbg_info/dbg_info.c | 12 +- src/dbg_info/dbg_info.h | 1 - src/http/http.c | 18 -- src/http/http.h | 5 - src/raddbg/raddbg_core.c | 8 +- src/raddbg/raddbg_views.c | 2 +- src/raddbg/raddbg_widgets.c | 59 ++++--- src/symbol_server/symbol_server.h | 2 + src/symbol_server/symbol_server_stub.c | 11 ++ src/win32/http/win32_http.c | 16 +- src/win32/http/win32_http.h | 8 + src/win32/symbol_server/win32_symbol_server.c | 164 +++++++++++------- src/win32/symbol_server/win32_symbol_server.h | 9 +- 19 files changed, 199 insertions(+), 318 deletions(-) diff --git a/project.raddbg b/project.raddbg index c9bf248d..76b56383 100644 --- a/project.raddbg +++ b/project.raddbg @@ -50,6 +50,12 @@ target: target: { executable: "build/raddbg.exe" - working_directory: "build/" + working_directory: build arguments: "--bin --rdi C:\\SymbolCache\\ntdll.pdb\\180BF1B90AA75697D0EFEA5E5630AC7E1\\ntdll.pdb --thread_count=1" } +target: +{ + executable: "build/raddbg.exe" + working_directory: build + arguments: "--bin --rdi --thread_count=1 C:/SymbolCache/kernelbase.pdb/53B51385668728BA4297C9C78EEC92DD1/kernelbase.pdb" +} diff --git a/src/dbg_engine/dbg_engine_core.h b/src/dbg_engine/dbg_engine_core.h index 26a90c6e..7dae3be5 100644 --- a/src/dbg_engine/dbg_engine_core.h +++ b/src/dbg_engine/dbg_engine_core.h @@ -102,17 +102,6 @@ struct D_BreakpointList U64 count; }; -//////////////////////////////// -//~ Dynamic Linker Types - -typedef U32 D_TlsModel; -enum -{ - D_TlsModel_Null, - D_TlsModel_WinodwsNt, - D_TlsModel_Gnu -}; - //////////////////////////////// //~ rjf: Entity Types @@ -136,11 +125,8 @@ struct D_Entity U64 timestamp; D_BreakpointFlags bp_flags; String8 string; - D_TlsModel tls_model; - U64 tls_index; - U64 tls_offset; U64 tls_root_vaddr; - OperatingSystem target_os; + OperatingSystem os; D_MsgID src_msg_id; }; diff --git a/src/dbg_engine/dbg_engine_ctrl.c b/src/dbg_engine/dbg_engine_ctrl.c index 98a49899..4e7b78d6 100644 --- a/src/dbg_engine/dbg_engine_ctrl.c +++ b/src/dbg_engine/dbg_engine_ctrl.c @@ -42,20 +42,6 @@ d_exception_kind_from_dmn(DMN_ExceptionKind kind) return result; } -internal D_TlsModel -d_tls_model_from_dmn(DMN_TlsModel type) -{ - D_TlsModel result = D_TlsModel_Null; - switch(type) - { - default:{}break; - case DMN_TlsModel_Null: {result = D_TlsModel_Null;}break; - case DMN_TlsModel_WinodwsNt: {result = D_TlsModel_WinodwsNt;}break; - case DMN_TlsModel_Gnu: {result = D_TlsModel_Gnu;}break; - } - return result; -} - internal String8 d_string_from_event_kind(D_EventKind kind) { @@ -645,8 +631,7 @@ d_serialized_string_from_event(Arena *arena, D_Event *event, U64 max) str8_serial_push_struct(scratch.arena, &srl, &event->exception_code); str8_serial_push_struct(scratch.arena, &srl, &event->rgba); str8_serial_push_struct(scratch.arena, &srl, &event->bp_flags); - str8_serial_push_struct(scratch.arena, &srl, &event->target_os); - str8_serial_push_struct(scratch.arena, &srl, &event->tls_model); + str8_serial_push_struct(scratch.arena, &srl, &event->os); str8_serial_push_struct(scratch.arena, &srl, &event->tls_index); str8_serial_push_struct(scratch.arena, &srl, &event->tls_offset); String8 string = event->string; @@ -682,8 +667,7 @@ d_event_from_serialized_string(Arena *arena, String8 string) read_off += str8_deserial_read_struct(string, read_off, &event.exception_code); read_off += str8_deserial_read_struct(string, read_off, &event.rgba); read_off += str8_deserial_read_struct(string, read_off, &event.bp_flags); - read_off += str8_deserial_read_struct(string, read_off, &event.target_os); - read_off += str8_deserial_read_struct(string, read_off, &event.tls_model); + read_off += str8_deserial_read_struct(string, read_off, &event.os); read_off += str8_deserial_read_struct(string, read_off, &event.tls_index); read_off += str8_deserial_read_struct(string, read_off, &event.tls_offset); read_off += str8_deserial_read_struct(string, read_off, &event.string.size); @@ -1300,8 +1284,7 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) if(machine != &d_entity_nil) { D_Entity *process = d_entity_alloc(store, machine, D_EntityKind_Process, event->arch, event->entity, (U64)event->entity_id); - process->tls_model = event->tls_model; - process->target_os = event->target_os; + process->os = event->os; process->src_msg_id = event->msg_id; d_entity_equip_string(store, process, event->string); } @@ -1437,8 +1420,6 @@ d_entity_store_apply_events(D_EntityCtxRWStore *store, D_EventList *list) d_entity_equip_string(store, module, event->string); module->timestamp = event->timestamp; module->vaddr_range = event->vaddr_rng; - module->tls_index = event->tls_index; - module->tls_offset = event->tls_offset; D_Entity *first_module = d_entity_child_from_kind(process, D_EntityKind_Module); if(first_module == module && process->string.size == 0) { @@ -1565,7 +1546,7 @@ d_thread_read_reg_block(D_Handle handle, void *reg_block) if(thread_ctx != 0) { Arch arch = thread->arch; - OperatingSystem os = process->target_os; + OperatingSystem os = process->os; result = arch_os_write_reg_block_from_thread_ctx(arch, os, reg_block, thread_ctx); } } @@ -2683,14 +2664,12 @@ d_ctrl_thread__module_open(D_Handle process, D_Handle module, U64 base_vaddr, DM } ////////////////////////////// - //- rjf: no found debug info path -> try to fall back on symbol server + //- rjf: no found debug info path -> try to fall back on symbol server cache path // -#if 0 if(initial_debug_info_path.size == 0) { initial_debug_info_path = smsv_local_path_from_key(arena, str8_skip_last_slash(module_info->debug_info_path), module_info->debug_info_guid, module_info->debug_info_age); } -#endif ////////////////////////////// //- rjf: write 1 at attachment marker, to signify attachment @@ -3154,8 +3133,7 @@ d_ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, D_Msg *msg, D out_evt->entity = d_handle_from_dmn(D_MachineID_Local, event->process); out_evt->arch = event->arch; out_evt->entity_id = event->code; - out_evt->tls_model = d_tls_model_from_dmn(event->tls_model); - out_evt->target_os = OperatingSystem_CURRENT; // TODO: operating system of the remote target machine + out_evt->os = OperatingSystem_CURRENT; // TODO: operating system of the remote target machine d_ctrl_state->process_counter += 1; }break; case DMN_EventKind_CreateThread: @@ -3985,7 +3963,7 @@ d_ctrl_thread__open_crash_dump(DMN_CtrlCtx *ctrl_ctx, D_Msg *msg) evt->msg_id = msg->msg_id; evt->entity = process; evt->arch = process_arch; - evt->target_os = process_os; + evt->os = process_os; evt->string = path; } @@ -6064,11 +6042,8 @@ d_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U6 dst_e->stack_base = src_e->stack_base; dst_e->timestamp = src_e->timestamp; dst_e->bp_flags = src_e->bp_flags; - dst_e->string = push_str8_copy(scratch.arena, src_e->string); - dst_e->tls_index = src_e->tls_index; - dst_e->tls_offset = src_e->tls_offset; - dst_e->target_os = src_e->target_os; - dst_e->tls_model = src_e->tls_model; + dst_e->string = str8_copy(scratch.arena, src_e->string); + dst_e->os = src_e->os; } if(dst_parent == &d_entity_nil) { diff --git a/src/dbg_engine/dbg_engine_ctrl.h b/src/dbg_engine/dbg_engine_ctrl.h index 1617dfb6..eb2f35e9 100644 --- a/src/dbg_engine/dbg_engine_ctrl.h +++ b/src/dbg_engine/dbg_engine_ctrl.h @@ -404,7 +404,6 @@ read_only global D_ModuleInfo d_module_info_nil = {0}; internal U64 d_hash_from_handle(D_Handle handle); internal D_EventCause d_event_cause_from_dmn_event_kind(DMN_EventKind event_kind); internal D_ExceptionKind d_exception_kind_from_dmn(DMN_ExceptionKind kind); -internal D_TlsModel d_tls_model_from_dmn(DMN_TlsModel type); internal String8 d_string_from_event_kind(D_EventKind kind); internal String8 d_string_from_msg_kind(D_MsgKind kind); internal D_EntityKind d_entity_kind_from_string(String8 string); diff --git a/src/dbg_engine/dbg_engine_user.c b/src/dbg_engine/dbg_engine_user.c index 91e55c68..7c7ba17a 100644 --- a/src/dbg_engine/dbg_engine_user.c +++ b/src/dbg_engine/dbg_engine_user.c @@ -1326,80 +1326,6 @@ d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num, U return list; } -//////////////////////////////// -//~ rjf: Process/Thread/Module Info Lookups - -internal U64 -d_tls_base_vaddr_from_process_root_rip(D_Entity *process, U64 root_vaddr, U64 rip_vaddr) -{ - ProfBeginFunction(); - U64 base_vaddr = 0; - if(!d_ctrl_targets_running()) - { - Temp scratch = scratch_begin(0, 0); - - //- rjf: unpack module info - D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr); - U64 addr_size = byte_size_from_arch(process->arch); - - switch(process->tls_model) - { - case D_TlsModel_Null: {}break; - case D_TlsModel_WinodwsNt: - { - // read thread local base pointer out of TEB - U64 thread_local_base = root_vaddr; - U64 tls_addr_array = 0; - D_ProcessMemorySlice tls_addr_array_slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(thread_local_base, thread_local_base + addr_size), 0, 0); - String8 tls_array_vaddr_data = tls_addr_array_slice.data; - if(tls_array_vaddr_data.size == addr_size) - { - U64 tls_array_vaddr = 0; - MemoryCopyStr8(&tls_array_vaddr, tls_array_vaddr_data); - - // read thread local storage pointer (array of TLS pointers, one per module) - U64 tls_ptr_vaddr = tls_array_vaddr + module->tls_index * addr_size; - D_ProcessMemorySlice result_slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(tls_ptr_vaddr, tls_ptr_vaddr + addr_size), 0, 0); - String8 result_data = result_slice.data; - if(result_data.size == addr_size) - { - MemoryCopyStr8(&base_vaddr, result_data); - } - } - }break; - case D_TlsModel_Gnu: - { - if(module->tls_index > 0) // zero is reserved for the generation counter - { - // read dynamic thread vector pointer (one per dynamic module) - U64 dtv_base = root_vaddr; - U64 dtv_size = addr_size * 2; // union dtv { size_t counter; struct dtv_pointer { void *val, *to_free; }; }; - U64 dtv_pointer_vaddr = dtv_base + module->tls_index * dtv_size; - D_ProcessMemorySlice dtv_pointer_slice = d_process_memory_slice_from_vaddr_range(scratch.arena, process->handle, r1u64(dtv_pointer_vaddr, dtv_pointer_vaddr + dtv_size), 0, 0); - String8 dtv_pointer_data = dtv_pointer_slice.data; - if(dtv_pointer_data.size == dtv_size) - { - U64 dtv_pointer = 0; - MemoryCopyStr8(&dtv_pointer, dtv_pointer_data); - - // verify that TLS block was allocated - U64 tls_dtv_unallocated = addr_size == 4 ? max_U32 : max_U64; - if(dtv_pointer != tls_dtv_unallocated) - { - base_vaddr = dtv_pointer + module->tls_offset; // add tls_offset because DT_NEEDED modules share TLS block with the main exe - } - } - } - }break; - default: {InvalidPath;}break; - } - - scratch_end(scratch); - } - ProfEnd(); - return base_vaddr; -} - //////////////////////////////// //~ rjf: Target Controls @@ -1509,57 +1435,6 @@ d_query_cached_cfa_from_thread_unwind(D_Entity *thread, U64 unwind_count) return cfa; } -internal U64 -d_query_cached_tls_base_vaddr_from_process_root_rip(D_Entity *process, U64 root_vaddr, U64 rip_vaddr) -{ - U64 result = 0; - for(U64 cache_idx = 0; cache_idx < ArrayCount(d_user_state->tls_base_caches); cache_idx += 1) - { - D_RunTLSBaseCache *cache = &d_user_state->tls_base_caches[(d_user_state->tls_base_cache_gen+cache_idx)%ArrayCount(d_user_state->tls_base_caches)]; - if(cache_idx == 0 && cache->slots_count == 0) - { - cache->slots_count = 256; - cache->slots = push_array(cache->arena, D_RunTLSBaseCacheSlot, cache->slots_count); - } - else if(cache->slots_count == 0) - { - break; - } - D_Handle handle = process->handle; - U64 hash = d_hash_from_seed_string(d_hash_from_string(str8_struct(&handle)), str8_struct(&rip_vaddr)); - U64 slot_idx = hash%cache->slots_count; - D_RunTLSBaseCacheSlot *slot = &cache->slots[slot_idx]; - D_RunTLSBaseCacheNode *node = 0; - for(D_RunTLSBaseCacheNode *n = slot->first; n != 0; n = n->hash_next) - { - if(d_handle_match(n->process, handle) && n->root_vaddr == root_vaddr && n->rip_vaddr == rip_vaddr) - { - node = n; - break; - } - } - if(node == 0) - { - U64 tls_base_vaddr = d_tls_base_vaddr_from_process_root_rip(process, root_vaddr, rip_vaddr); - if(tls_base_vaddr != 0) - { - node = push_array(cache->arena, D_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 = tls_base_vaddr; - } - } - if(node != 0 && node->tls_base_vaddr != 0) - { - result = node->tls_base_vaddr; - break; - } - } - return result; -} - internal E_String2NumMap * d_query_cached_locals_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff) { diff --git a/src/dbg_engine/dbg_engine_user.h b/src/dbg_engine/dbg_engine_user.h index ae9a95d7..0236384d 100644 --- a/src/dbg_engine/dbg_engine_user.h +++ b/src/dbg_engine/dbg_engine_user.h @@ -313,8 +313,7 @@ struct D_Event U32 rgba; D_BreakpointFlags bp_flags; String8 string; - OperatingSystem target_os; - D_TlsModel tls_model; + OperatingSystem os; }; typedef struct D_EventNode D_EventNode; @@ -443,11 +442,6 @@ internal D_LineListArray d_lines_array_from_file_path_line_range(Arena *arena, S internal D_LineList d_lines_from_dbgi_key_file_path_line_num(Arena *arena, DI_Key dbgi_key, String8 file_path, S64 line_num, U64 max_voffs_per_line); internal D_LineList d_lines_from_file_path_line_num(Arena *arena, String8 file_path, S64 line_num, U64 max_voffs_per_line); -//////////////////////////////// -//~ rjf: Process/Thread/Module Info Lookups - -internal U64 d_tls_base_vaddr_from_process_root_rip(D_Entity *process, U64 root_vaddr, U64 rip_vaddr); - //////////////////////////////// //~ rjf: Target Controls @@ -473,7 +467,6 @@ internal DI_KeyList d_push_active_dbgi_key_list(Arena *arena); internal U64 d_query_cached_rip_from_thread(D_Entity *thread); internal U64 d_query_cached_rip_from_thread_unwind(D_Entity *thread, U64 unwind_count); internal U64 d_query_cached_cfa_from_thread_unwind(D_Entity *thread, U64 unwind_count); -internal U64 d_query_cached_tls_base_vaddr_from_process_root_rip(D_Entity *process, U64 root_vaddr, U64 rip_vaddr); internal E_String2NumMap *d_query_cached_locals_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff); internal E_String2NumMap *d_query_cached_member_map_from_dbgi_key_voff(DI_Key dbgi_key, U64 voff); diff --git a/src/dbg_info/dbg_info.c b/src/dbg_info/dbg_info.c index 30acce03..79c3d77b 100644 --- a/src/dbg_info/dbg_info.c +++ b/src/dbg_info/dbg_info.c @@ -680,16 +680,22 @@ di_async_tick(void) } } - //- rjf: check with the symbol server to see if we are actively downloading O.G. + //- rjf: kick off symbol server download, or check to see if we are actively downloading O.G. B32 og_is_downloading = 0; { B32 file_is_present = (properties_from_file_path(og_path).modified != 0); if(!file_is_present) { - SMSV_Status status = smsv_status_from_local_path(og_path); - if(status == SMSV_Status_Pending) + String8 symbol_cache_path = smsv_cache_path(); + if(str8_match(symbol_cache_path, og_path, StringMatchFlag_RightSideSloppy|StringMatchFlag_SlashInsensitive)) { og_is_downloading = 1; + smsv_fill_local_path(og_path); + SMSV_Status status = smsv_status_from_local_path(og_path); + if(status == SMSV_Status_Null) + { + og_is_downloading = 0; + } } } } diff --git a/src/dbg_info/dbg_info.h b/src/dbg_info/dbg_info.h index 096d0b2a..0cff1bea 100644 --- a/src/dbg_info/dbg_info.h +++ b/src/dbg_info/dbg_info.h @@ -140,7 +140,6 @@ struct DI_LoadTask B32 og_analyzed; B32 og_is_rdi; U64 og_size; - B32 og_is_downloading; B32 rdi_analyzed; B32 rdi_is_stale; diff --git a/src/http/http.c b/src/http/http.c index 5358979b..db9ec6ca 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -31,21 +31,3 @@ http_status_kind_from_code(HTTP_StatusCode code) } return kind; } - -//////////////////////////////////////////////////////////////// -//~ rjf: Synchronous Request Helper - -internal HTTP_Response -http_request(Arena *arena, HTTP_RequestParams *params) -{ - HTTP_Response response = {0}; - Temp scratch = scratch_begin(&arena, 1); - GuardedRing *gr = guarded_ring_alloc(scratch.arena, KB(64)); - { - http_push_request(gr, params, max_U64); - http_pop_response(arena, gr, &response, max_U64); - } - guarded_ring_release(gr); - scratch_end(scratch); - return response; -} diff --git a/src/http/http.h b/src/http/http.h index a6cb3d96..24f73a9f 100644 --- a/src/http/http.h +++ b/src/http/http.h @@ -156,11 +156,6 @@ struct HTTP_Response internal HTTP_StatusKind http_status_kind_from_code(HTTP_StatusCode code); -//////////////////////////////////////////////////////////////// -//~ rjf: Synchronous Request Helper - -internal HTTP_Response http_request(Arena *arena, HTTP_RequestParams *params); - //////////////////////////////////////////////////////////////// //~ rjf: @per_os_impl Top-Level Layer Calls diff --git a/src/raddbg/raddbg_core.c b/src/raddbg/raddbg_core.c index 3e5b5ed4..2ad9f1c4 100644 --- a/src/raddbg/raddbg_core.c +++ b/src/raddbg/raddbg_core.c @@ -13066,7 +13066,6 @@ rd_frame(void) str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " exception_code: 0x%I64x\n", (U64)evt.exception_code); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " bp_flags: 0x%I64x\n", (U64)evt.bp_flags); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " string: \"%S\"\n", escaped_from_raw_str8(scratch.arena, evt.string)); - str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " tls_model: 0x%I64x\n", evt.tls_model); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " explanation: \"%S\"\n", escaped_from_raw_str8(scratch.arena, explanation_string)); str8_list_pushf(rd_state->cmd_output_arena, &rd_state->cmd_outputs, " }\n"); } @@ -17393,14 +17392,13 @@ rd_frame(void) } } }break; - case D_EventKind_NewModule: + case D_EventKind_ModuleDebugInfoPathChange: { D_Entity *module = d_entity_from_handle(evt->entity); D_Entity *debug_info_path = d_entity_child_from_kind(module, D_EntityKind_DebugInfoPath); String8 new_path = debug_info_path->string; - B32 file_exists = file_path_exists(new_path); - B32 file_is_pending = (!file_exists ? smsv_status_from_local_path(new_path) == SMSV_Status_Pending : 0); - if(new_path.size != 0 && (file_exists || file_is_pending)) + B32 file_exists = 1; // file_path_exists(new_path); + if(new_path.size != 0 && file_exists) { CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info")); B32 path_found = 0; diff --git a/src/raddbg/raddbg_views.c b/src/raddbg/raddbg_views.c index 6dd2aab3..73411fc2 100644 --- a/src/raddbg/raddbg_views.c +++ b/src/raddbg/raddbg_views.c @@ -2268,7 +2268,7 @@ RD_VIEW_UI_FUNCTION_DEF(text) default: { String8 checksum_value = rd_checksum_value_from_hash_kind(scratch.arena, hash, checksum_kind); - file_is_out_of_date = !memory_is_zero(checksum_value.str, checksum_value.size) && !str8_match(checksum_value, checksum_expected, 0); + file_is_out_of_date = checksum_expected.size != 0 && !memory_is_zero(checksum_value.str, checksum_value.size) && !str8_match(checksum_value, checksum_expected, 0); }break; case RDI_ChecksumKind_Timestamp: { diff --git a/src/raddbg/raddbg_widgets.c b/src/raddbg/raddbg_widgets.c index 3fceac67..fa235759 100644 --- a/src/raddbg/raddbg_widgets.c +++ b/src/raddbg/raddbg_widgets.c @@ -562,39 +562,50 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, D_Entity *entity, B32 include_extr ARCH_Info *arch_info = arch_info_from_arch(entity->arch); B32 call_stack_high_priority = d_handle_match(entity->handle, rd_base_regs()->thread); D_CallStack call_stack = d_call_stack_from_thread(access, entity->handle, call_stack_high_priority, call_stack_high_priority ? rd_state->frame_eval_memread_endt_us : 0); + B32 did_first_in_main_module = 0; B32 did_first_known = 0; + U64 num_pushed = 0; + D_Entity *first_module = d_entity_child_from_kind(process, D_EntityKind_Module); for(U64 idx = 0, limit = 10; - idx < call_stack.frames_count && idx < limit; + idx < call_stack.frames_count && num_pushed < limit; idx += 1) { D_CallStackFrame *f = &call_stack.frames[call_stack.frames_count - 1 - idx]; - U64 rip_vaddr = arch_ip_from_reg_block(arch_info, f->regs); - D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr); - U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr); - String8 name = {0}; + if(f->inline_depth == 0) { - DI_Key dbgi_key = d_dbgi_key_from_module(module); - RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); - if(rdi != &rdi_parsed_nil) + U64 rip_vaddr = arch_ip_from_reg_block(arch_info, f->regs); + D_Entity *module = d_module_from_process_vaddr(process, rip_vaddr); + if(did_first_in_main_module || module == first_module) { - RDI_Symbol *procedure = rdi_procedure_from_voff(rdi, rip_voff); - name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); - name = push_str8_copy(arena, name); - } - if(name.size == 0 && did_first_known) - { - name = str8_lit("???"); - } - if(name.size != 0) - { - did_first_known = 1; - dr_fstrs_push_new(arena, &result, ¶ms, name, .size = extras_size, .color = symbol_color); - if(idx+1 < call_stack.frames_count) + did_first_in_main_module = 1; + U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr); + String8 name = {0}; { - dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" > "), .color = secondary_color, .size = extras_size); - if(idx+1 == limit) + DI_Key dbgi_key = d_dbgi_key_from_module(module); + RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0); + if(rdi != &rdi_parsed_nil) { - dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("..."), .color = secondary_color, .size = extras_size); + RDI_Symbol *procedure = rdi_procedure_from_voff(rdi, rip_voff); + name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size); + name = push_str8_copy(arena, name); + } + if(name.size == 0 && did_first_known) + { + name = str8_lit("???"); + } + if(name.size != 0) + { + did_first_known = 1; + num_pushed += 1; + dr_fstrs_push_new(arena, &result, ¶ms, name, .size = extras_size, .color = symbol_color); + if(idx+1 < call_stack.frames_count) + { + dr_fstrs_push_new(arena, &result, ¶ms, str8_lit(" > "), .color = secondary_color, .size = extras_size); + if(num_pushed+1 == limit) + { + dr_fstrs_push_new(arena, &result, ¶ms, str8_lit("..."), .color = secondary_color, .size = extras_size); + } + } } } } diff --git a/src/symbol_server/symbol_server.h b/src/symbol_server/symbol_server.h index b0f38b5d..f41b9cc2 100644 --- a/src/symbol_server/symbol_server.h +++ b/src/symbol_server/symbol_server.h @@ -13,7 +13,9 @@ SMSV_Status; internal void smsv_init(void); internal void smsv_async_tick(void); +internal String8 smsv_cache_path(void); internal String8 smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age); +internal void smsv_fill_local_path(String8 path); internal SMSV_Status smsv_status_from_local_path(String8 path); #endif // SYMBOL_SERVER_H diff --git a/src/symbol_server/symbol_server_stub.c b/src/symbol_server/symbol_server_stub.c index db1e737b..bbd71e35 100644 --- a/src/symbol_server/symbol_server_stub.c +++ b/src/symbol_server/symbol_server_stub.c @@ -11,12 +11,23 @@ smsv_async_tick(void) { } +internal String8 +smsv_cache_path(void) +{ + return s(""); +} + internal String8 smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age) { return s(""); } +internal void +smsv_fill_local_path(String8 path) +{ +} + internal SMSV_Status smsv_status_from_local_path(String8 path) { diff --git a/src/win32/http/win32_http.c b/src/win32/http/win32_http.c index 10239c31..0f6c3059 100644 --- a/src/win32/http/win32_http.c +++ b/src/win32/http/win32_http.c @@ -390,20 +390,20 @@ http_async_tick(void) } // rjf: push this record + B32 push_failed = 0; { - // TODO(rjf): can't wait here technically, because we might be waiting for other - // work in the async threads to pop! so we'll just deadlock right here. two options: - // - // (a) http requests need to be on another timeline - // (b) we need to prepare for this to fail & batch it up or something. - // RingGuard g = guarded_ring_open(req->out_ring); - guarded_ring_write_string_or_wait(&g, record_data, max_U64); + if(!guarded_ring_write_string_or_wait(&g, record_data, 0)) + { + push_failed = 1; + String8 unpushed_body_piece = str8_substr(body, r1u64(off, next_off)); + str8_list_push(req->arena, &req->finished_body_pieces, str8_copy(req->arena, unpushed_body_piece)); + } guarded_ring_close(&g); } // rjf: cancel on no movement - if(next_off == off) + if(next_off == off || push_failed) { break; } diff --git a/src/win32/http/win32_http.h b/src/win32/http/win32_http.h index c95e4e61..75fe3d5c 100644 --- a/src/win32/http/win32_http.h +++ b/src/win32/http/win32_http.h @@ -41,6 +41,14 @@ struct W32_HTTP_Request U64 next_body_piece_size; }; +typedef struct W32_HTTP_Response W32_HTTP_Response; +struct W32_HTTP_Response +{ + W32_HTTP_Response *next; + GuardedRing *out_ring; + String8 record; +}; + typedef struct W32_HTTP_State W32_HTTP_State; struct W32_HTTP_State { diff --git a/src/win32/symbol_server/win32_symbol_server.c b/src/win32/symbol_server/win32_symbol_server.c index 7d0eaf29..9b54a49b 100644 --- a/src/win32/symbol_server/win32_symbol_server.c +++ b/src/win32/symbol_server/win32_symbol_server.c @@ -1,6 +1,36 @@ // Copyright (c) Epic Games Tools // Licensed under the MIT license (https://opensource.org/license/mit/) +//////////////////////////////// +//~ rjf: Helpers + +internal String8 +w32_smsv_dbg_name_from_local_path(String8 path) +{ + String8 result = str8_skip_last_slash(path); + return result; +} + +internal String8 +w32_smsv_unique_identifier_from_local_path(String8 path) +{ + U64 local_cache_path_pos = str8_find_needle(path, 0, w32_smsv_state->symbol_cache_path, StringMatchFlag_SlashInsensitive); + U64 first_slash_pos = str8_find_needle(path, local_cache_path_pos, s("/"), StringMatchFlag_SlashInsensitive); + String8 cache_relative_path = str8_skip(path, first_slash_pos); + U64 second_slash_pos = str8_find_needle(cache_relative_path, 0, s("/"), StringMatchFlag_SlashInsensitive); + String8 name_root = str8_skip(cache_relative_path, second_slash_pos+1); + U64 third_slash_pos = str8_find_needle(name_root, 0, s("/"), 0); + String8 name = str8_skip(name_root, third_slash_pos+1); + U64 fourth_slash_pos = str8_find_needle(name, 0, s("/"), StringMatchFlag_SlashInsensitive); + String8 unique_identifier = str8_skip(name, fourth_slash_pos+1); + U64 last_slash_pos = str8_find_needle(unique_identifier, 0, s("/"), StringMatchFlag_SlashInsensitive); + unique_identifier = str8_prefix(unique_identifier, last_slash_pos); + return unique_identifier; +} + +//////////////////////////////// +//~ rjf: Implementation + internal void smsv_init(void) { @@ -231,18 +261,13 @@ smsv_async_tick(void) if(server_url.size != 0) { task->status = W32_SMSV_TaskStatus_Requested; - Guid guid = task->guid; - U64 age = task->age; - String8 debug_info_unique_identifier = {0}; - { - debug_info_unique_identifier = str8f(scratch.arena, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%I64x", - guid.data1, guid.data2, guid.data3, guid.data4[0], guid.data4[1], guid.data4[2], guid.data4[3], guid.data4[4], guid.data4[5], guid.data4[6], guid.data4[7], age); - } + String8 dbg_name = w32_smsv_dbg_name_from_local_path(task->local_path); + String8 debug_info_unique_identifier = w32_smsv_unique_identifier_from_local_path(task->local_path); HTTP_RequestParams params = { .id = (U64)task, .method = HTTP_Method_Get, - .url = str8f(scratch.arena, "%S/%S/%S/%S", server_url, task->dbg_name, debug_info_unique_identifier, task->dbg_name), + .url = str8f(scratch.arena, "%S/%S/%S/%S", server_url, dbg_name, debug_info_unique_identifier, dbg_name), }; if(!http_push_request(w32_smsv_state->http_response_ring, ¶ms, 0)) { @@ -322,6 +347,12 @@ smsv_async_tick(void) scratch_end(scratch); } +internal String8 +smsv_cache_path(void) +{ + return w32_smsv_state->symbol_cache_path; +} + internal String8 smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age) { @@ -342,69 +373,70 @@ smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age) String8 path = str8f(scratch.arena, "%S/%S/%S/%S", symbol_cache_path, dbg_name, debug_info_unique_identifier, dbg_name); result = path_normalized_from_string(arena, path); } - - // rjf: determine if we already have this debug info stored locally - B32 already_cached_locally = (properties_from_file_path(result).modified != 0); - - // rjf: if not cached: record (local path -> download task) mapping - B32 task_is_new = 0; - U64 task_id = 0; - if(!already_cached_locally) - { - U64 hash = u64_hash_from_str8(result); - U64 slot_idx = hash%w32_smsv_state->task_slots_count; - W32_SMSV_TaskSlot *slot = &w32_smsv_state->task_slots[slot_idx]; - Stripe *stripe = stripe_from_slot_idx(&w32_smsv_state->task_stripes, slot_idx); - for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) - { - B32 already_exists = 0; - RWMutexScope(stripe->rw_mutex, write_mode) - { - W32_SMSV_Task *node = 0; - for(W32_SMSV_Task *n = slot->first; n != 0; n = n->next) - { - if(MemoryMatchStruct(&n->guid, &guid)) - { - already_exists = 1; - node = n; - break; - } - } - if(node == 0 && write_mode) - { - Arena *arena = arena_alloc(); - node = push_array(arena, W32_SMSV_Task, 1); - node->arena = arena; - node->local_path = str8_copy(arena, result); - node->dbg_name = str8_copy(arena, dbg_name); - node->guid = guid; - node->age = age; - DLLPushBack(slot->first, slot->last, node); - task_is_new = 1; - task_id = (U64)node; - } - } - if(already_exists) - { - break; - } - } - } - - // rjf: if the task is new -> push request to start task - if(task_is_new) - { - RingGuard g = guarded_ring_open(w32_smsv_state->new_task_ring); - guarded_ring_write_struct_or_wait(&g, &task_id, max_U64); - guarded_ring_close(&g); - ins_atomic_u32_eval_assign(&async_loop_again, 1); - cond_var_broadcast(async_tick_start_cond_var); - } } scratch_end(scratch); return result; } +internal void +smsv_fill_local_path(String8 path) +{ + // rjf: determine if we already have this debug info stored locally + B32 already_cached_locally = (properties_from_file_path(path).modified != 0); + + // rjf: if not cached: record (local path -> download task) mapping + B32 task_is_new = 0; + U64 task_id = 0; + if(!already_cached_locally) + { + U64 hash = u64_hash_from_str8(path); + U64 slot_idx = hash%w32_smsv_state->task_slots_count; + W32_SMSV_TaskSlot *slot = &w32_smsv_state->task_slots[slot_idx]; + Stripe *stripe = stripe_from_slot_idx(&w32_smsv_state->task_stripes, slot_idx); + for(B32 write_mode = 0; write_mode <= 1; write_mode += 1) + { + B32 already_exists = 0; + RWMutexScope(stripe->rw_mutex, write_mode) + { + W32_SMSV_Task *node = 0; + for(W32_SMSV_Task *n = slot->first; n != 0; n = n->next) + { + if(path_match_normalized(n->local_path, path)) + { + already_exists = 1; + node = n; + break; + } + } + if(node == 0 && write_mode) + { + Arena *arena = arena_alloc(); + node = push_array(arena, W32_SMSV_Task, 1); + node->arena = arena; + node->local_path = path_normalized_from_string(arena, path); + DLLPushBack(slot->first, slot->last, node); + task_is_new = 1; + task_id = (U64)node; + } + } + if(already_exists) + { + break; + } + } + } + + // rjf: if the task is new -> push request to start task + if(task_is_new) + { + RingGuard g = guarded_ring_open(w32_smsv_state->new_task_ring); + guarded_ring_write_struct_or_wait(&g, &task_id, max_U64); + guarded_ring_close(&g); + ins_atomic_u32_eval_assign(&async_loop_again, 1); + cond_var_broadcast(async_tick_start_cond_var); + } +} + internal SMSV_Status smsv_status_from_local_path(String8 path) { diff --git a/src/win32/symbol_server/win32_symbol_server.h b/src/win32/symbol_server/win32_symbol_server.h index ae9f02a4..0ebc1b36 100644 --- a/src/win32/symbol_server/win32_symbol_server.h +++ b/src/win32/symbol_server/win32_symbol_server.h @@ -22,9 +22,6 @@ struct W32_SMSV_Task // rjf: key / parameters Arena *arena; String8 local_path; - String8 dbg_name; - Guid guid; - U64 age; // rjf: working state W32_SMSV_TaskStatus status; @@ -64,4 +61,10 @@ struct W32_SMSV_State global W32_SMSV_State *w32_smsv_state = 0; +//////////////////////////////// +//~ rjf: Helpers + +internal String8 w32_smsv_dbg_name_from_local_path(String8 path); +internal String8 w32_smsv_unique_identifier_from_local_path(String8 path); + #endif // WIN32_SYMBOL_SERVER_H