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

This commit is contained in:
Ryan Fleury
2026-06-08 21:06:44 -07:00
parent b22f9f2d8b
commit 132751777f
19 changed files with 199 additions and 318 deletions
+7 -1
View File
@@ -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"
}
+1 -15
View File
@@ -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;
};
+9 -34
View File
@@ -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)
{
-1
View File
@@ -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);
-125
View File
@@ -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)
{
+1 -8
View File
@@ -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);
+9 -3
View File
@@ -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;
}
}
}
}
-1
View File
@@ -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;
-18
View File
@@ -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;
}
-5
View File
@@ -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
+3 -5
View File
@@ -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;
+1 -1
View File
@@ -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:
{
+13 -2
View File
@@ -562,14 +562,22 @@ 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];
if(f->inline_depth == 0)
{
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)
{
did_first_in_main_module = 1;
U64 rip_voff = d_voff_from_vaddr(module, rip_vaddr);
String8 name = {0};
{
@@ -588,11 +596,12 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, D_Entity *entity, B32 include_extr
if(name.size != 0)
{
did_first_known = 1;
num_pushed += 1;
dr_fstrs_push_new(arena, &result, &params, name, .size = extras_size, .color = symbol_color);
if(idx+1 < call_stack.frames_count)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit(" > "), .color = secondary_color, .size = extras_size);
if(idx+1 == limit)
if(num_pushed+1 == limit)
{
dr_fstrs_push_new(arena, &result, &params, str8_lit("..."), .color = secondary_color, .size = extras_size);
}
@@ -600,6 +609,8 @@ rd_title_fstrs_from_ctrl_entity(Arena *arena, D_Entity *entity, B32 include_extr
}
}
}
}
}
access_close(access);
}
+2
View File
@@ -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
+11
View File
@@ -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)
{
+8 -8
View File
@@ -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;
}
+8
View File
@@ -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
{
+50 -18
View File
@@ -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, &params, 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,16 +373,23 @@ 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);
}
}
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(result).modified != 0);
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(result);
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);
@@ -363,7 +401,7 @@ smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age)
W32_SMSV_Task *node = 0;
for(W32_SMSV_Task *n = slot->first; n != 0; n = n->next)
{
if(MemoryMatchStruct(&n->guid, &guid))
if(path_match_normalized(n->local_path, path))
{
already_exists = 1;
node = n;
@@ -375,10 +413,7 @@ smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age)
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;
node->local_path = path_normalized_from_string(arena, path);
DLLPushBack(slot->first, slot->last, node);
task_is_new = 1;
task_id = (U64)node;
@@ -401,9 +436,6 @@ smsv_local_path_from_key(Arena *arena, String8 dbg_name, Guid guid, U64 age)
cond_var_broadcast(async_tick_start_cond_var);
}
}
scratch_end(scratch);
return result;
}
internal SMSV_Status
smsv_status_from_local_path(String8 path)
@@ -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