mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-12 23:31:38 -07:00
Merge tag 'v0.9.24-alpha'
This commit is contained in:
@@ -1,3 +1,35 @@
|
||||
# v0.9.24-alpha
|
||||
|
||||
## Debugger Changes
|
||||
|
||||
- Added the ability for the debugger to load, use, and evaluate using debug
|
||||
info, even when not actively debugging. The debugger will now keep a process'
|
||||
debug info loaded, even after the process ends. It stores the set of loaded
|
||||
debug info files in the project configuration file, meaning it will also
|
||||
automatically load the same debug info across many runs. Debug info can also
|
||||
be loaded manually (without ever launching a process) with the
|
||||
`Load Debug Info` command. There is also a new tab, `Debug Info`, which allows
|
||||
viewing and managing the set of loaded debug info files.
|
||||
- Improved the debugger's behavior when used as a drag & drop target, to allow
|
||||
for debug info loading as an option (when relevant), and to better handle the
|
||||
case where many files (potentially of different types) are dropped together.
|
||||
- Improved debug info searching performance and reponsiveness in large projects.
|
||||
- Fixed some crashes and incorrect results with the new `list` view.
|
||||
- Fixed some cases where RDIs did not contain some basic types from their
|
||||
originating PDBs.
|
||||
- Allowed `.` and `->` operators to be used with array types.
|
||||
- Fixed the debugger's treatment of quoted command line arguments when building
|
||||
targets. In previous versions, calling `raddbg main.exe "foo bar baz"` would
|
||||
create a target `main.exe` with arguments `foo bar baz` (dropping the quotes).
|
||||
This is now fixed, such that the target's arguments string will also contain
|
||||
the quotes, and pass them to the target when launched.
|
||||
- Fixed the debugger not correctly responding (through font and UI scale) to DPI
|
||||
changes.
|
||||
- Fixed the debugger incorrectly generating conflicting source line info records
|
||||
in PDB -> RDI conversion, which in some scenarios was preventing source line
|
||||
maps from working (leading to breakpoint resolution failing).
|
||||
- Other small fixes, improvements, and tweaks.
|
||||
|
||||
# v0.9.23-alpha
|
||||
|
||||
## Debugger Changes
|
||||
|
||||
@@ -18,6 +18,9 @@ ac_init(void)
|
||||
ac_shared->req_batches[idx].mutex = mutex_alloc();
|
||||
ac_shared->req_batches[idx].arena = arena_alloc();
|
||||
}
|
||||
ac_shared->cancel_thread = thread_launch(ac_cancel_thread_entry_point, 0);
|
||||
ac_shared->cancel_thread_mutex = mutex_alloc();
|
||||
mutex_take(ac_shared->cancel_thread_mutex);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -138,9 +141,9 @@ ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U6
|
||||
node->key = str8_copy(stripe->arena, key);
|
||||
node->working_count = 1;
|
||||
node->evict_threshold_us = params->evict_threshold_us;
|
||||
node->access_pt.last_time_touched_us = os_now_microseconds();
|
||||
node->access_pt.last_update_idx_touched = update_tick_idx();
|
||||
}
|
||||
node->access_pt.last_time_touched_us = os_now_microseconds();
|
||||
node->access_pt.last_update_idx_touched = update_tick_idx();
|
||||
|
||||
// rjf: request
|
||||
if(need_request)
|
||||
@@ -161,8 +164,8 @@ ac_artifact_from_key_(Access *access, String8 key, AC_ArtifactParams *params, U6
|
||||
}
|
||||
n->v.key = str8_copy(req_batch->arena, key);
|
||||
n->v.gen = params->gen;
|
||||
n->v.cancel_signal = &node->cancelled;
|
||||
n->v.create = params->create;
|
||||
n->v.cancel_signal = params->cancel_signal;
|
||||
}
|
||||
cond_var_broadcast(async_tick_start_cond_var);
|
||||
ins_atomic_u32_eval_assign(&async_loop_again, 1);
|
||||
@@ -210,6 +213,14 @@ ac_async_tick(void)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: enable cancellation scanning
|
||||
//
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
mutex_drop(ac_shared->cancel_thread_mutex);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: do eviction pass across all caches
|
||||
//
|
||||
@@ -574,5 +585,70 @@ ac_async_tick(void)
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: disable cancellation scanning
|
||||
//
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
mutex_take(ac_shared->cancel_thread_mutex);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cancel Thread
|
||||
|
||||
internal void
|
||||
ac_cancel_thread_entry_point(void *p)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
os_sleep_milliseconds(50);
|
||||
MutexScope(ac_shared->cancel_thread_mutex)
|
||||
{
|
||||
for EachIndex(cache_slot_idx, ac_shared->cache_slots_count)
|
||||
{
|
||||
Stripe *cache_stripe = stripe_from_slot_idx(&ac_shared->cache_stripes, cache_slot_idx);
|
||||
RWMutexScope(cache_stripe->rw_mutex, 0)
|
||||
{
|
||||
for EachNode(cache, AC_Cache, ac_shared->cache_slots[cache_slot_idx])
|
||||
{
|
||||
Rng1U64 slot_range = lane_range(cache->slots_count);
|
||||
for EachInRange(slot_idx, slot_range)
|
||||
{
|
||||
AC_Slot *slot = &cache->slots[slot_idx];
|
||||
Stripe *stripe = stripe_from_slot_idx(&cache->stripes, slot_idx);
|
||||
for(B32 write_mode = 0; write_mode <= 1; write_mode += 1)
|
||||
{
|
||||
B32 slot_has_work = 0;
|
||||
RWMutexScope(stripe->rw_mutex, write_mode)
|
||||
{
|
||||
for(AC_Node *n = slot->first, *next = 0; n != 0; n = next)
|
||||
{
|
||||
next = n->next;
|
||||
if(access_pt_is_expired(&n->access_pt, .time = n->evict_threshold_us) && ins_atomic_u64_eval(&n->working_count) > 0)
|
||||
{
|
||||
slot_has_work = 1;
|
||||
if(!write_mode)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
n->cancelled = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!slot_has_work)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ struct AC_ArtifactParams
|
||||
U64 gen;
|
||||
U64 evict_threshold_us;
|
||||
B32 *stale_out;
|
||||
B32 *cancel_signal;
|
||||
AC_Flags flags;
|
||||
};
|
||||
|
||||
@@ -127,6 +126,10 @@ struct AC_Shared
|
||||
|
||||
// rjf: requests
|
||||
AC_RequestBatch req_batches[2]; // 0: high priority, 1: low priority
|
||||
|
||||
// rjf: cancel thread
|
||||
Thread cancel_thread;
|
||||
Mutex cancel_thread_mutex;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
@@ -139,11 +142,6 @@ global AC_Shared *ac_shared = 0;
|
||||
|
||||
internal void ac_init(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Helpers
|
||||
|
||||
internal B32 ac_cancelled(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Lookups
|
||||
|
||||
@@ -155,4 +153,9 @@ internal AC_Artifact ac_artifact_from_key_(Access *access, String8 key, AC_Artif
|
||||
|
||||
internal void ac_async_tick(void);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cancel Thread
|
||||
|
||||
internal void ac_cancel_thread_entry_point(void *p);
|
||||
|
||||
#endif // ARTIFACT_CACHE_H
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
#endif
|
||||
|
||||
#if !defined(BUILD_VERSION_PATCH)
|
||||
# define BUILD_VERSION_PATCH 23
|
||||
# define BUILD_VERSION_PATCH 24
|
||||
#endif
|
||||
|
||||
#define BUILD_VERSION_STRING_LITERAL Stringify(BUILD_VERSION_MAJOR) "." Stringify(BUILD_VERSION_MINOR) "." Stringify(BUILD_VERSION_PATCH)
|
||||
|
||||
@@ -108,6 +108,11 @@ main_thread_base_entry_point(int arguments_count, char **arguments)
|
||||
U64 num_async_threads = os_get_system_info()->logical_processor_count;
|
||||
U64 num_main_threads_clamped = Min(num_async_threads, num_main_threads);
|
||||
num_async_threads -= num_main_threads_clamped;
|
||||
String8 num_async_threads_string = cmd_line_string(&cmdline, str8_lit("async_thread_count"));
|
||||
if(num_async_threads_string.size != 0)
|
||||
{
|
||||
try_u64_from_str8_c_rules(num_async_threads_string, &num_async_threads);
|
||||
}
|
||||
num_async_threads = Max(1, num_async_threads);
|
||||
Barrier barrier = barrier_alloc(num_async_threads);
|
||||
LaneCtx *lane_ctxs = push_array(scratch.arena, LaneCtx, num_async_threads);
|
||||
@@ -189,7 +194,7 @@ async_thread_entry_point(void *params)
|
||||
{
|
||||
if(!ins_atomic_u32_eval(&async_loop_again))
|
||||
{
|
||||
MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+100000);
|
||||
MutexScope(async_tick_start_mutex) cond_var_wait(async_tick_start_cond_var, async_tick_start_mutex, os_now_microseconds()+1000000);
|
||||
}
|
||||
ins_atomic_u32_eval_assign(&async_loop_again, 0);
|
||||
ins_atomic_u32_eval_assign(&async_loop_again_high_priority, 0);
|
||||
|
||||
+24
-9
@@ -85,25 +85,40 @@ correct_slash_from_char(U8 c)
|
||||
internal U64
|
||||
cstring8_length(U8 *c)
|
||||
{
|
||||
U8 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
return (p - c);
|
||||
U64 length = 0;
|
||||
if(c)
|
||||
{
|
||||
U8 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
length = (U64)(p - c);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cstring16_length(U16 *c)
|
||||
{
|
||||
U16 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
return (p - c);
|
||||
U64 length = 0;
|
||||
if(c)
|
||||
{
|
||||
U16 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
length = (U64)(p - c);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
internal U64
|
||||
cstring32_length(U32 *c)
|
||||
{
|
||||
U32 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
return (p - c);
|
||||
U64 length = 0;
|
||||
if(c)
|
||||
{
|
||||
U32 *p = c;
|
||||
for (;*p != 0; p += 1);
|
||||
length = (U64)(p - c);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
@@ -120,7 +120,7 @@ internal void access_touch(Access *access, AccessPt *pt, CondVar cv);
|
||||
|
||||
//- rjf: access points
|
||||
internal B32 access_pt_is_expired_(AccessPt *pt, AccessPtExpireParams *params);
|
||||
#define access_pt_is_expired(pt, ...) access_pt_is_expired_((pt), &(AccessPtExpireParams){.time = 2000000, .update_idxs = 10, __VA_ARGS__})
|
||||
#define access_pt_is_expired(pt, ...) access_pt_is_expired_((pt), &(AccessPtExpireParams){.time = 2000000, .update_idxs = 2, __VA_ARGS__})
|
||||
|
||||
//- rjf: progress counters
|
||||
#define set_progress_ptr(ptr) (tctx_selected()->progress_counter_ptr = (ptr))
|
||||
|
||||
+34
-14
@@ -3189,7 +3189,7 @@ ctrl_thread__entry_point(void *p)
|
||||
CTRL_Entity *module = ctrl_entity_from_handle(entity_ctx, msg->entity);
|
||||
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
|
||||
DI_Key old_dbgi_key = di_key_from_path_timestamp(debug_info_path->string, debug_info_path->timestamp);
|
||||
di_close(old_dbgi_key);
|
||||
di_close(old_dbgi_key, 0);
|
||||
MutexScopeW(ctrl_state->ctrl_thread_entity_ctx_rw_mutex)
|
||||
{
|
||||
ctrl_entity_equip_string(ctrl_state->ctrl_thread_entity_store, debug_info_path, path_normalized_from_string(scratch.arena, path));
|
||||
@@ -4112,7 +4112,7 @@ ctrl_thread__next_dmn_event(Arena *arena, DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg,
|
||||
out_evt->entity = module_handle;
|
||||
out_evt->string = module_path;
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module_ent);
|
||||
di_close(dbgi_key);
|
||||
di_close(dbgi_key, 0);
|
||||
}break;
|
||||
case DMN_EventKind_DebugString:
|
||||
{
|
||||
@@ -4274,15 +4274,19 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
|
||||
U64 thread_rip_voff = ctrl_voff_from_vaddr(module, thread_rip_vaddr);
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: gather evaluation modules
|
||||
//- rjf: gather evaluation debug infos & modules
|
||||
//
|
||||
U64 eval_modules_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_Module *eval_modules = push_array(arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
U64 eval_dbg_infos_count = Max(1, entity_ctx->entity_kind_counts[CTRL_EntityKind_Module]);
|
||||
E_DbgInfo *eval_dbg_infos = push_array(arena, E_DbgInfo, eval_dbg_infos_count);
|
||||
E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0];
|
||||
MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil);
|
||||
{
|
||||
U64 eval_module_idx = 0;
|
||||
U64 eval_dbg_info_idx = 0;
|
||||
for(CTRL_Entity *machine = entity_ctx->root->first;
|
||||
machine != &ctrl_entity_nil;
|
||||
machine = machine->next)
|
||||
@@ -4392,10 +4396,18 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
|
||||
rdi = di_rdi_from_key(scope->access, dbgi_key, 1, max_U64);
|
||||
}
|
||||
|
||||
//- rjf: fill debug info
|
||||
eval_dbg_infos[eval_dbg_info_idx].dbgi_key = dbgi_key;
|
||||
eval_dbg_infos[eval_dbg_info_idx].rdi = rdi;
|
||||
if(mod == module)
|
||||
{
|
||||
eval_dbg_infos_primary = &eval_dbg_infos[eval_dbg_info_idx];
|
||||
}
|
||||
eval_dbg_info_idx += 1;
|
||||
|
||||
//- rjf: fill evaluation module info
|
||||
eval_modules[eval_module_idx].arch = arch;
|
||||
eval_modules[eval_module_idx].dbgi_key = dbgi_key;
|
||||
eval_modules[eval_module_idx].rdi = rdi;
|
||||
eval_modules[eval_module_idx].dbg_info_num= (U32)eval_dbg_info_idx;
|
||||
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;
|
||||
@@ -4427,6 +4439,11 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
|
||||
ctx->thread_reg_space = e_space_make(CTRL_EvalSpaceKind_Entity);
|
||||
ctx->thread_reg_space.u64_0 = (U64)thread;
|
||||
|
||||
//- rjf: fill debug infos
|
||||
ctx->dbg_infos = eval_dbg_infos;
|
||||
ctx->dbg_infos_count = eval_dbg_infos_count;
|
||||
ctx->primary_dbg_info = eval_dbg_infos_primary;
|
||||
|
||||
//- rjf: fill modules
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
@@ -4445,8 +4462,8 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
|
||||
E_IRCtx *ctx = &scope->ir_ctx;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(arch);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_modules_primary->rdi, thread_rip_voff);
|
||||
ctx->locals_map = e_push_locals_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff);
|
||||
ctx->member_map = e_push_member_map_from_rdi_voff(arena, eval_dbg_infos_primary->rdi, thread_rip_voff);
|
||||
ctx->macro_map = push_array(arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(arena, 512);
|
||||
ctx->auto_hook_map = push_array(arena, E_AutoHookMap, 1);
|
||||
@@ -4469,7 +4486,7 @@ ctrl_thread__eval_scope_begin(Arena *arena, CTRL_UserBreakpointList *user_bps, C
|
||||
// TODO(rjf): need to compute this out here somehow... ctx->frame_base[0] = ;
|
||||
ctx->tls_base = push_array(arena, U64, 1);
|
||||
}
|
||||
e_select_interpret_ctx(&scope->interpret_ctx, eval_modules_primary->rdi, thread_rip_voff);
|
||||
e_select_interpret_ctx(&scope->interpret_ctx, eval_dbg_infos_primary->rdi, thread_rip_voff);
|
||||
|
||||
ProfEnd();
|
||||
return scope;
|
||||
@@ -6485,6 +6502,7 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
|
||||
//- rjf: compute call stack
|
||||
CTRL_Entity *thread = ctrl_entity_from_handle(entity_ctx, thread_handle);
|
||||
B32 good = 1;
|
||||
B32 retry = 0;
|
||||
Arena *arena = 0;
|
||||
CTRL_CallStack *call_stack = 0;
|
||||
if(thread != &ctrl_entity_nil)
|
||||
@@ -6507,12 +6525,17 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
|
||||
good = 1;
|
||||
call_stack[0] = ctrl_call_stack_from_unwind(arena, process, &unwind);
|
||||
}
|
||||
if(unwind.flags & CTRL_UnwindFlag_Stale)
|
||||
{
|
||||
retry = 1;
|
||||
}
|
||||
post_reg_gen = ctrl_reg_gen();
|
||||
post_mem_gen = ctrl_mem_gen();
|
||||
}
|
||||
if(pre_reg_gen != post_reg_gen || pre_mem_gen != post_mem_gen)
|
||||
{
|
||||
good = 0;
|
||||
retry = 1;
|
||||
}
|
||||
if(!good)
|
||||
{
|
||||
@@ -6533,11 +6556,8 @@ ctrl_call_stack_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out,
|
||||
artifact.u64[1] = (U64)call_stack;
|
||||
}
|
||||
|
||||
//- rjf: retry on bad
|
||||
if(!good)
|
||||
{
|
||||
retry_out[0] = 1;
|
||||
}
|
||||
//- rjf: mark retry
|
||||
retry_out[0] = retry;
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
@@ -1500,6 +1500,16 @@ d_tick(Arena *arena, D_TargetArray *targets, D_BreakpointArray *breakpoints, D_P
|
||||
evt->code = event->u64_code;
|
||||
}break;
|
||||
|
||||
case CTRL_EventKind_NewModule:
|
||||
{
|
||||
D_EventNode *n = push_array(arena, D_EventNode, 1);
|
||||
SLLQueuePush(result.first, result.last, n);
|
||||
result.count += 1;
|
||||
D_Event *evt = &n->v;
|
||||
evt->kind = D_EventKind_ModuleLoad;
|
||||
evt->module = event->entity;
|
||||
}break;
|
||||
|
||||
//- rjf: debug strings
|
||||
|
||||
case CTRL_EventKind_DebugString:
|
||||
|
||||
@@ -86,6 +86,7 @@ struct D_TrapNet
|
||||
typedef enum D_EventKind
|
||||
{
|
||||
D_EventKind_Null,
|
||||
D_EventKind_ModuleLoad,
|
||||
D_EventKind_ProcessEnd,
|
||||
D_EventKind_Stop,
|
||||
D_EventKind_COUNT
|
||||
@@ -107,6 +108,7 @@ struct D_Event
|
||||
{
|
||||
D_EventKind kind;
|
||||
D_EventCause cause;
|
||||
CTRL_Handle module;
|
||||
CTRL_Handle thread;
|
||||
U64 vaddr;
|
||||
U64 code;
|
||||
|
||||
+156
-84
@@ -313,8 +313,8 @@ di_open(DI_Key key)
|
||||
}
|
||||
|
||||
internal void
|
||||
di_close(DI_Key key)
|
||||
{
|
||||
di_close(DI_Key key, B32 force_closed)
|
||||
{
|
||||
//- rjf: unpack key
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&key));
|
||||
U64 slot_idx = hash%di_shared->slots_count;
|
||||
@@ -340,8 +340,15 @@ di_close(DI_Key key)
|
||||
}
|
||||
}
|
||||
if(node)
|
||||
{
|
||||
node->refcount -= 1;
|
||||
{
|
||||
if(force_closed)
|
||||
{
|
||||
node->refcount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
node->refcount -= 1;
|
||||
}
|
||||
if(node->refcount == 0)
|
||||
{
|
||||
for(;;)
|
||||
@@ -377,7 +384,7 @@ di_close(DI_Key key)
|
||||
{
|
||||
arena_release(arena);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -670,12 +677,12 @@ di_async_tick(void)
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: analyze O.G. debug info
|
||||
//- rjf: analyze O.G. debug info
|
||||
if(!t->og_analyzed)
|
||||
{
|
||||
t->og_analyzed = 1;
|
||||
OS_Handle file = os_file_open(OS_AccessFlag_ShareRead|OS_AccessFlag_Read, og_path);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
FileProperties props = os_properties_from_file(file);
|
||||
t->og_size = props.size;
|
||||
U64 rdi_magic_maybe = 0;
|
||||
if(os_file_read_struct(file, 0, &rdi_magic_maybe) == 8 &&
|
||||
@@ -685,11 +692,12 @@ di_async_tick(void)
|
||||
}
|
||||
os_file_close(file);
|
||||
}
|
||||
U64 og_size = t->og_size;
|
||||
U64 og_size = t->og_size;
|
||||
B32 og_is_rdi = t->og_is_rdi;
|
||||
B32 og_is_good = (og_size > 0);
|
||||
|
||||
//- rjf: compute key's RDI path
|
||||
String8 rdi_path = {0};
|
||||
String8 rdi_path = {0};
|
||||
{
|
||||
if(og_is_rdi)
|
||||
{
|
||||
@@ -754,8 +762,31 @@ di_async_tick(void)
|
||||
threads_available = (max_threads >= needed_threads);
|
||||
}
|
||||
|
||||
//- rjf: if this conversion will overwrite an RDI we already have in cache,
|
||||
// then we need to evict the old one from the cache.
|
||||
B32 ready_to_launch_conversion = (threads_available && !og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI_LoadTaskStatus_Active);
|
||||
if(ready_to_launch_conversion)
|
||||
{
|
||||
U64 path2key_hash = u64_hash_from_str8(og_path);
|
||||
U64 path2key_slot_idx = path2key_hash%di_shared->path2key_slots_count;
|
||||
DI_KeySlot *path2key_slot = &di_shared->path2key_slots[path2key_slot_idx];
|
||||
Stripe *path2key_stripe = stripe_from_slot_idx(&di_shared->path2key_stripes, path2key_slot_idx);
|
||||
RWMutexScope(path2key_stripe->rw_mutex, 0)
|
||||
{
|
||||
// NOTE(rjf): we need to iterate from last -> first, since we want to evict the
|
||||
// most recent key.
|
||||
for(DI_KeyPathNode *n = path2key_slot->last; n != 0; n = n->prev)
|
||||
{
|
||||
if(str8_match(n->path, og_path, 0) && !di_key_match(key, n->key))
|
||||
{
|
||||
di_close(n->key, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: launch conversion processes
|
||||
if(threads_available && !og_is_rdi && rdi_is_stale && t->thread_count != 0 && t->status != DI_LoadTaskStatus_Active)
|
||||
if(og_is_good && ready_to_launch_conversion)
|
||||
{
|
||||
B32 should_compress = 0;
|
||||
OS_ProcessLaunchParams params = {0};
|
||||
@@ -818,7 +849,13 @@ di_async_tick(void)
|
||||
di_shared->conversion_thread_count -= t->thread_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: ready to launch, but bad O.G. file -> just immediately mark as done
|
||||
if(!og_is_good && ready_to_launch_conversion)
|
||||
{
|
||||
t->status = DI_LoadTaskStatus_Done;
|
||||
}
|
||||
|
||||
//- rjf: if the RDI for this task is not stale, then we're already done - mark this
|
||||
// task as done & prepped for storing into the cache
|
||||
@@ -960,8 +997,11 @@ di_async_tick(void)
|
||||
node->arena = rdi_parsed_arena;
|
||||
MemoryCopyStruct(&node->rdi, &rdi_parsed);
|
||||
node->completion_count += 1;
|
||||
node->working_count -= 1;
|
||||
ins_atomic_u64_inc_eval(&di_shared->load_gen);
|
||||
node->working_count -= 1;
|
||||
if(node->rdi.raw_data_size != 0)
|
||||
{
|
||||
ins_atomic_u64_inc_eval(&di_shared->load_gen);
|
||||
}
|
||||
ins_atomic_u64_inc_eval(&di_shared->load_count);
|
||||
}
|
||||
else
|
||||
@@ -1142,9 +1182,10 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
Rng1U64 range = lane_range(element_count);
|
||||
for EachInRange(idx, range)
|
||||
{
|
||||
//- rjf: every so often, check if we need to cancel, and cancel
|
||||
//- rjf: every so often, check if we need to cancel, and cancel
|
||||
if(idx%10000 == 0 && !!ins_atomic_u32_eval(cancel_signal))
|
||||
{
|
||||
// TODO(rjf)
|
||||
break;
|
||||
}
|
||||
|
||||
//- rjf: get element, map to string; if empty, continue to next element
|
||||
@@ -1244,7 +1285,15 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
|
||||
//- rjf: decide if we cancelled
|
||||
B32 cancelled = 0;
|
||||
if(lane_idx() == 0 && !!ins_atomic_u32_eval(cancel_signal))
|
||||
{
|
||||
cancelled = 1;
|
||||
}
|
||||
lane_sync_u64(&cancelled, 0);
|
||||
|
||||
//- rjf: produce sort records
|
||||
typedef struct SortRecord SortRecord;
|
||||
struct SortRecord
|
||||
@@ -1255,15 +1304,15 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
U64 sort_records_count = all_items->total_count;
|
||||
SortRecord *sort_records = 0;
|
||||
SortRecord *sort_records__swap = 0;
|
||||
ProfScope("produce sort records")
|
||||
if(!cancelled) ProfScope("produce sort records")
|
||||
{
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
sort_records = push_array(scratch.arena, SortRecord, sort_records_count);
|
||||
sort_records = push_array_no_zero(scratch.arena, SortRecord, sort_records_count);
|
||||
}
|
||||
if(lane_idx() == lane_from_task_idx(1))
|
||||
{
|
||||
sort_records__swap = push_array(scratch.arena, SortRecord, sort_records_count);
|
||||
sort_records__swap = push_array_no_zero(scratch.arena, SortRecord, sort_records_count);
|
||||
}
|
||||
lane_sync_u64(&sort_records, 0);
|
||||
lane_sync_u64(&sort_records__swap, lane_from_task_idx(1));
|
||||
@@ -1283,7 +1332,7 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
lane_sync();
|
||||
|
||||
//- rjf: sort records
|
||||
ProfScope("sort records")
|
||||
if(!cancelled) ProfScope("sort records")
|
||||
{
|
||||
//- rjf: set up common data
|
||||
U64 bits_per_digit = 8;
|
||||
@@ -1382,12 +1431,12 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
|
||||
//- rjf: produce final array
|
||||
DI_SearchItemArray items = {0};
|
||||
ProfScope("produce final array")
|
||||
if(!cancelled) ProfScope("produce final array")
|
||||
{
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
items.count = all_items->total_count;
|
||||
items.v = push_array(arena, DI_SearchItem, items.count);
|
||||
items.v = push_array_no_zero(arena, DI_SearchItem, items.count);
|
||||
}
|
||||
lane_sync_u64(&items.count, 0);
|
||||
lane_sync_u64(&items.v, 0);
|
||||
@@ -1401,11 +1450,20 @@ di_search_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//- rjf: bundle as artifact
|
||||
artifact.u64[0] = (U64)arenas;
|
||||
artifact.u64[1] = arenas_count;
|
||||
artifact.u64[2] = (U64)items.v;
|
||||
artifact.u64[3] = items.count;
|
||||
//- rjf: bundle as artifact
|
||||
if(!cancelled)
|
||||
{
|
||||
artifact.u64[0] = (U64)arenas;
|
||||
artifact.u64[1] = arenas_count;
|
||||
artifact.u64[2] = (U64)items.v;
|
||||
artifact.u64[3] = items.count;
|
||||
}
|
||||
|
||||
//- rjf: release results on cancel
|
||||
else
|
||||
{
|
||||
arena_release(arena);
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
access_close(access);
|
||||
@@ -1446,7 +1504,7 @@ di_search_item_array_from_target_query(Access *access, RDI_SectionKind target, S
|
||||
String8 key = str8_list_join(scratch.arena, &key_parts, 0);
|
||||
|
||||
// rjf: get artifact
|
||||
AC_Artifact artifact = ac_artifact_from_key(access, key, di_search_artifact_create, di_search_artifact_destroy, endt_us, .gen = di_load_gen(), .flags = AC_Flag_Wide, .stale_out = stale_out);
|
||||
AC_Artifact artifact = ac_artifact_from_key(access, key, di_search_artifact_create, di_search_artifact_destroy, endt_us, .gen = di_load_gen(), .flags = AC_Flag_Wide, .evict_threshold_us = 100000, .stale_out = stale_out);
|
||||
|
||||
// rjf: unpack artifact
|
||||
result.v = (DI_SearchItem *)artifact.u64[2];
|
||||
@@ -1481,73 +1539,87 @@ di_match_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U64 *g
|
||||
|
||||
//- rjf: get all loaded keys
|
||||
DI_KeyArray dbgi_keys = di_push_all_loaded_keys(scratch.arena);
|
||||
|
||||
|
||||
//- rjf: take cancellation signal
|
||||
B32 cancelled = 0;
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
cancelled = ins_atomic_u32_eval(cancel_signal);
|
||||
}
|
||||
lane_sync_u64(&cancelled, 0);
|
||||
|
||||
//- rjf: wide search across all debug infos
|
||||
DI_Match *lane_matches = 0;
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
lane_matches = push_array(scratch.arena, DI_Match, lane_count());
|
||||
}
|
||||
lane_sync_u64(&lane_matches, 0);
|
||||
{
|
||||
read_only local_persist RDI_NameMapKind name_map_kinds[] =
|
||||
DI_Match *lane_matches = 0;
|
||||
if(!cancelled)
|
||||
{
|
||||
if(lane_idx() == 0)
|
||||
{
|
||||
RDI_NameMapKind_GlobalVariables,
|
||||
RDI_NameMapKind_ThreadVariables,
|
||||
RDI_NameMapKind_Constants,
|
||||
RDI_NameMapKind_Procedures,
|
||||
RDI_NameMapKind_Types,
|
||||
};
|
||||
read_only local_persist RDI_SectionKind name_map_section_kinds[] =
|
||||
lane_matches = push_array(scratch.arena, DI_Match, lane_count());
|
||||
}
|
||||
lane_sync_u64(&lane_matches, 0);
|
||||
{
|
||||
RDI_SectionKind_GlobalVariables,
|
||||
RDI_SectionKind_ThreadVariables,
|
||||
RDI_SectionKind_Constants,
|
||||
RDI_SectionKind_Procedures,
|
||||
RDI_SectionKind_TypeNodes,
|
||||
};
|
||||
Rng1U64 range = lane_range(dbgi_keys.count);
|
||||
for EachInRange(dbgi_idx, range)
|
||||
{
|
||||
Access *access = access_open();
|
||||
read_only local_persist RDI_NameMapKind name_map_kinds[] =
|
||||
{
|
||||
DI_Key dbgi_key = dbgi_keys.v[dbgi_idx];
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
for EachElement(name_map_kind_idx, name_map_kinds)
|
||||
RDI_NameMapKind_GlobalVariables,
|
||||
RDI_NameMapKind_ThreadVariables,
|
||||
RDI_NameMapKind_Constants,
|
||||
RDI_NameMapKind_Procedures,
|
||||
RDI_NameMapKind_Types,
|
||||
};
|
||||
read_only local_persist RDI_SectionKind name_map_section_kinds[] =
|
||||
{
|
||||
RDI_SectionKind_GlobalVariables,
|
||||
RDI_SectionKind_ThreadVariables,
|
||||
RDI_SectionKind_Constants,
|
||||
RDI_SectionKind_Procedures,
|
||||
RDI_SectionKind_TypeNodes,
|
||||
};
|
||||
Rng1U64 range = lane_range(dbgi_keys.count);
|
||||
for EachInRange(dbgi_idx, range)
|
||||
{
|
||||
Access *access = access_open();
|
||||
{
|
||||
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
|
||||
RDI_ParsedNameMap parsed_name_map = {0};
|
||||
rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map);
|
||||
RDI_NameMapNode *map_node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size);
|
||||
U32 num = 0;
|
||||
U32 *run = rdi_matches_from_map_node(rdi, map_node, &num);
|
||||
if(num != 0)
|
||||
DI_Key dbgi_key = dbgi_keys.v[dbgi_idx];
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
for EachElement(name_map_kind_idx, name_map_kinds)
|
||||
{
|
||||
lane_matches[lane_idx()].key = dbgi_key;
|
||||
lane_matches[lane_idx()].section_kind = name_map_section_kinds[name_map_kind_idx];
|
||||
lane_matches[lane_idx()].idx = run[num-1];
|
||||
RDI_NameMap *name_map = rdi_element_from_name_idx(rdi, NameMaps, name_map_kinds[name_map_kind_idx]);
|
||||
RDI_ParsedNameMap parsed_name_map = {0};
|
||||
rdi_parsed_from_name_map(rdi, name_map, &parsed_name_map);
|
||||
RDI_NameMapNode *map_node = rdi_name_map_lookup(rdi, &parsed_name_map, name.str, name.size);
|
||||
U32 num = 0;
|
||||
U32 *run = rdi_matches_from_map_node(rdi, map_node, &num);
|
||||
if(num != 0)
|
||||
{
|
||||
lane_matches[lane_idx()].key = dbgi_key;
|
||||
lane_matches[lane_idx()].section_kind = name_map_section_kinds[name_map_kind_idx];
|
||||
lane_matches[lane_idx()].idx = run[num-1];
|
||||
}
|
||||
}
|
||||
}
|
||||
access_close(access);
|
||||
}
|
||||
access_close(access);
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
}
|
||||
}
|
||||
lane_sync();
|
||||
|
||||
//- rjf: pick match
|
||||
DI_Match match = {0};
|
||||
for EachIndex(idx, lane_count())
|
||||
{
|
||||
if(lane_matches[idx].idx != 0)
|
||||
DI_Match match = {0};
|
||||
if(lane_matches != 0)
|
||||
{
|
||||
for EachIndex(idx, lane_count())
|
||||
{
|
||||
match = lane_matches[idx];
|
||||
if(di_key_match(di_key_zero(), preferred_key) || di_key_match(match.key, preferred_key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(lane_matches[idx].idx != 0)
|
||||
{
|
||||
match = lane_matches[idx];
|
||||
if(di_key_match(di_key_zero(), preferred_key) || di_key_match(match.key, preferred_key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//- rjf: package as artifact
|
||||
AC_Artifact artifact = {0};
|
||||
{
|
||||
@@ -1579,7 +1651,7 @@ di_match_from_string(String8 string, U64 index, DI_Key preferred_dbgi_key, U64 e
|
||||
String8 key = str8_list_join(scratch.arena, &key_parts, 0);
|
||||
U64 dbgi_count = di_load_count();
|
||||
B32 wide = (dbgi_count > 256);
|
||||
AC_Artifact artifact = ac_artifact_from_key(access, key, di_match_artifact_create, 0, endt_us, .flags = wide ? AC_Flag_Wide : 0, .gen = di_load_gen());
|
||||
AC_Artifact artifact = ac_artifact_from_key(access, key, di_match_artifact_create, 0, endt_us, .flags = wide ? AC_Flag_Wide : 0, .gen = di_load_gen(), .evict_threshold_us = wide ? 20000000 : 10000000);
|
||||
result.key.u64[0] = artifact.u64[0];
|
||||
result.key.u64[1] = artifact.u64[1];
|
||||
result.section_kind = artifact.u64[2];
|
||||
|
||||
@@ -323,7 +323,7 @@ internal DI_Key di_key_from_path_timestamp(String8 path, U64 min_timestamp);
|
||||
//~ rjf: Debug Info Opening / Closing
|
||||
|
||||
internal void di_open(DI_Key key);
|
||||
internal void di_close(DI_Key key);
|
||||
internal void di_close(DI_Key key, B32 force_closed);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug Info Lookups
|
||||
|
||||
+31
-3
@@ -676,8 +676,10 @@ internal void
|
||||
e_select_base_ctx(E_BaseCtx *ctx)
|
||||
{
|
||||
//- rjf: select base context
|
||||
if(ctx->modules == 0) { ctx->modules = &e_module_nil; }
|
||||
if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; }
|
||||
if(ctx->modules == 0) { ctx->modules = &e_module_nil; }
|
||||
if(ctx->primary_module == 0) { ctx->primary_module = &e_module_nil; }
|
||||
if(ctx->dbg_infos == 0) { ctx->dbg_infos = &e_dbg_info_nil; }
|
||||
if(ctx->primary_dbg_info == 0) { ctx->primary_dbg_info = &e_dbg_info_nil; }
|
||||
e_base_ctx = ctx;
|
||||
|
||||
//- rjf: reset the evaluation cache
|
||||
@@ -718,7 +720,7 @@ e_select_base_ctx(E_BaseCtx *ctx)
|
||||
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(folder),
|
||||
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(folder),
|
||||
});
|
||||
e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_module->rdi, e_base_ctx->thread_ip_voff);
|
||||
e_cache->thread_ip_procedure = rdi_procedure_from_voff(e_base_ctx->primary_dbg_info->rdi, e_base_ctx->thread_ip_voff);
|
||||
e_cache->used_expr_map = push_array(e_cache->arena, E_UsedExprMap, 1);
|
||||
e_cache->used_expr_map->slots_count = 64;
|
||||
e_cache->used_expr_map->slots = push_array(e_cache->arena, E_UsedExprSlot, e_cache->used_expr_map->slots_count);
|
||||
@@ -744,6 +746,32 @@ e_select_ir_ctx(E_IRCtx *ctx)
|
||||
e_ir_ctx = ctx;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Accessors
|
||||
|
||||
internal E_DbgInfo *
|
||||
e_dbg_info_from_module(E_Module *module)
|
||||
{
|
||||
E_DbgInfo *result = &e_dbg_info_nil;
|
||||
if(0 < module->dbg_info_num && module->dbg_info_num <= e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
result = &e_base_ctx->dbg_infos[module->dbg_info_num-1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal E_DbgInfo *
|
||||
e_dbg_info_from_type_key(E_TypeKey type_key)
|
||||
{
|
||||
E_DbgInfo *result = &e_dbg_info_nil;
|
||||
if(type_key.kind == E_TypeKeyKind_Ext &&
|
||||
0 < type_key.u32[2] && type_key.u32[2] <= e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
result = &e_base_ctx->dbg_infos[type_key.u32[2]-1];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Cache Accessing Functions
|
||||
|
||||
|
||||
+32
-10
@@ -174,8 +174,8 @@ struct E_TypeKey
|
||||
E_TypeKeyKind kind;
|
||||
U32 u32[3];
|
||||
// [0] -> E_TypeKind (Basic, Cons, Ext); Arch (Reg, RegAlias)
|
||||
// [1] -> Type Index In RDI (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons)
|
||||
// [2] -> RDI Index (Ext)
|
||||
// [1] -> Type Index In Debug Info (Ext); Code (Reg, RegAlias); Type Index In Constructed (Cons)
|
||||
// [2] -> Debug Info Number (Ext)
|
||||
};
|
||||
|
||||
typedef struct E_TypeKeyNode E_TypeKeyNode;
|
||||
@@ -384,11 +384,12 @@ enum
|
||||
E_TypeFlag_IsCodeText = (1<<4),
|
||||
E_TypeFlag_IsPathText = (1<<5),
|
||||
E_TypeFlag_IsNotText = (1<<6),
|
||||
E_TypeFlag_EditableChildren = (1<<7),
|
||||
E_TypeFlag_InheritedByMembers = (1<<8),
|
||||
E_TypeFlag_InheritedByElements = (1<<9),
|
||||
E_TypeFlag_ArrayLikeExpansion = (1<<10),
|
||||
E_TypeFlag_StubSingleLineExpansion = (1<<11),
|
||||
E_TypeFlag_IsNotEditable = (1<<7),
|
||||
E_TypeFlag_EditableChildren = (1<<8),
|
||||
E_TypeFlag_InheritedByMembers = (1<<9),
|
||||
E_TypeFlag_InheritedByElements = (1<<10),
|
||||
E_TypeFlag_ArrayLikeExpansion = (1<<11),
|
||||
E_TypeFlag_StubSingleLineExpansion = (1<<12),
|
||||
};
|
||||
|
||||
typedef struct E_Member E_Member;
|
||||
@@ -564,15 +565,24 @@ struct E_ConsTypeSlot
|
||||
E_ConsTypeNode *last;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Debug Info
|
||||
|
||||
typedef struct E_DbgInfo E_DbgInfo;
|
||||
struct E_DbgInfo
|
||||
{
|
||||
DI_Key dbgi_key;
|
||||
RDI_Parsed *rdi;
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Modules
|
||||
|
||||
typedef struct E_Module E_Module;
|
||||
struct E_Module
|
||||
{
|
||||
DI_Key dbgi_key;
|
||||
RDI_Parsed *rdi;
|
||||
Rng1U64 vaddr_range;
|
||||
U32 dbg_info_num;
|
||||
Arch arch;
|
||||
E_Space space;
|
||||
};
|
||||
@@ -760,6 +770,11 @@ struct E_BaseCtx
|
||||
Arch thread_arch;
|
||||
U64 thread_unwind_count;
|
||||
|
||||
// rjf: debug infos
|
||||
E_DbgInfo *dbg_infos;
|
||||
U64 dbg_infos_count;
|
||||
E_DbgInfo *primary_dbg_info;
|
||||
|
||||
// rjf: modules
|
||||
E_Module *modules;
|
||||
U64 modules_count;
|
||||
@@ -1111,7 +1126,8 @@ read_only global E_String2ExprMap e_string2expr_map_nil = {0};
|
||||
read_only global E_Expr e_expr_nil = {&e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil, &e_expr_nil};
|
||||
read_only global E_IRNode e_irnode_nil = {&e_irnode_nil, &e_irnode_nil, &e_irnode_nil};
|
||||
read_only global E_Eval e_eval_nil = {{0}, {0}, {0}, &e_expr_nil, {&e_irnode_nil}};
|
||||
read_only global E_Module e_module_nil = {{0}, &rdi_parsed_nil};
|
||||
read_only global E_DbgInfo e_dbg_info_nil = {{0}, &rdi_parsed_nil};
|
||||
read_only global E_Module e_module_nil = {0};
|
||||
read_only global E_CacheBundle e_cache_bundle_nil = {0, {0}, {0}, {0}, {{0}, 0, &e_expr_nil, &e_expr_nil}, {&e_irnode_nil}};
|
||||
thread_static E_BaseCtx *e_base_ctx = 0;
|
||||
thread_static E_IRCtx *e_ir_ctx = 0;
|
||||
@@ -1203,6 +1219,12 @@ internal void e_select_cache(E_Cache *cache);
|
||||
internal void e_select_base_ctx(E_BaseCtx *ctx);
|
||||
internal void e_select_ir_ctx(E_IRCtx *ctx);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Context Accessors
|
||||
|
||||
internal E_DbgInfo *e_dbg_info_from_module(E_Module *module);
|
||||
internal E_DbgInfo *e_dbg_info_from_type_key(E_TypeKey type_key);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Base Cache Accessing Functions
|
||||
//
|
||||
|
||||
+50
-33
@@ -389,7 +389,8 @@ E_TYPE_ACCESS_FUNCTION_DEF(default)
|
||||
E_TypeKind check_type_kind = l_restype_kind;
|
||||
if(l_restype_kind == E_TypeKind_Ptr ||
|
||||
l_restype_kind == E_TypeKind_LRef ||
|
||||
l_restype_kind == E_TypeKind_RRef)
|
||||
l_restype_kind == E_TypeKind_RRef ||
|
||||
l_restype_kind == E_TypeKind_Array)
|
||||
{
|
||||
check_type_key = e_type_key_unwrap(l.type_key, E_TypeUnwrapFlag_All);
|
||||
check_type_kind = e_type_kind_from_key(check_type_key);
|
||||
@@ -698,6 +699,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
result = new_result_maybe;
|
||||
break;
|
||||
}
|
||||
else if(new_result_maybe.msgs.count != 0 && result.msgs.count == 0)
|
||||
{
|
||||
result = new_result_maybe;
|
||||
}
|
||||
}
|
||||
if(result.root != &e_irnode_nil)
|
||||
{
|
||||
@@ -963,28 +968,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
String8 bytecode = e_bytecode_from_oplist(scratch.arena, &oplist);
|
||||
E_Interpretation interpretation = e_interpret(bytecode);
|
||||
E_Module *module = &e_module_nil;
|
||||
U32 rdi_idx = 0;
|
||||
for EachIndex(idx, e_base_ctx->modules_count)
|
||||
{
|
||||
E_Module *m = &e_base_ctx->modules[idx];
|
||||
if(e_space_match(interpretation.space, m->space) && contains_1u64(m->vaddr_range, interpretation.value.u64))
|
||||
{
|
||||
module = m;
|
||||
rdi_idx = (U32)idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(module != &e_module_nil)
|
||||
{
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
U64 voff = interpretation.value.u64 - module->vaddr_range.min;
|
||||
U64 new_vaddr = 0;
|
||||
RDI_Procedure *p = rdi_procedure_from_voff(module->rdi, voff);
|
||||
RDI_GlobalVariable *g = rdi_global_variable_from_voff(module->rdi, voff);
|
||||
RDI_Procedure *p = rdi_procedure_from_voff(dbg_info->rdi, voff);
|
||||
RDI_GlobalVariable *g = rdi_global_variable_from_voff(dbg_info->rdi, voff);
|
||||
U32 type_idx = 0;
|
||||
if(p->name_string_idx != 0)
|
||||
{
|
||||
type_idx = p->type_idx;
|
||||
new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(module->rdi, p);
|
||||
new_vaddr = module->vaddr_range.min + rdi_first_voff_from_procedure(dbg_info->rdi, p);
|
||||
}
|
||||
else if(g->name_string_idx != 0)
|
||||
{
|
||||
@@ -993,10 +997,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
}
|
||||
if(type_idx != 0)
|
||||
{
|
||||
RDI_TypeNode *t = rdi_element_from_name_idx(module->rdi, TypeNodes, type_idx);
|
||||
RDI_TypeNode *t = rdi_element_from_name_idx(dbg_info->rdi, TypeNodes, type_idx);
|
||||
result.root = e_irtree_const_u(arena, new_vaddr);
|
||||
result.mode = E_Mode_Value;
|
||||
result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, rdi_idx);
|
||||
result.type_key = e_type_key_ext(e_type_kind_from_rdi(t->kind), type_idx, module->dbg_info_num);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
@@ -1792,12 +1796,12 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("member"), 0)))
|
||||
{
|
||||
E_Module *module = e_base_ctx->primary_module;
|
||||
U32 module_idx = (U32)(module - e_base_ctx->modules);
|
||||
RDI_Parsed *rdi = module->rdi;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
RDI_Parsed *rdi = dbg_info->rdi;
|
||||
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
|
||||
RDI_UDT *udt = rdi_container_udt_from_procedure(rdi, procedure);
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
|
||||
E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module_idx);
|
||||
E_TypeKey container_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), udt->self_type_idx, module->dbg_info_num);
|
||||
E_Member member = e_type_member_from_key_name__cached(container_type_key, string);
|
||||
if(member.kind != E_MemberKind_Null)
|
||||
{
|
||||
@@ -1811,8 +1815,8 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
if(!string_mapped && (qualifier.size == 0 || str8_match(qualifier, str8_lit("local"), 0)))
|
||||
{
|
||||
E_Module *module = e_base_ctx->primary_module;
|
||||
U32 module_idx = (U32)(module - e_base_ctx->modules);
|
||||
RDI_Parsed *rdi = module->rdi;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
RDI_Parsed *rdi = dbg_info->rdi;
|
||||
U64 local_num = e_num_from_string(e_ir_ctx->locals_map, string__redirected);
|
||||
if(local_num != 0)
|
||||
{
|
||||
@@ -1820,7 +1824,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
|
||||
// rjf: extract local's type key
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, local->type_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), local->type_idx, module->dbg_info_num);
|
||||
|
||||
// rjf: extract local's location block
|
||||
B32 got_location_block = 0;
|
||||
@@ -1887,13 +1891,14 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
Access *access = access_open();
|
||||
|
||||
// rjf: find match
|
||||
DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_module->dbgi_key, 0);
|
||||
DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
|
||||
if(match.idx == 0)
|
||||
{
|
||||
String8List namespaceified_strings = {0};
|
||||
{
|
||||
E_Module *module = e_base_ctx->primary_module;
|
||||
RDI_Parsed *rdi = module->rdi;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
RDI_Parsed *rdi = dbg_info->rdi;
|
||||
RDI_Procedure *procedure = e_cache->thread_ip_procedure;
|
||||
U64 name_size = 0;
|
||||
U8 *name_ptr = rdi_string_from_idx(rdi, procedure->name_string_idx, &name_size);
|
||||
@@ -1916,7 +1921,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
}
|
||||
for(String8Node *n = namespaceified_strings.first; n != 0; n = n->next)
|
||||
{
|
||||
match = di_match_from_string(n->string, 0, e_base_ctx->primary_module->dbgi_key, 0);
|
||||
match = di_match_from_string(n->string, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
|
||||
if(match.idx != 0)
|
||||
{
|
||||
break;
|
||||
@@ -1927,17 +1932,27 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
// rjf: match -> RDI
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0);
|
||||
|
||||
// rjf: find dbg info from rdi
|
||||
E_DbgInfo *dbg_info = &e_dbg_info_nil;
|
||||
U32 dbg_info_num = 0;
|
||||
for EachIndex(idx, e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
if(e_base_ctx->dbg_infos[idx].rdi == rdi)
|
||||
{
|
||||
dbg_info = &e_base_ctx->dbg_infos[idx];
|
||||
dbg_info_num = idx+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: find module from dbgi key
|
||||
U32 dbgi_idx = 0;
|
||||
E_Module *module = &e_module_nil;
|
||||
for EachIndex(idx, e_base_ctx->modules_count)
|
||||
{
|
||||
if(e_base_ctx->modules[idx].rdi == rdi)
|
||||
if(e_base_ctx->modules[idx].dbg_info_num == dbg_info_num)
|
||||
{
|
||||
module = &e_base_ctx->modules[idx];
|
||||
dbgi_idx = (U32)idx;
|
||||
if(module == e_base_ctx->primary_module ||
|
||||
e_space_match(module->space, e_base_ctx->primary_module->space))
|
||||
if(module == e_base_ctx->primary_module || e_space_match(module->space, e_base_ctx->primary_module->space))
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1945,7 +1960,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
}
|
||||
|
||||
// rjf: form result
|
||||
if(match.idx != 0 && module != &e_module_nil)
|
||||
if(match.idx != 0 && dbg_info != &e_dbg_info_nil)
|
||||
{
|
||||
switch(match.section_kind)
|
||||
{
|
||||
@@ -1958,7 +1973,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
E_OpList oplist = {0};
|
||||
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + global_var->voff));
|
||||
string_mapped = 1;
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
|
||||
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
mapped_bytecode_mode = E_Mode_Offset;
|
||||
mapped_bytecode_space = module->space;
|
||||
@@ -1971,7 +1986,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
E_OpList oplist = {0};
|
||||
e_oplist_push_op(arena, &oplist, RDI_EvalOp_TLSOff, e_value_u64(thread_var->tls_off));
|
||||
string_mapped = 1;
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
|
||||
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
mapped_bytecode_mode = E_Mode_Offset;
|
||||
mapped_bytecode_space = module->space;
|
||||
@@ -1994,7 +2009,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
E_OpList oplist = {0};
|
||||
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(value));
|
||||
string_mapped = 1;
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
|
||||
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
mapped_bytecode_mode = E_Mode_Value;
|
||||
mapped_bytecode_space = module->space;
|
||||
@@ -2012,7 +2027,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
E_OpList oplist = {0};
|
||||
e_oplist_push_op(arena, &oplist, RDI_EvalOp_ConstU64, e_value_u64(module->vaddr_range.min + voff));
|
||||
string_mapped = 1;
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
|
||||
mapped_bytecode = e_bytecode_from_oplist(arena, &oplist);
|
||||
mapped_bytecode_mode = E_Mode_Value;
|
||||
mapped_bytecode_space = module->space;
|
||||
@@ -2021,7 +2036,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
{
|
||||
U32 type_idx = match.idx;
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbgi_idx);
|
||||
mapped_type_key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, dbg_info_num);
|
||||
string_mapped = 1;
|
||||
}break;
|
||||
}
|
||||
@@ -2106,9 +2121,10 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
if(!generated && mapped_location_block != 0)
|
||||
{
|
||||
E_Module *module = mapped_location_block_module;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
E_Space space = module->space;
|
||||
Arch arch = module->arch;
|
||||
RDI_Parsed *rdi = module->rdi;
|
||||
RDI_Parsed *rdi = dbg_info->rdi;
|
||||
RDI_LocationBlock *block = mapped_location_block;
|
||||
U64 all_location_data_size = 0;
|
||||
U8 *all_location_data = rdi_table_from_name(rdi, LocationData, &all_location_data_size);
|
||||
@@ -2461,17 +2477,18 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
if(e_space_read(interpret.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
|
||||
{
|
||||
Arch arch = e_base_ctx->primary_module->arch;
|
||||
U32 rdi_idx = 0;
|
||||
U32 dbg_info_num = 0;
|
||||
RDI_Parsed *rdi = 0;
|
||||
U64 module_base = 0;
|
||||
for(U64 idx = 0; idx < e_base_ctx->modules_count; idx += 1)
|
||||
{
|
||||
if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vtable_vaddr))
|
||||
{
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(&e_base_ctx->modules[idx]);
|
||||
arch = e_base_ctx->modules[idx].arch;
|
||||
rdi_idx = (U32)idx;
|
||||
rdi = e_base_ctx->modules[idx].rdi;
|
||||
module_base = e_base_ctx->modules[idx].vaddr_range.min;
|
||||
dbg_info_num = e_base_ctx->modules[idx].dbg_info_num;
|
||||
rdi = dbg_info->rdi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2484,7 +2501,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
|
||||
{
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, global_var->container_idx);
|
||||
RDI_TypeNode *type = rdi_element_from_name_idx(rdi, TypeNodes, udt->self_type_idx);
|
||||
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, rdi_idx);
|
||||
E_TypeKey derived_type_key = e_type_key_ext(e_type_kind_from_rdi(type->kind), udt->self_type_idx, dbg_info_num);
|
||||
E_TypeKey ptr_to_derived_type_key = e_type_key_cons_ptr(arch, derived_type_key, 1, 0);
|
||||
result.type_key = ptr_to_derived_type_key;
|
||||
}
|
||||
|
||||
@@ -585,19 +585,19 @@ e_leaf_type_key_from_name(String8 name)
|
||||
E_TypeKey key = e_leaf_builtin_type_key_from_name(name);
|
||||
if(!e_type_key_match(e_type_key_zero(), key))
|
||||
{
|
||||
DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_module->dbgi_key, 0);
|
||||
DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, 0);
|
||||
if(match.section_kind == RDI_SectionKind_TypeNodes)
|
||||
{
|
||||
Access *access = access_open();
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, match.key, 0, 0);
|
||||
for EachIndex(idx, e_base_ctx->modules_count)
|
||||
for EachIndex(idx, e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
E_Module *module = &e_base_ctx->modules[idx];
|
||||
if(module->rdi == rdi)
|
||||
E_DbgInfo *dbg_info = &e_base_ctx->dbg_infos[idx];
|
||||
if(dbg_info->rdi == rdi)
|
||||
{
|
||||
U32 type_idx = match.idx;
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, type_idx);
|
||||
key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)idx);
|
||||
key = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), type_idx, (U32)idx+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+307
-290
@@ -271,7 +271,7 @@ e_type_key_basic(E_TypeKind kind)
|
||||
}
|
||||
|
||||
internal E_TypeKey
|
||||
e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx)
|
||||
e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num)
|
||||
{
|
||||
E_TypeKey key = {E_TypeKeyKind_Ext};
|
||||
key.u32[0] = (U32)kind;
|
||||
@@ -282,7 +282,7 @@ e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx)
|
||||
else
|
||||
{
|
||||
key.u32[1] = type_idx;
|
||||
key.u32[2] = rdi_idx;
|
||||
key.u32[2] = rdi_num;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@@ -646,10 +646,13 @@ e_type_byte_size_from_key(E_TypeKey key)
|
||||
case E_TypeKeyKind_Ext:
|
||||
{
|
||||
U64 type_node_idx = key.u32[1];
|
||||
U32 rdi_idx = key.u32[2];
|
||||
RDI_Parsed *rdi = e_base_ctx->modules[rdi_idx].rdi;
|
||||
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
|
||||
result = rdi_type->byte_size;
|
||||
U32 rdi_num = key.u32[2];
|
||||
if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi;
|
||||
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
|
||||
result = rdi_type->byte_size;
|
||||
}
|
||||
}break;
|
||||
case E_TypeKeyKind_Cons:
|
||||
{
|
||||
@@ -758,322 +761,327 @@ e_push_type_from_key(Arena *arena, E_TypeKey key)
|
||||
case E_TypeKeyKind_Ext:
|
||||
{
|
||||
U64 type_node_idx = key.u32[1];
|
||||
U32 rdi_idx = key.u32[2];
|
||||
RDI_Parsed *rdi = e_base_ctx->modules[rdi_idx].rdi;
|
||||
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
|
||||
if(rdi_type->kind != RDI_TypeKind_NULL)
|
||||
U32 rdi_num = key.u32[2];
|
||||
if(0 < rdi_num && rdi_num <= e_base_ctx->dbg_infos_count)
|
||||
{
|
||||
E_TypeKind kind = e_type_kind_from_rdi(rdi_type->kind);
|
||||
|
||||
//- rjf: record types => unpack name * members & produce
|
||||
if(RDI_TypeKind_FirstRecord <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastRecord)
|
||||
RDI_Parsed *rdi = e_base_ctx->dbg_infos[rdi_num-1].rdi;
|
||||
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
|
||||
Arch arch = arch_from_rdi_arch(tli->arch);
|
||||
RDI_TypeNode *rdi_type = rdi_element_from_name_idx(rdi, TypeNodes, type_node_idx);
|
||||
if(rdi_type->kind != RDI_TypeKind_NULL)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
E_TypeKind kind = e_type_kind_from_rdi(rdi_type->kind);
|
||||
|
||||
// rjf: unpack UDT info
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx);
|
||||
|
||||
// rjf: unpack members
|
||||
E_Member *members = 0;
|
||||
U32 members_count = 0;
|
||||
//- rjf: record types => unpack name * members & produce
|
||||
if(RDI_TypeKind_FirstRecord <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastRecord)
|
||||
{
|
||||
members_count = udt->member_count;
|
||||
members = push_array(arena, E_Member, members_count);
|
||||
if(members_count != 0)
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: unpack UDT info
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, rdi_type->user_defined.udt_idx);
|
||||
|
||||
// rjf: unpack members
|
||||
E_Member *members = 0;
|
||||
U32 members_count = 0;
|
||||
{
|
||||
members_count = udt->member_count;
|
||||
members = push_array(arena, E_Member, members_count);
|
||||
if(members_count != 0)
|
||||
{
|
||||
for(U32 member_idx = udt->member_first;
|
||||
member_idx < udt->member_first+udt->member_count;
|
||||
member_idx += 1)
|
||||
{
|
||||
RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx);
|
||||
E_TypeKind member_type_kind = E_TypeKind_Null;
|
||||
RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx);
|
||||
member_type_kind = e_type_kind_from_rdi(member_type->kind);
|
||||
E_Member *dst = &members[member_idx-udt->member_first];
|
||||
dst->kind = e_member_kind_from_rdi(src->kind);
|
||||
dst->type_key = e_type_key_ext(member_type_kind, src->type_idx, rdi_num);
|
||||
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
|
||||
dst->off = (U64)src->off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = members_count;
|
||||
type->arch = arch;
|
||||
type->members = members;
|
||||
}
|
||||
|
||||
//- rjf: enum types => unpack name * values & produce
|
||||
else if(rdi_type->kind == RDI_TypeKind_Enum)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num);
|
||||
}
|
||||
|
||||
// rjf: unpack members
|
||||
E_EnumVal *enum_vals = 0;
|
||||
U32 enum_vals_count = 0;
|
||||
{
|
||||
U32 udt_idx = rdi_type->user_defined.udt_idx;
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx);
|
||||
enum_vals_count = udt->member_count;
|
||||
enum_vals = push_array(arena, E_EnumVal, enum_vals_count);
|
||||
for(U32 member_idx = udt->member_first;
|
||||
member_idx < udt->member_first+udt->member_count;
|
||||
member_idx += 1)
|
||||
{
|
||||
RDI_Member *src = rdi_element_from_name_idx(rdi, Members, member_idx);
|
||||
E_TypeKind member_type_kind = E_TypeKind_Null;
|
||||
RDI_TypeNode *member_type = rdi_element_from_name_idx(rdi, TypeNodes, src->type_idx);
|
||||
member_type_kind = e_type_kind_from_rdi(member_type->kind);
|
||||
E_Member *dst = &members[member_idx-udt->member_first];
|
||||
dst->kind = e_member_kind_from_rdi(src->kind);
|
||||
dst->type_key = e_type_key_ext(member_type_kind, src->type_idx, rdi_idx);
|
||||
RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx);
|
||||
E_EnumVal *dst = &enum_vals[member_idx-udt->member_first];
|
||||
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
|
||||
dst->off = (U64)src->off;
|
||||
dst->val = src->val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = members_count;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
type->members = members;
|
||||
}
|
||||
|
||||
//- rjf: enum types => unpack name * values & produce
|
||||
else if(rdi_type->kind == RDI_TypeKind_Enum)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_idx);
|
||||
}
|
||||
|
||||
// rjf: unpack members
|
||||
E_EnumVal *enum_vals = 0;
|
||||
U32 enum_vals_count = 0;
|
||||
{
|
||||
U32 udt_idx = rdi_type->user_defined.udt_idx;
|
||||
RDI_UDT *udt = rdi_element_from_name_idx(rdi, UDTs, udt_idx);
|
||||
enum_vals_count = udt->member_count;
|
||||
enum_vals = push_array(arena, E_EnumVal, enum_vals_count);
|
||||
for(U32 member_idx = udt->member_first;
|
||||
member_idx < udt->member_first+udt->member_count;
|
||||
member_idx += 1)
|
||||
{
|
||||
RDI_EnumMember *src = rdi_element_from_name_idx(rdi, EnumMembers, member_idx);
|
||||
E_EnumVal *dst = &enum_vals[member_idx-udt->member_first];
|
||||
dst->name.str = rdi_string_from_idx(rdi, src->name_string_idx, &dst->name.size);
|
||||
dst->val = src->val;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = enum_vals_count;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
type->enum_vals = enum_vals;
|
||||
type->direct_type_key = direct_type_key;
|
||||
}
|
||||
|
||||
//- rjf: constructed types
|
||||
else if(RDI_TypeKind_FirstConstructed <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastConstructed)
|
||||
{
|
||||
// rjf: unpack direct type
|
||||
B32 direct_type_is_good = 0;
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->constructed.direct_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->constructed.direct_type_idx, rdi_idx);
|
||||
direct_type_is_good = 1;
|
||||
direct_type_byte_size = (U64)direct_type_node->byte_size;
|
||||
}
|
||||
|
||||
// rjf: construct based on kind
|
||||
switch(rdi_type->kind)
|
||||
{
|
||||
case RDI_TypeKind_Modifier:
|
||||
{
|
||||
E_TypeFlags flags = 0;
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Const)
|
||||
{
|
||||
flags |= E_TypeFlag_Const;
|
||||
}
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Volatile)
|
||||
{
|
||||
flags |= E_TypeFlag_Volatile;
|
||||
}
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Restrict)
|
||||
{
|
||||
flags |= E_TypeFlag_Restrict;
|
||||
}
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->flags = flags;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Ptr:
|
||||
case RDI_TypeKind_LRef:
|
||||
case RDI_TypeKind_RRef:
|
||||
{
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
|
||||
type->count = 1;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
|
||||
case RDI_TypeKind_Array:
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = (U64)rdi_type->byte_size;
|
||||
type->count = enum_vals_count;
|
||||
type->arch = arch;
|
||||
type->enum_vals = enum_vals;
|
||||
type->direct_type_key = direct_type_key;
|
||||
}
|
||||
|
||||
//- rjf: constructed types
|
||||
else if(RDI_TypeKind_FirstConstructed <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastConstructed)
|
||||
{
|
||||
// rjf: unpack direct type
|
||||
B32 direct_type_is_good = 0;
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->constructed.direct_type_idx < type_node_idx)
|
||||
{
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = rdi_type->constructed.count;
|
||||
type->byte_size = direct_type_byte_size * type->count;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Function:
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->constructed.direct_type_idx, rdi_num);
|
||||
direct_type_is_good = 1;
|
||||
direct_type_byte_size = (U64)direct_type_node->byte_size;
|
||||
}
|
||||
|
||||
// rjf: construct based on kind
|
||||
switch(rdi_type->kind)
|
||||
{
|
||||
U32 count = rdi_type->constructed.count;
|
||||
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
|
||||
U32 check_count = 0;
|
||||
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
|
||||
if(check_count == count)
|
||||
case RDI_TypeKind_Modifier:
|
||||
{
|
||||
E_TypeFlags flags = 0;
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Const)
|
||||
{
|
||||
flags |= E_TypeFlag_Const;
|
||||
}
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Volatile)
|
||||
{
|
||||
flags |= E_TypeFlag_Volatile;
|
||||
}
|
||||
if(rdi_type->flags & RDI_TypeModifierFlag_Restrict)
|
||||
{
|
||||
flags |= E_TypeFlag_Restrict;
|
||||
}
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array(arena, E_TypeKey, type->count);
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
if(param_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
|
||||
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
|
||||
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case RDI_TypeKind_Method:
|
||||
{
|
||||
// NOTE(rjf): for methods, the `direct` type points at the owner type.
|
||||
// the return type, instead of being encoded via the `direct` type, is
|
||||
// encoded via the first parameter.
|
||||
U32 count = rdi_type->constructed.count;
|
||||
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
|
||||
U32 check_count = 0;
|
||||
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
|
||||
if(check_count == count)
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->flags = flags;
|
||||
type->arch = arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Ptr:
|
||||
case RDI_TypeKind_LRef:
|
||||
case RDI_TypeKind_RRef:
|
||||
{
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
|
||||
type->owner_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
if(param_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
|
||||
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
|
||||
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_idx);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(type->count > 0)
|
||||
{
|
||||
type->direct_type_key = type->param_type_keys[0];
|
||||
type->count -= 1;
|
||||
type->param_type_keys += 1;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case RDI_TypeKind_MemberPtr:
|
||||
{
|
||||
// rjf: unpack owner type
|
||||
E_TypeKey owner_type_key = zero_struct;
|
||||
if(rdi_type->constructed.owner_type_idx < type_node_idx)
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->byte_size = bit_size_from_arch(arch)/8;
|
||||
type->count = 1;
|
||||
type->arch = arch;
|
||||
}break;
|
||||
|
||||
case RDI_TypeKind_Array:
|
||||
{
|
||||
RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx);
|
||||
E_TypeKind owner_type_kind = e_type_kind_from_rdi(owner_type_node->kind);
|
||||
owner_type_key = e_type_key_ext(owner_type_kind, rdi_type->constructed.owner_type_idx, rdi_idx);
|
||||
}
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(e_base_ctx->modules[rdi_idx].arch)/8;
|
||||
type->owner_type_key = owner_type_key;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}break;
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = rdi_type->constructed.count;
|
||||
type->byte_size = direct_type_byte_size * type->count;
|
||||
type->arch = arch;
|
||||
}break;
|
||||
case RDI_TypeKind_Function:
|
||||
{
|
||||
U32 count = rdi_type->constructed.count;
|
||||
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
|
||||
U32 check_count = 0;
|
||||
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
|
||||
if(check_count == count)
|
||||
{
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(arch)/8;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array(arena, E_TypeKey, type->count);
|
||||
type->arch = arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
if(param_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
|
||||
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
|
||||
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case RDI_TypeKind_Method:
|
||||
{
|
||||
// NOTE(rjf): for methods, the `direct` type points at the owner type.
|
||||
// the return type, instead of being encoded via the `direct` type, is
|
||||
// encoded via the first parameter.
|
||||
U32 count = rdi_type->constructed.count;
|
||||
U32 idx_run_first = rdi_type->constructed.param_idx_run_first;
|
||||
U32 check_count = 0;
|
||||
U32 *idx_run = rdi_idx_run_from_first_count(rdi, idx_run_first, count, &check_count);
|
||||
if(check_count == count)
|
||||
{
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(arch)/8;
|
||||
type->owner_type_key = direct_type_key;
|
||||
type->count = count;
|
||||
type->param_type_keys = push_array_no_zero(arena, E_TypeKey, type->count);
|
||||
type->arch = arch;
|
||||
for(U32 idx = 0; idx < type->count; idx += 1)
|
||||
{
|
||||
U32 param_type_idx = idx_run[idx];
|
||||
if(param_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *param_type_node = rdi_element_from_name_idx(rdi, TypeNodes, param_type_idx);
|
||||
E_TypeKind param_kind = e_type_kind_from_rdi(param_type_node->kind);
|
||||
type->param_type_keys[idx] = e_type_key_ext(param_kind, param_type_idx, rdi_num);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(type->count > 0)
|
||||
{
|
||||
type->direct_type_key = type->param_type_keys[0];
|
||||
type->count -= 1;
|
||||
type->param_type_keys += 1;
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case RDI_TypeKind_MemberPtr:
|
||||
{
|
||||
// rjf: unpack owner type
|
||||
E_TypeKey owner_type_key = zero_struct;
|
||||
if(rdi_type->constructed.owner_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *owner_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->constructed.owner_type_idx);
|
||||
E_TypeKind owner_type_kind = e_type_kind_from_rdi(owner_type_node->kind);
|
||||
owner_type_key = e_type_key_ext(owner_type_kind, rdi_type->constructed.owner_type_idx, rdi_num);
|
||||
}
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = bit_size_from_arch(arch)/8;
|
||||
type->owner_type_key = owner_type_key;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = arch;
|
||||
}break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: alias types
|
||||
else if(rdi_type->kind == RDI_TypeKind_Alias)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
|
||||
//- rjf: alias types
|
||||
else if(rdi_type->kind == RDI_TypeKind_Alias)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_idx);
|
||||
direct_type_byte_size = direct_type_node->byte_size;
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->user_defined.direct_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->user_defined.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->user_defined.direct_type_idx, rdi_num);
|
||||
direct_type_byte_size = direct_type_node->byte_size;
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = arch;
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
//- rjf: bitfields
|
||||
else if(RDI_TypeKind_Bitfield == rdi_type->kind)
|
||||
{
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->bitfield.direct_type_idx < type_node_idx)
|
||||
//- rjf: bitfields
|
||||
else if(RDI_TypeKind_Bitfield == rdi_type->kind)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->bitfield.direct_type_idx, rdi_idx);
|
||||
direct_type_byte_size = direct_type_node->byte_size;
|
||||
// rjf: unpack direct type
|
||||
E_TypeKey direct_type_key = zero_struct;
|
||||
U64 direct_type_byte_size = 0;
|
||||
if(rdi_type->bitfield.direct_type_idx < type_node_idx)
|
||||
{
|
||||
RDI_TypeNode *direct_type_node = rdi_element_from_name_idx(rdi, TypeNodes, rdi_type->bitfield.direct_type_idx);
|
||||
E_TypeKind direct_type_kind = e_type_kind_from_rdi(direct_type_node->kind);
|
||||
direct_type_key = e_type_key_ext(direct_type_kind, rdi_type->bitfield.direct_type_idx, rdi_num);
|
||||
direct_type_byte_size = direct_type_node->byte_size;
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->off = (U32)rdi_type->bitfield.off;
|
||||
type->count = (U64)rdi_type->bitfield.size;
|
||||
type->arch = arch;
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->byte_size = direct_type_byte_size;
|
||||
type->direct_type_key = direct_type_key;
|
||||
type->off = (U32)rdi_type->bitfield.off;
|
||||
type->count = (U64)rdi_type->bitfield.size;
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
//- rjf: incomplete types
|
||||
else if(RDI_TypeKind_FirstIncomplete <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastIncomplete)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
//- rjf: incomplete types
|
||||
else if(RDI_TypeKind_FirstIncomplete <= rdi_type->kind && rdi_type->kind <= RDI_TypeKind_LastIncomplete)
|
||||
{
|
||||
// rjf: unpack name
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, rdi_type->user_defined.name_string_idx, &name.size);
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->arch = arch;
|
||||
}
|
||||
|
||||
// rjf: produce
|
||||
type = push_array(arena, E_Type, 1);
|
||||
type->kind = kind;
|
||||
type->name = push_str8_copy(arena, name);
|
||||
type->arch = e_base_ctx->modules[rdi_idx].arch;
|
||||
}
|
||||
|
||||
}
|
||||
}break;
|
||||
|
||||
@@ -2653,9 +2661,18 @@ e_list_gather_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U
|
||||
chunk->count += 1;
|
||||
total_count += 1;
|
||||
|
||||
//- rjf: record this offset in our hit-offset table
|
||||
{
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&off));
|
||||
U64 slot_idx = hash%hit_slots_count;
|
||||
HitOffsetNode *n = push_array(scratch.arena, HitOffsetNode, 1);
|
||||
n->off = off;
|
||||
SLLStackPush(hit_slots[slot_idx], n);
|
||||
}
|
||||
|
||||
//- rjf: read next offset, advance
|
||||
B32 read_stale = 0;
|
||||
B32 read_good = ctrl_process_memory_read(process, r1u64(off + member_element_off, off + member_size), &read_stale, &next_off, 0);
|
||||
B32 read_good = ctrl_process_memory_read(process, r1u64(off + member_element_off, off + member_element_off + member_size), &read_stale, &next_off, 0);
|
||||
if(read_stale)
|
||||
{
|
||||
retry = 1;
|
||||
|
||||
@@ -70,7 +70,7 @@ internal E_EnumValArray e_enum_val_array_from_list(Arena *arena, E_EnumValList *
|
||||
//- rjf: basic key constructors
|
||||
internal E_TypeKey e_type_key_zero(void);
|
||||
internal E_TypeKey e_type_key_basic(E_TypeKind kind);
|
||||
internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_idx);
|
||||
internal E_TypeKey e_type_key_ext(E_TypeKind kind, U32 type_idx, U32 rdi_num);
|
||||
internal E_TypeKey e_type_key_reg(Arch arch, REGS_RegCode code);
|
||||
internal E_TypeKey e_type_key_reg_alias(Arch arch, REGS_AliasCode code);
|
||||
|
||||
|
||||
@@ -150,8 +150,14 @@ ev_type_key_is_editable(E_TypeKey type_key)
|
||||
B32 done = 0;
|
||||
for(E_TypeKey t = type_key; !result && !done; t = e_type_key_direct(t))
|
||||
{
|
||||
E_TypeKind kind = e_type_kind_from_key(t);
|
||||
switch(kind)
|
||||
E_Type *type = e_type_from_key(t);
|
||||
E_TypeKind kind = type->kind;
|
||||
if(type->flags & E_TypeFlag_IsNotEditable)
|
||||
{
|
||||
result = 0;
|
||||
done = 1;
|
||||
}
|
||||
else switch(kind)
|
||||
{
|
||||
case E_TypeKind_Null:
|
||||
case E_TypeKind_Function:
|
||||
@@ -167,7 +173,6 @@ ev_type_key_is_editable(E_TypeKey type_key)
|
||||
}break;
|
||||
case E_TypeKind_Array:
|
||||
{
|
||||
E_Type *type = e_type_from_key(t);
|
||||
if(type->flags & E_TypeFlag_IsNotText)
|
||||
{
|
||||
result = 0;
|
||||
@@ -1906,17 +1911,25 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
|
||||
{
|
||||
U64 vaddr = ptr_data->value_eval.value.u64;
|
||||
E_Module *module = &e_module_nil;
|
||||
U32 module_idx = 0;
|
||||
for EachIndex(idx, e_base_ctx->modules_count)
|
||||
{
|
||||
if(contains_1u64(e_base_ctx->modules[idx].vaddr_range, vaddr))
|
||||
{
|
||||
module = &e_base_ctx->modules[idx];
|
||||
module_idx = (U32)idx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
RDI_Parsed *rdi = module->rdi;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_module(module);
|
||||
if(dbg_info == &e_dbg_info_nil)
|
||||
{
|
||||
dbg_info = e_dbg_info_from_type_key(type_key);
|
||||
}
|
||||
U32 dbg_info_num = 0;
|
||||
if(dbg_info != &e_dbg_info_nil)
|
||||
{
|
||||
dbg_info_num = (U32)(dbg_info - e_base_ctx->dbg_infos) + 1;
|
||||
}
|
||||
RDI_Parsed *rdi = dbg_info->rdi;
|
||||
U64 voff = vaddr - module->vaddr_range.min;
|
||||
B32 good_symbol_match = 0;
|
||||
|
||||
@@ -1965,7 +1978,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
|
||||
if(inline_site != 0)
|
||||
{
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, inline_site->type_idx);
|
||||
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, module_idx);
|
||||
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), inline_site->type_idx, dbg_info_num);
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, inline_site->name_string_idx, &name.size);
|
||||
if(inline_site->type_idx != 0)
|
||||
@@ -1995,7 +2008,7 @@ ev_string_iter_next(Arena *arena, EV_StringIter *it, String8 *out_string)
|
||||
U64 proc_idx = scope->proc_idx;
|
||||
RDI_Procedure *procedure = rdi_element_from_name_idx(rdi, Procedures, proc_idx);
|
||||
RDI_TypeNode *type_node = rdi_element_from_name_idx(rdi, TypeNodes, procedure->type_idx);
|
||||
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, module_idx);
|
||||
E_TypeKey type = e_type_key_ext(e_type_kind_from_rdi(type_node->kind), procedure->type_idx, dbg_info_num);
|
||||
String8 name = {0};
|
||||
name.str = rdi_string_from_idx(rdi, procedure->name_string_idx, &name.size);
|
||||
if(procedure->type_idx != 0)
|
||||
|
||||
@@ -170,7 +170,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
|
||||
case 2:
|
||||
if(2 < max)
|
||||
{
|
||||
char cont_byte = str[1];
|
||||
unsigned char cont_byte = str[1];
|
||||
if(raddbg_utf8_class[cont_byte >> 3] == 0)
|
||||
{
|
||||
result.codepoint = (byte & 0x0000001f) << 6;
|
||||
@@ -181,7 +181,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
|
||||
case 3:
|
||||
if(2 < max)
|
||||
{
|
||||
char cont_byte[2] = {str[1], str[2]};
|
||||
unsigned char cont_byte[2] = {(unsigned char)str[1], (unsigned char)str[2]};
|
||||
if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 &&
|
||||
raddbg_utf8_class[cont_byte[1] >> 3] == 0)
|
||||
{
|
||||
@@ -194,7 +194,7 @@ raddbg_decode_utf8(char *str, unsigned __int64 max)
|
||||
case 4:
|
||||
if(3 < max)
|
||||
{
|
||||
char cont_byte[3] = {str[1], str[2], str[3]};
|
||||
unsigned char cont_byte[3] = {(unsigned char)str[1], (unsigned char)str[2], (unsigned char)str[3]};
|
||||
if(raddbg_utf8_class[cont_byte[0] >> 3] == 0 &&
|
||||
raddbg_utf8_class[cont_byte[1] >> 3] == 0 &&
|
||||
raddbg_utf8_class[cont_byte[2] >> 3] == 0)
|
||||
@@ -431,6 +431,9 @@ raddbg_annotate_vaddr_range__impl(void *ptr, unsigned __int64 size, char *fmt, .
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
buffer_size = RADDBG_MARKUP_VSNPRINTF(buffer, sizeof(buffer), fmt, args);
|
||||
buffer_size = ((buffer_size < 0) ? 0 :
|
||||
(buffer_size > sizeof(buffer)) ? sizeof(buffer) :
|
||||
buffer_size);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -52,6 +52,9 @@ union RDI_SHA1 {RDI_U8 u8[20];};
|
||||
typedef union RDI_SHA256 RDI_SHA256;
|
||||
union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};
|
||||
|
||||
typedef union RDI_GUID RDI_GUID;
|
||||
union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//~ Overridable Enabling/Disabling Of Table Index Typechecking
|
||||
|
||||
@@ -64,7 +67,7 @@ union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};
|
||||
|
||||
// "raddbg\0\0"
|
||||
#define RDI_MAGIC_CONSTANT 0x0000676264646172
|
||||
#define RDI_ENCODING_VERSION 16
|
||||
#define RDI_ENCODING_VERSION 17
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//~ Format Types & Functions
|
||||
@@ -807,6 +810,7 @@ X(RDI_Arch, arch)\
|
||||
X(RDI_U32, exe_name_string_idx)\
|
||||
X(RDI_U64, exe_hash)\
|
||||
X(RDI_U64, voff_max)\
|
||||
X(RDI_GUID, guid)\
|
||||
X(RDI_U32, producer_name_string_idx)\
|
||||
|
||||
#define RDI_BinarySectionFlags_XList \
|
||||
@@ -1283,6 +1287,7 @@ RDI_Arch arch;
|
||||
RDI_U32 exe_name_string_idx;
|
||||
RDI_U64 exe_hash;
|
||||
RDI_U64 voff_max;
|
||||
RDI_GUID guid;
|
||||
RDI_U32 producer_name_string_idx;
|
||||
};
|
||||
|
||||
|
||||
@@ -1196,6 +1196,11 @@ rdim_bake_params_concat_in_place(RDIM_BakeParams *dst, RDIM_BakeParams *src)
|
||||
{
|
||||
dst->top_level_info.voff_max = src->top_level_info.voff_max;
|
||||
}
|
||||
if(dst->top_level_info.guid.u64[0] == 0 &&
|
||||
dst->top_level_info.guid.u64[1] == 0)
|
||||
{
|
||||
dst->top_level_info.guid = src->top_level_info.guid;
|
||||
}
|
||||
if(dst->top_level_info.producer_name.size == 0)
|
||||
{
|
||||
dst->top_level_info.producer_name = src->top_level_info.producer_name;
|
||||
|
||||
@@ -499,6 +499,7 @@ struct RDIM_TopLevelInfo
|
||||
RDIM_String8 exe_name;
|
||||
RDI_U64 exe_hash;
|
||||
RDI_U64 voff_max;
|
||||
RDI_GUID guid;
|
||||
RDIM_String8 producer_name;
|
||||
};
|
||||
|
||||
|
||||
@@ -584,6 +584,8 @@ type_coverage_eval_tests(void)
|
||||
SLLNode node1 = {0, &node2, 1};
|
||||
raddbg_pin(list(node1, the_real_next_ptr));
|
||||
|
||||
node6.next = &node1;
|
||||
|
||||
Alias1 a1 = has_enums.kind;
|
||||
Alias2 a2 = has_enums.flags;
|
||||
Alias3 a3 = has_enums;
|
||||
|
||||
@@ -548,7 +548,14 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
case WM_DPICHANGED:
|
||||
{
|
||||
F32 new_dpi = (F32)(wParam & 0xffff);
|
||||
RECT suggested_new_rect = *(RECT *)lParam;
|
||||
window->dpi = new_dpi;
|
||||
SetWindowPos(window->hwnd, 0,
|
||||
suggested_new_rect.left,
|
||||
suggested_new_rect.top,
|
||||
suggested_new_rect.right - suggested_new_rect.left,
|
||||
suggested_new_rect.bottom - suggested_new_rect.top,
|
||||
0);
|
||||
}break;
|
||||
|
||||
//- rjf: [file drop]
|
||||
@@ -565,7 +572,9 @@ os_w32_wnd_proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
U64 name_size = DragQueryFile(drop, idx, 0, 0) + 1;
|
||||
U8 *name_ptr = push_array(os_w32_event_arena, U8, name_size);
|
||||
DragQueryFile(drop, idx, (char *)name_ptr, name_size);
|
||||
str8_list_push(os_w32_event_arena, &event->strings, str8(name_ptr, name_size - 1));
|
||||
String8 path_string = str8(name_ptr, name_size - 1);
|
||||
String8 path_string__normalized = path_normalized_from_string(os_w32_event_arena, path_string);
|
||||
str8_list_push(os_w32_event_arena, &event->strings, path_string__normalized);
|
||||
}
|
||||
DragFinish(drop);
|
||||
}break;
|
||||
|
||||
+4
-2
@@ -1143,9 +1143,11 @@ pdb_has_file_ref(String8 msf_data, String8List file_list, MSF_RawStreamTable *st
|
||||
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);
|
||||
String8 path_pdbstyle_lower = lower_from_str8(temp.arena, path_pdbstyle);
|
||||
U32 off1 = pdb_strtbl_off_from_string(strtbl, path_pdbstyle);
|
||||
U32 off2 = pdb_strtbl_off_from_string(strtbl, path_pdbstyle_lower);
|
||||
temp_end(temp);
|
||||
if(off != max_U32)
|
||||
if(off1 != max_U32 || off2 != max_U32)
|
||||
{
|
||||
has_ref = 1;
|
||||
break;
|
||||
|
||||
+1
-1
@@ -851,7 +851,7 @@ rb_thread_entry_point(void *p)
|
||||
{
|
||||
unique_identifier_string = str8f(arena, "%I64x", bake_params->top_level_info.exe_hash);
|
||||
}
|
||||
if(unique_identifier_string.size == 0 && input_files.first != 0 && input_files.first->v->format == RB_FileFormat_PDB)
|
||||
if(unique_identifier_string.size == 0)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8 msf_data = input_files.first->v->data;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -252,6 +252,8 @@ RD_CmdKind_ListBreakpoints,
|
||||
RD_CmdKind_ClearOutput,
|
||||
RD_CmdKind_AddWatchPin,
|
||||
RD_CmdKind_ToggleWatchPin,
|
||||
RD_CmdKind_LoadDebugInfo,
|
||||
RD_CmdKind_UnloadDebugInfo,
|
||||
RD_CmdKind_AddTypeView,
|
||||
RD_CmdKind_AddFilePathMap,
|
||||
RD_CmdKind_EditUserTheme,
|
||||
@@ -292,6 +294,7 @@ RD_CmdKind_OpenCallStack,
|
||||
RD_CmdKind_OpenTargets,
|
||||
RD_CmdKind_OpenBreakpoints,
|
||||
RD_CmdKind_OpenWatchPins,
|
||||
RD_CmdKind_OpenDebugInfos,
|
||||
RD_CmdKind_OpenThreads,
|
||||
RD_CmdKind_OpenProcesses,
|
||||
RD_CmdKind_OpenMachines,
|
||||
@@ -525,6 +528,7 @@ X(call_stack) \
|
||||
X(targets) \
|
||||
X(breakpoints) \
|
||||
X(watch_pins) \
|
||||
X(debug_infos) \
|
||||
X(threads) \
|
||||
X(processes) \
|
||||
X(machines) \
|
||||
@@ -589,10 +593,10 @@ Z(getting_started)\
|
||||
.os_event = rd_regs()->os_event,\
|
||||
|
||||
C_LINKAGE_BEGIN
|
||||
extern String8 rd_tab_fast_path_view_name_table[24];
|
||||
extern String8 rd_tab_fast_path_query_name_table[24];
|
||||
extern RD_VocabInfo rd_vocab_info_table[352];
|
||||
extern RD_NameSchemaInfo rd_name_schema_info_table[25];
|
||||
extern String8 rd_tab_fast_path_view_name_table[25];
|
||||
extern String8 rd_tab_fast_path_query_name_table[25];
|
||||
extern RD_VocabInfo rd_vocab_info_table[358];
|
||||
extern RD_NameSchemaInfo rd_name_schema_info_table[26];
|
||||
extern String8 rd_reg_slot_code_name_table[47];
|
||||
extern Rng1U64 rd_reg_slot_range_table[47];
|
||||
extern String8 rd_binding_version_remap_old_name_table[8];
|
||||
|
||||
@@ -33,6 +33,7 @@ RD_WatchTabFastPathTable:
|
||||
{Targets "Targets" targets 1 Target "Displays, and allows editing of, the list of all targets."}
|
||||
{Breakpoints "Breakpoints" breakpoints 1 CircleFilled "Displays, and allows editing of, the list of all breakpoints."}
|
||||
{WatchPins "Watch Pins" watch_pins 1 Pin "Displays, and allows editing of, the list of all watch pins."}
|
||||
{DebugInfos "Debug Info" debug_infos 1 Module "Displays, and allows editing of, the list of all debug info files that the debugger has loaded."}
|
||||
{Threads "Threads" threads 1 Threads "Displays the list of all threads in all processes to which the debugger is attached."}
|
||||
{Processes "Processes" processes 1 Scheduler "Displays the list of all processes to which the debugger is attached."}
|
||||
{Machines "Machines" machines 1 Machine "Displays the list of all machines to which the debugger is connected."}
|
||||
@@ -91,6 +92,7 @@ RD_VocabTable:
|
||||
{type_view _ "Type View" _ Binoculars }
|
||||
{file_path_map _ "File Path Map" _ FileOutline }
|
||||
{watch_pin _ "Watch Pin" _ Pin }
|
||||
{debug_info _ "Debug Info" "Debug Info" Module }
|
||||
{watch watches "Watch" "Watches" Binoculars }
|
||||
{view _ "View" _ Binoculars }
|
||||
{breakpoint _ "Breakpoint" _ CircleFilled }
|
||||
@@ -196,6 +198,8 @@ RD_VocabTable:
|
||||
{row_height "" "Row Height" "" Null }
|
||||
{tab_height "" "Tab Height" "" Null }
|
||||
{rgba "" "RGBA" "" Palette }
|
||||
{path "" "Path" "" FileOutline }
|
||||
{guid "" "GUID" "" Null }
|
||||
}
|
||||
|
||||
@struct RD_VocabInfo:
|
||||
@@ -657,6 +661,21 @@ RD_VocabTable:
|
||||
```,
|
||||
}
|
||||
|
||||
//- rjf: debug infos
|
||||
{
|
||||
debug_info,
|
||||
```
|
||||
@row_commands(enable_cfg, duplicate_cfg, remove_cfg)
|
||||
@collection_commands(load_debug_info)
|
||||
x:
|
||||
{
|
||||
'path': @no_relativize path,
|
||||
@query 'guid': string,
|
||||
@no_revert @no_expand @default(1) 'enabled': bool,
|
||||
}
|
||||
```,
|
||||
}
|
||||
|
||||
//- rjf: file path maps
|
||||
{
|
||||
file_path_map,
|
||||
@@ -1044,6 +1063,10 @@ RD_CmdTable: // | | | |
|
||||
{AddWatchPin 1 1 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "add_watch_pin" "Add Watch Pin" "Places a watch pin at a given location (file path and line number or address)." "" "$watch_pins," }
|
||||
{ToggleWatchPin 1 0 0 0 "" Expr null Nil Null 0 0 0 0 1 1 1 Pin "toggle_watch_pin" "Toggle Watch Pin" "Places or removes a watch pin at a given location (file path and line number or address)." "" "" }
|
||||
|
||||
//- rjf: debug infos
|
||||
{LoadDebugInfo 1 1 0 0 `folder:\\"$input\\"` FilePath null Nil Null 1 0 0 0 0 1 1 Module "load_debug_info" "Load Debug Info" "Loads a debug info file." "" "$debug_infos," }
|
||||
{UnloadDebugInfo 1 1 0 0 "query:debug_infos" Cfg null Nil Null 0 0 0 0 1 1 1 Module "unload_debug_info" "Unload Debug Info" "Unloads a debug info file." "" "$debug_infos," }
|
||||
|
||||
//- rjf: type views
|
||||
{AddTypeView 0 0 0 0 "" String null Nil Null 0 0 0 0 0 0 0 Binoculars "add_type_view" "Add Type View" "Adds a new type view." "" "" }
|
||||
|
||||
|
||||
+440
-115
@@ -789,7 +789,7 @@ rd_eval_space_read(E_Space space, void *out, Rng1U64 range)
|
||||
//- rjf: meta-config reads
|
||||
case RD_EvalSpaceKind_MetaCfg:
|
||||
{
|
||||
// rjf: unpack cfg
|
||||
//- rjf: unpack cfg
|
||||
CFG_Node *root_cfg = rd_cfg_from_eval_space(space);
|
||||
String8 child_key = e_string_from_id(space.u64s[1]);
|
||||
CFG_Node *cfg = root_cfg;
|
||||
@@ -798,54 +798,85 @@ rd_eval_space_read(E_Space space, void *out, Rng1U64 range)
|
||||
cfg = cfg_node_child_from_string(root_cfg, child_key);
|
||||
}
|
||||
|
||||
// rjf: determine data to read from, depending on child type in schema
|
||||
//- rjf: determine data to read from, depending on child type in schema
|
||||
String8 read_data = {0};
|
||||
if(child_key.size != 0)
|
||||
{
|
||||
MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, root_cfg->string);
|
||||
MD_Node *expr_child_schema = &md_nil_node;
|
||||
// rjf: get schemas for the accessed child
|
||||
MD_Node *child_schema = &md_nil_node;
|
||||
for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next)
|
||||
MD_Node *expr_child_schema = &md_nil_node;
|
||||
{
|
||||
child_schema = md_child_from_string(n->v, child_key, 0);
|
||||
if(child_schema != &md_nil_node)
|
||||
MD_NodePtrList schemas = cfg_schemas_from_name(scratch.arena, rd_state->cfg_schema_table, root_cfg->string);
|
||||
for(MD_NodePtrNode *n = schemas.first; n != 0 && child_schema == &md_nil_node; n = n->next)
|
||||
{
|
||||
expr_child_schema = md_child_from_string(n->v, str8_lit("expression"), 0);
|
||||
child_schema = md_child_from_string(n->v, child_key, 0);
|
||||
if(child_schema != &md_nil_node)
|
||||
{
|
||||
expr_child_schema = md_child_from_string(n->v, str8_lit("expression"), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
String8 child_type_name = child_schema->first->string;
|
||||
|
||||
// rjf: get value string (or default fallback)
|
||||
String8 value_string = cfg->first->string;
|
||||
if(value_string.size == 0)
|
||||
{
|
||||
value_string = md_tag_from_string(child_schema, str8_lit("default"), 0)->first->string;
|
||||
}
|
||||
|
||||
// rjf: if this is an override child to a parent, fall back on defaults from parents
|
||||
if(value_string.size == 0 && !md_node_is_nil(md_tag_from_string(child_schema, str8_lit("override"), 0)))
|
||||
{
|
||||
for(CFG_Node *parent = root_cfg->parent; parent != &cfg_nil_node; parent = parent->parent)
|
||||
{
|
||||
CFG_Node *parent_child_w_key = cfg_node_child_from_string(parent, child_key);
|
||||
if(parent_child_w_key != &cfg_nil_node)
|
||||
{
|
||||
value_string = parent_child_w_key->first->string;
|
||||
break;
|
||||
}
|
||||
value_string = rd_default_setting_from_names(parent->string, child_key);
|
||||
if(value_string.size != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: if this is a query -> compute the value string based on query path
|
||||
if(md_node_has_tag(child_schema, str8_lit("query"), 0))
|
||||
{
|
||||
// TODO(rjf): this needs to be replaced by hooks
|
||||
if(str8_match(child_schema->string, str8_lit("guid"), 0))
|
||||
{
|
||||
Access *access = access_open();
|
||||
String8 path = rd_path_from_cfg(root_cfg);
|
||||
U64 timestamp = 0;
|
||||
try_u64_from_str8_c_rules(cfg_node_child_from_string(root_cfg, str8_lit("timestamp"))->first->string, ×tamp);
|
||||
DI_Key key = di_key_from_path_timestamp(path, timestamp);
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, key, 0, 0);
|
||||
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
|
||||
Guid guid = {0};
|
||||
MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid));
|
||||
value_string = string_from_guid(scratch.arena, guid);
|
||||
access_close(access);
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: textual data
|
||||
if(str8_match(child_type_name, str8_lit("path"), 0) ||
|
||||
str8_match(child_type_name, str8_lit("path_pt"), 0) ||
|
||||
str8_match(child_type_name, str8_lit("code_string"), 0) ||
|
||||
str8_match(child_type_name, str8_lit("expr_string"), 0) ||
|
||||
str8_match(child_type_name, str8_lit("string"), 0))
|
||||
{
|
||||
read_data = cfg->first->string;
|
||||
read_data = value_string;
|
||||
}
|
||||
|
||||
// rjf: non-textual data
|
||||
else
|
||||
{
|
||||
String8 value_string = cfg->first->string;
|
||||
if(value_string.size == 0)
|
||||
{
|
||||
value_string = md_tag_from_string(child_schema, str8_lit("default"), 0)->first->string;
|
||||
}
|
||||
if(value_string.size == 0 && !md_node_is_nil(md_tag_from_string(child_schema, str8_lit("override"), 0)))
|
||||
{
|
||||
for(CFG_Node *parent = root_cfg->parent; parent != &cfg_nil_node; parent = parent->parent)
|
||||
{
|
||||
CFG_Node *parent_child_w_key = cfg_node_child_from_string(parent, child_key);
|
||||
if(parent_child_w_key != &cfg_nil_node)
|
||||
{
|
||||
value_string = parent_child_w_key->first->string;
|
||||
break;
|
||||
}
|
||||
value_string = rd_default_setting_from_names(parent->string, child_key);
|
||||
if(value_string.size != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
E_Key parent_key = {0};
|
||||
if(expr_child_schema != &md_nil_node && child_schema != expr_child_schema)
|
||||
{
|
||||
@@ -2224,11 +2255,22 @@ rd_view_ui(Rng2F32 rect)
|
||||
{
|
||||
default:
|
||||
{
|
||||
U64 vaddr = eval.value.u64;
|
||||
CTRL_Entity *process = rd_ctrl_entity_from_eval_space(eval.space);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
U64 voff = ctrl_voff_from_vaddr(module, vaddr);
|
||||
U64 voff = 0;
|
||||
DI_Key dbgi_key = {0};
|
||||
if(eval.space.kind == CTRL_EvalSpaceKind_Entity)
|
||||
{
|
||||
U64 vaddr = eval.value.u64;
|
||||
CTRL_Entity *process = rd_ctrl_entity_from_eval_space(eval.space);
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, vaddr);
|
||||
dbgi_key = ctrl_dbgi_key_from_module(module);
|
||||
voff = ctrl_voff_from_vaddr(module, vaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
voff = eval.value.u64;
|
||||
E_DbgInfo *dbg_info = e_dbg_info_from_type_key(eval.irtree.type_key);
|
||||
dbgi_key = dbg_info->dbgi_key;
|
||||
}
|
||||
{
|
||||
Access *access = access_open();
|
||||
RDI_Parsed *rdi = di_rdi_from_key(access, dbgi_key, 0, 0);
|
||||
@@ -3998,7 +4040,9 @@ rd_view_ui(Rng2F32 rect)
|
||||
|
||||
// rjf: apply type note
|
||||
if(!(cell_info.flags & RD_WatchCellFlag_NoEval) &&
|
||||
cell->eval.space.kind == CTRL_EvalSpaceKind_Entity &&
|
||||
e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Null &&
|
||||
(cell->eval.space.kind == E_SpaceKind_Null ||
|
||||
cell->eval.space.kind == CTRL_EvalSpaceKind_Entity) &&
|
||||
row_info->callstack_thread == &ctrl_entity_nil &&
|
||||
e_type_kind_from_key(cell->eval.irtree.type_key) != E_TypeKind_Function)
|
||||
UI_FontSize(ui_top_font_size()*0.9f)
|
||||
@@ -5176,6 +5220,19 @@ rd_window_frame(void)
|
||||
cfg_node_release(rd_state->cfg, cfg_node_child_from_string(window, str8_lit("maximized")));
|
||||
}
|
||||
|
||||
//- rjf: DPI changes -> xform font size / window size
|
||||
F32 dpi = os_dpi_from_window(ws->os);
|
||||
if(dpi != ws->last_dpi)
|
||||
{
|
||||
fnt_reset();
|
||||
F32 current_font_size = rd_font_size();
|
||||
F32 new_font_size = current_font_size * (dpi / ws->last_dpi);
|
||||
new_font_size = Clamp(6.f, new_font_size, 72.f);
|
||||
CFG_Node *font_size_cfg = cfg_node_child_from_string_or_alloc(rd_state->cfg, window, str8_lit("font_size"));
|
||||
cfg_node_new_replacef(rd_state->cfg, font_size_cfg, "%I64u", (U64)new_font_size);
|
||||
ws->last_dpi = dpi;
|
||||
}
|
||||
|
||||
//- rjf: commit position
|
||||
Rng2F32 window_rect = os_rect_from_window(ws->os);
|
||||
if(!is_fullscreen && !is_maximized && !is_minimized)
|
||||
@@ -5690,75 +5747,73 @@ rd_window_frame(void)
|
||||
////////////////////////////
|
||||
//- rjf: @window_ui_part drop-completion context menu
|
||||
//
|
||||
if(ws->drop_completion_paths.node_count != 0)
|
||||
if(ws->top_drop_completion_task != 0)
|
||||
{
|
||||
RD_DropCompletionTask *task = ws->top_drop_completion_task;
|
||||
B32 done = 0;
|
||||
UI_CtxMenu(rd_state->drop_completion_key) UI_PrefWidth(ui_em(40.f, 1.f)) UI_TagF("implicit")
|
||||
{
|
||||
UI_TagF("weak")
|
||||
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
|
||||
// rjf: file names
|
||||
UI_TagF("weak") UI_Row UI_Padding(ui_em(1.25f, 1.f))
|
||||
{
|
||||
UI_Row UI_Padding(ui_em(1.f, 1.f))
|
||||
String8List strings = {0};
|
||||
U64 idx = 0;
|
||||
for(String8Node *n = task->paths.first; n != 0 && idx < 20; n = n->next, idx += 1)
|
||||
{
|
||||
UI_PrefWidth(ui_em(2.f, 1.f)) RD_Font(RD_FontSlot_Icons) ui_label(rd_icon_kind_text_table[RD_IconKind_FileOutline]);
|
||||
UI_PrefWidth(ui_text_dim(10, 1)) ui_label(n->string);
|
||||
str8_list_push(scratch.arena, &strings, str8_skip_last_slash(n->string));
|
||||
if(idx+1 == 20)
|
||||
{
|
||||
str8_list_push(scratch.arena, &strings, str8_lit("..."));
|
||||
}
|
||||
}
|
||||
StringJoin join = {.sep = str8_lit(", ")};
|
||||
String8 string = str8_list_join(scratch.arena, &strings, &join);
|
||||
UI_PrefWidth(ui_pct(1, 0)) ui_label(string);
|
||||
}
|
||||
ui_divider(ui_em(1.f, 1.f));
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "Add File%s As Target%s",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
|
||||
|
||||
// rjf: option to add EXEs as targets
|
||||
if(task->exe)
|
||||
{
|
||||
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "Add as target%s", (task->paths.node_count > 1) ? "s" : "")))
|
||||
{
|
||||
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string);
|
||||
}
|
||||
ui_ctx_menu_close();
|
||||
}
|
||||
if(ws->drop_completion_paths.node_count == 1)
|
||||
{
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Play, 0, "Add File%s As Target%s And Run",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
|
||||
{
|
||||
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
|
||||
for(String8Node *n = task->paths.first; n != 0; n = n->next)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string);
|
||||
}
|
||||
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
|
||||
if(processes.count != 0)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_KillAll);
|
||||
}
|
||||
rd_cmd(RD_CmdKind_Run);
|
||||
ui_ctx_menu_close();
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
if(ws->drop_completion_paths.node_count == 1)
|
||||
|
||||
// rjf: option to load files as debug info
|
||||
if(task->dbg)
|
||||
{
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_StepInto, 0, "Add File%s As Target%s And Step Into",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Module, 0, "Load as debug info")))
|
||||
{
|
||||
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
|
||||
for(String8Node *n = task->paths.first; n != 0; n = n->next)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_AddTarget, .file_path = n->string);
|
||||
rd_cmd(RD_CmdKind_LoadDebugInfo, .file_path = n->string);
|
||||
}
|
||||
CTRL_EntityArray processes = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Process);
|
||||
if(processes.count != 0)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_KillAll);
|
||||
}
|
||||
rd_cmd(RD_CmdKind_StepInto);
|
||||
ui_ctx_menu_close();
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_Target, 0, "View File%s",
|
||||
(ws->drop_completion_paths.node_count > 1) ? "s" : "")))
|
||||
|
||||
// rjf: option to just open & view the file contents
|
||||
if(ui_clicked(rd_icon_buttonf(RD_IconKind_FileOutline, 0, "View file%s contents", (task->paths.node_count > 1) ? "s'" : "")))
|
||||
{
|
||||
for(String8Node *n = ws->drop_completion_paths.first; n != 0; n = n->next)
|
||||
for(String8Node *n = task->paths.first; n != 0; n = n->next)
|
||||
{
|
||||
rd_cmd(RD_CmdKind_Open, .file_path = n->string);
|
||||
}
|
||||
done = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: pop task, close context menu if needed, when done
|
||||
if(done)
|
||||
{
|
||||
SLLStackPop(ws->top_drop_completion_task);
|
||||
if(ws->top_drop_completion_task == 0)
|
||||
{
|
||||
ui_ctx_menu_close();
|
||||
}
|
||||
}
|
||||
@@ -8292,23 +8347,45 @@ rd_window_frame(void)
|
||||
{
|
||||
B32 need_drop_completion = 0;
|
||||
arena_clear(ws->drop_completion_arena);
|
||||
MemoryZeroStruct(&ws->drop_completion_paths);
|
||||
ws->top_drop_completion_task = 0;
|
||||
ws->drop_completion_panel = panel->cfg->id;
|
||||
String8List exe_paths = {0};
|
||||
String8List dbg_paths = {0};
|
||||
for(String8Node *n = evt->paths.first; n != 0; n = n->next)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
String8 path = n->string;
|
||||
if(str8_match(str8_skip_last_dot(path), str8_lit("exe"), StringMatchFlag_CaseInsensitive))
|
||||
String8 ext = str8_skip_last_dot(path);
|
||||
if(str8_match(ext, str8_lit("exe"), StringMatchFlag_CaseInsensitive))
|
||||
{
|
||||
str8_list_push(ws->drop_completion_arena, &ws->drop_completion_paths, push_str8_copy(ws->drop_completion_arena, path));
|
||||
need_drop_completion = 1;
|
||||
str8_list_push(ws->drop_completion_arena, &exe_paths, str8_copy(ws->drop_completion_arena, path));
|
||||
}
|
||||
else if(str8_match(ext, str8_lit("pdb"), StringMatchFlag_CaseInsensitive) ||
|
||||
str8_match(ext, str8_lit("rdi"), StringMatchFlag_CaseInsensitive))
|
||||
{
|
||||
str8_list_push(ws->drop_completion_arena, &dbg_paths, str8_copy(ws->drop_completion_arena, path));
|
||||
}
|
||||
else
|
||||
{
|
||||
rd_cmd(RD_CmdKind_Open, .file_path = path);
|
||||
rd_cmd(RD_CmdKind_Open, .file_path = path, .panel = panel->cfg->id);
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
if(need_drop_completion)
|
||||
if(dbg_paths.node_count != 0)
|
||||
{
|
||||
RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1);
|
||||
SLLStackPush(ws->top_drop_completion_task, t);
|
||||
t->dbg = 1;
|
||||
t->paths = dbg_paths;
|
||||
}
|
||||
if(exe_paths.node_count != 0)
|
||||
{
|
||||
RD_DropCompletionTask *t = push_array(ws->drop_completion_arena, RD_DropCompletionTask, 1);
|
||||
SLLStackPush(ws->top_drop_completion_task, t);
|
||||
t->exe = 1;
|
||||
t->paths = exe_paths;
|
||||
}
|
||||
if(ws->top_drop_completion_task != 0)
|
||||
{
|
||||
ui_ctx_menu_open(rd_state->drop_completion_key, ui_key_zero(), evt->pos);
|
||||
}
|
||||
@@ -8547,7 +8624,7 @@ rd_window_frame(void)
|
||||
}
|
||||
|
||||
// rjf: soft circle around mouse
|
||||
if(box->hot_t > 0.01f) DR_ClipScope(box->rect)
|
||||
if(box->hot_t > 0.01f) DR_ClipScope(intersect_2f32(box->rect, dr_top_clip()))
|
||||
{
|
||||
Vec4F32 color = hover_color;
|
||||
color.w *= 0.02f;
|
||||
@@ -9297,7 +9374,7 @@ rd_code_color_slot_from_txt_token_kind_lookup_string(TXT_TokenKind kind, String8
|
||||
// rjf: try to map using asynchronous matching system
|
||||
if(!mapped && kind == TXT_TokenKind_Identifier)
|
||||
{
|
||||
DI_Match match = di_match_from_string(string, 0, e_base_ctx->primary_module->dbgi_key, 0);
|
||||
DI_Match match = di_match_from_string(string, 0, di_key_zero(), 0);
|
||||
RDI_SectionKind section_kind = match.section_kind;
|
||||
mapped = 1;
|
||||
switch(section_kind)
|
||||
@@ -9935,6 +10012,12 @@ rd_init(CmdLine *cmdln)
|
||||
cfg_node_new(rd_state->cfg, cfg_node_root(), str8_lit("transient"));
|
||||
}
|
||||
|
||||
// rjf: set up loaded debug info cache
|
||||
{
|
||||
rd_state->loaded_dbg_info_slots_count = 4096;
|
||||
rd_state->loaded_dbg_info_slots = push_array(arena, RD_LoadedDbgInfoSlot, rd_state->loaded_dbg_info_slots_count);
|
||||
}
|
||||
|
||||
// rjf: set up window cache
|
||||
{
|
||||
rd_state->window_state_slots_count = 64;
|
||||
@@ -10028,7 +10111,14 @@ rd_init(CmdLine *cmdln)
|
||||
String8List passthrough_args_list = {0};
|
||||
for(String8Node *n = target_args.first->next; n != 0; n = n->next)
|
||||
{
|
||||
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
|
||||
if(str8_find_needle(n->string, 0, str8_lit(" "), 0) < n->string.size)
|
||||
{
|
||||
str8_list_pushf(scratch.arena, &passthrough_args_list, "\"%S\"", n->string);
|
||||
}
|
||||
else
|
||||
{
|
||||
str8_list_push(scratch.arena, &passthrough_args_list, n->string);
|
||||
}
|
||||
}
|
||||
StringJoin join = {str8_lit(""), str8_lit(" "), str8_lit("")};
|
||||
arguments_string = str8_list_join(scratch.arena, &passthrough_args_list, &join);
|
||||
@@ -10290,6 +10380,76 @@ rd_frame(void)
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: apply debug info config trees -> loaded debug info cache
|
||||
//
|
||||
{
|
||||
U64 current_update_tick_idx = update_tick_idx();
|
||||
|
||||
//- rjf: for each debug info config, reflect in cache - open if needed
|
||||
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
|
||||
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
|
||||
{
|
||||
// rjf: unpack debug info config
|
||||
CFG_Node *di = n->v;
|
||||
String8 path = rd_path_from_cfg(di);
|
||||
CFG_Node *di_timestamp = cfg_node_child_from_string(di, str8_lit("timestamp"));
|
||||
U64 timestamp = 0;
|
||||
try_u64_from_str8_c_rules(di_timestamp->first->string, ×tamp);
|
||||
DI_Key key = di_key_from_path_timestamp(path, timestamp);
|
||||
|
||||
// rjf: touch in cache
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&key));
|
||||
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
|
||||
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
|
||||
RD_LoadedDbgInfoNode *node = 0;
|
||||
for(RD_LoadedDbgInfoNode *n = slot->first; n != 0; n = n->hash_next)
|
||||
{
|
||||
if(di_key_match(key, n->key))
|
||||
{
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node == 0)
|
||||
{
|
||||
node = rd_state->free_loaded_dbg_info_node;
|
||||
if(node)
|
||||
{
|
||||
SLLStackPop_N(rd_state->free_loaded_dbg_info_node, hash_next);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = push_array(rd_state->arena, RD_LoadedDbgInfoNode, 1);
|
||||
}
|
||||
DLLPushBack_NP(slot->first, slot->last, node, hash_next, hash_prev);
|
||||
node->key = key;
|
||||
di_open(key);
|
||||
}
|
||||
node->last_tick_idx_touched = current_update_tick_idx;
|
||||
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
|
||||
DLLPushBack_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, node, lru_next, lru_prev);
|
||||
}
|
||||
|
||||
//- rjf: iterate least-recently-used loaded debug infos - if any have not been updated this tick,
|
||||
// then evict
|
||||
for(RD_LoadedDbgInfoNode *n = rd_state->loaded_dbg_info_lru_first, *next = 0; n != 0; n = next)
|
||||
{
|
||||
next = n->lru_next;
|
||||
if(n->last_tick_idx_touched >= current_update_tick_idx)
|
||||
{
|
||||
break;
|
||||
}
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&n->key));
|
||||
U64 slot_idx = hash%rd_state->loaded_dbg_info_slots_count;
|
||||
RD_LoadedDbgInfoSlot *slot = &rd_state->loaded_dbg_info_slots[slot_idx];
|
||||
DLLRemove_NP(rd_state->loaded_dbg_info_lru_first, rd_state->loaded_dbg_info_lru_last, n, lru_next, lru_prev);
|
||||
DLLRemove_NP(slot->first, slot->last, n, hash_next, hash_prev);
|
||||
SLLStackPush_N(rd_state->free_loaded_dbg_info_node, n, hash_next);
|
||||
di_close(n->key, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: garbage collect untouched immediate cfg trees
|
||||
//
|
||||
@@ -10756,7 +10916,56 @@ rd_frame(void)
|
||||
ProfScope("loop - consume events in core, tick engine, and repeat") for(U64 cmd_process_loop_idx = 0; cmd_process_loop_idx < 3; cmd_process_loop_idx += 1)
|
||||
{
|
||||
////////////////////////////
|
||||
//- rjf: unpack eval-dependent info
|
||||
//- rjf: gather all unique debug info keys, build map
|
||||
//
|
||||
typedef struct DbgInfoNode DbgInfoNode;
|
||||
struct DbgInfoNode
|
||||
{
|
||||
DbgInfoNode *hash_next;
|
||||
DbgInfoNode *order_next;
|
||||
DI_Key key;
|
||||
U64 idx;
|
||||
};
|
||||
U64 dbg_info_slots_count = 4096;
|
||||
DbgInfoNode **dbg_info_slots = push_array(scratch.arena, DbgInfoNode *, dbg_info_slots_count);
|
||||
DbgInfoNode *first_dbg_info = 0;
|
||||
DbgInfoNode *last_dbg_info = 0;
|
||||
U64 dbg_infos_count = 0;
|
||||
{
|
||||
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
|
||||
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
|
||||
{
|
||||
CFG_Node *di = n->v;
|
||||
String8 path = rd_path_from_cfg(di);
|
||||
CFG_Node *timestamp_node = cfg_node_child_from_string(di, str8_lit("timestamp"));
|
||||
U64 timestamp = 0;
|
||||
try_u64_from_str8_c_rules(timestamp_node->first->string, ×tamp);
|
||||
DI_Key key = di_key_from_path_timestamp(path, timestamp);
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&key));
|
||||
U64 slot_idx = hash%dbg_info_slots_count;
|
||||
DbgInfoNode *node = 0;
|
||||
for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next)
|
||||
{
|
||||
if(di_key_match(n->key, key))
|
||||
{
|
||||
node = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(node == 0)
|
||||
{
|
||||
node = push_array(scratch.arena, DbgInfoNode, 1);
|
||||
SLLStackPush_N(dbg_info_slots[slot_idx], node, hash_next);
|
||||
SLLQueuePush_N(first_dbg_info, last_dbg_info, node, order_next);
|
||||
node->key = key;
|
||||
node->idx = dbg_infos_count;
|
||||
dbg_infos_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: unpack basic evaluation context
|
||||
//
|
||||
ProfBegin("unpack eval-dependent info");
|
||||
CTRL_Entity *process = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, rd_regs()->process);
|
||||
@@ -10767,32 +10976,67 @@ rd_frame(void)
|
||||
CTRL_Entity *module = ctrl_module_from_process_vaddr(process, rip_vaddr);
|
||||
U64 rip_voff = ctrl_voff_from_vaddr(module, rip_vaddr);
|
||||
U64 tls_root_vaddr = ctrl_tls_root_vaddr_from_thread(&d_state->ctrl_entity_store->ctx, thread->handle);
|
||||
ProfEnd();
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: produce all debug infos
|
||||
//
|
||||
U64 eval_dbg_infos_count = Max(1, dbg_infos_count);
|
||||
E_DbgInfo *eval_dbg_infos = push_array(scratch.arena, E_DbgInfo, eval_dbg_infos_count);
|
||||
E_DbgInfo *eval_dbg_infos_primary = &eval_dbg_infos[0];
|
||||
MemoryCopyStruct(eval_dbg_infos_primary, &e_dbg_info_nil);
|
||||
{
|
||||
U64 idx = 0;
|
||||
for(DbgInfoNode *n = first_dbg_info; n != 0; n = n->order_next)
|
||||
{
|
||||
eval_dbg_infos[idx].dbgi_key = n->key;
|
||||
eval_dbg_infos[idx].rdi = di_rdi_from_key(rd_state->frame_access, n->key, 0, 0);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: produce all eval modules
|
||||
//
|
||||
CTRL_EntityArray all_modules = ctrl_entity_array_from_kind(&d_state->ctrl_entity_store->ctx, CTRL_EntityKind_Module);
|
||||
U64 eval_modules_count = Max(1, all_modules.count);
|
||||
E_Module *eval_modules = push_array(scratch.arena, E_Module, eval_modules_count);
|
||||
E_Module *eval_modules_primary = &eval_modules[0];
|
||||
eval_modules_primary->rdi = &rdi_parsed_nil;
|
||||
eval_modules_primary->vaddr_range = r1u64(0, max_U64);
|
||||
DI_Key primary_dbgi_key = {0};
|
||||
ProfScope("produce all eval modules")
|
||||
{
|
||||
for EachIndex(eval_module_idx, all_modules.count)
|
||||
{
|
||||
CTRL_Entity *m = all_modules.v[eval_module_idx];
|
||||
DI_Key dbgi_key = ctrl_dbgi_key_from_module(m);
|
||||
eval_modules[eval_module_idx].arch = m->arch;
|
||||
eval_modules[eval_module_idx].dbgi_key = dbgi_key;
|
||||
eval_modules[eval_module_idx].rdi = di_rdi_from_key(rd_state->frame_access, dbgi_key, 0, 0);
|
||||
eval_modules[eval_module_idx].vaddr_range = m->vaddr_range;
|
||||
eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), CTRL_EvalSpaceKind_Entity);
|
||||
|
||||
// rjf: dbgi key -> eval dbg info num
|
||||
U32 dbg_info_num = 0;
|
||||
{
|
||||
U64 hash = u64_hash_from_str8(str8_struct(&dbgi_key));
|
||||
U64 slot_idx = hash%dbg_info_slots_count;
|
||||
for(DbgInfoNode *n = dbg_info_slots[slot_idx]; n != 0; n = n->hash_next)
|
||||
{
|
||||
if(di_key_match(n->key, dbgi_key))
|
||||
{
|
||||
dbg_info_num = n->idx+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// rjf: fill
|
||||
eval_modules[eval_module_idx].vaddr_range = m->vaddr_range;
|
||||
eval_modules[eval_module_idx].arch = m->arch;
|
||||
eval_modules[eval_module_idx].dbg_info_num = dbg_info_num;
|
||||
eval_modules[eval_module_idx].space = rd_eval_space_from_ctrl_entity(ctrl_entity_ancestor_from_kind(m, CTRL_EntityKind_Process), CTRL_EvalSpaceKind_Entity);
|
||||
if(module == m)
|
||||
{
|
||||
eval_modules_primary = &eval_modules[eval_module_idx];
|
||||
primary_dbgi_key = dbgi_key;
|
||||
eval_dbg_infos_primary = (0 < dbg_info_num && dbg_info_num <= eval_dbg_infos_count) ? &eval_dbg_infos[dbg_info_num-1] : &e_dbg_info_nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
ProfEnd();
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: begin evaluation
|
||||
@@ -10813,6 +11057,11 @@ rd_frame(void)
|
||||
ctx->thread_arch = thread->arch;
|
||||
ctx->thread_unwind_count = unwind_count;
|
||||
|
||||
//- rjf: fill debug infos
|
||||
ctx->dbg_infos = eval_dbg_infos;
|
||||
ctx->dbg_infos_count = eval_dbg_infos_count;
|
||||
ctx->primary_dbg_info = eval_dbg_infos_primary;
|
||||
|
||||
//- rjf: fill modules
|
||||
ctx->modules = eval_modules;
|
||||
ctx->modules_count = eval_modules_count;
|
||||
@@ -10939,6 +11188,7 @@ rd_frame(void)
|
||||
str8_lit("breakpoint"),
|
||||
str8_lit("watch_pin"),
|
||||
str8_lit("target"),
|
||||
str8_lit("debug_info"),
|
||||
str8_lit("file_path_map"),
|
||||
str8_lit("type_view"),
|
||||
str8_lit("recent_project"),
|
||||
@@ -11281,6 +11531,18 @@ rd_frame(void)
|
||||
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(cfgs_slice),
|
||||
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(cfgs_slice),
|
||||
}));
|
||||
e_string2typekey_map_insert(rd_frame_arena(), rd_state->meta_name2type_map, str8_lit("environment"),
|
||||
e_type_key_cons(.kind = E_TypeKind_Set,
|
||||
.name = str8_lit("environment"),
|
||||
.irext = E_TYPE_IREXT_FUNCTION_NAME(environment),
|
||||
.access = E_TYPE_ACCESS_FUNCTION_NAME(environment),
|
||||
.expand =
|
||||
{
|
||||
.info = E_TYPE_EXPAND_INFO_FUNCTION_NAME(environment),
|
||||
.range = E_TYPE_EXPAND_RANGE_FUNCTION_NAME(environment),
|
||||
.id_from_num = E_TYPE_EXPAND_ID_FROM_NUM_FUNCTION_NAME(environment),
|
||||
.num_from_id = E_TYPE_EXPAND_NUM_FROM_ID_FUNCTION_NAME(environment),
|
||||
}));
|
||||
}
|
||||
|
||||
//- rjf: add macro for collections with specific lookup rules (but no unique id rules)
|
||||
@@ -11588,8 +11850,8 @@ rd_frame(void)
|
||||
E_IRCtx *ctx = ir_ctx;
|
||||
ctx->regs_map = ctrl_string2reg_from_arch(eval_base_ctx->primary_module->arch);
|
||||
ctx->reg_alias_map = ctrl_string2alias_from_arch(eval_base_ctx->primary_module->arch);
|
||||
ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(primary_dbgi_key, rip_voff);
|
||||
ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(primary_dbgi_key, rip_voff);
|
||||
ctx->locals_map = d_query_cached_locals_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff);
|
||||
ctx->member_map = d_query_cached_member_map_from_dbgi_key_voff(eval_base_ctx->primary_dbg_info->dbgi_key, rip_voff);
|
||||
ctx->macro_map = macro_map;
|
||||
ctx->auto_hook_map = auto_hook_map;
|
||||
}
|
||||
@@ -11611,7 +11873,7 @@ rd_frame(void)
|
||||
ctx->tls_base = push_array(scratch.arena, U64, 1);
|
||||
ctx->tls_base[0] = d_query_cached_tls_base_vaddr_from_process_root_rip(process, tls_root_vaddr, rip_vaddr);
|
||||
}
|
||||
e_select_interpret_ctx(interpret_ctx, eval_modules_primary->rdi, rip_voff);
|
||||
e_select_interpret_ctx(interpret_ctx, eval_dbg_infos_primary->rdi, rip_voff);
|
||||
|
||||
////////////////////////////
|
||||
//- rjf: evaluate unpacked settings (must be used earlier than this point in the frame,
|
||||
@@ -13663,7 +13925,15 @@ rd_frame(void)
|
||||
DI_Key voff_dbgi_key = {0};
|
||||
if(!name_resolved)
|
||||
{
|
||||
DI_Match match = di_match_from_string(name, 0, e_base_ctx->primary_module->dbgi_key, 0);
|
||||
DI_Match match = {0};
|
||||
if(match.idx == 0)
|
||||
{
|
||||
match = di_match_from_string(name, 0, e_base_ctx->primary_dbg_info->dbgi_key, rd_state->frame_eval_memread_endt_us);
|
||||
}
|
||||
if(match.idx == 0)
|
||||
{
|
||||
match = di_match_from_string(name, 0, di_key_zero(), rd_state->frame_eval_memread_endt_us);
|
||||
}
|
||||
if(match.section_kind == RDI_SectionKind_Procedures)
|
||||
{
|
||||
Access *access = access_open();
|
||||
@@ -14792,6 +15062,21 @@ rd_frame(void)
|
||||
}
|
||||
}break;
|
||||
|
||||
//- rjf: debug infos
|
||||
case RD_CmdKind_LoadDebugInfo:
|
||||
{
|
||||
CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project"));
|
||||
CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info"));
|
||||
CFG_Node *path = cfg_node_new(rd_state->cfg, di, str8_lit("path"));
|
||||
cfg_node_new(rd_state->cfg, path, rd_regs()->file_path);
|
||||
}break;
|
||||
case RD_CmdKind_UnloadDebugInfo:
|
||||
{
|
||||
CFG_Node *di = cfg_node_from_id(rd_regs()->cfg);
|
||||
CFG_Node *path = cfg_node_child_from_string(di, str8_lit("path"));
|
||||
cfg_node_release(rd_state->cfg, di);
|
||||
}break;
|
||||
|
||||
//- rjf: type views
|
||||
case RD_CmdKind_AddTypeView:
|
||||
{
|
||||
@@ -15877,6 +16162,43 @@ rd_frame(void)
|
||||
switch(evt->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case D_EventKind_ModuleLoad:
|
||||
{
|
||||
CTRL_Entity *module = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, evt->module);
|
||||
CTRL_Entity *debug_info_path = ctrl_entity_child_from_kind(module, CTRL_EntityKind_DebugInfoPath);
|
||||
String8 new_path = debug_info_path->string;
|
||||
if(new_path.size != 0 && os_file_path_exists(new_path))
|
||||
{
|
||||
CFG_NodePtrList dbg_infos = cfg_node_top_level_list_from_string(scratch.arena, str8_lit("debug_info"));
|
||||
B32 path_found = 0;
|
||||
CFG_Node *found_di = &cfg_nil_node;
|
||||
for EachNode(n, CFG_NodePtrNode, dbg_infos.first)
|
||||
{
|
||||
CFG_Node *di = n->v;
|
||||
String8 path = rd_path_from_cfg(di);
|
||||
if(str8_match(path, new_path, 0))
|
||||
{
|
||||
path_found = 1;
|
||||
found_di = di;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!path_found)
|
||||
{
|
||||
CFG_Node *project = cfg_node_child_from_string(cfg_node_root(), str8_lit("project"));
|
||||
CFG_Node *di = cfg_node_new(rd_state->cfg, project, str8_lit("debug_info"));
|
||||
CFG_Node *path_root = cfg_node_new(rd_state->cfg, di, str8_lit("path"));
|
||||
CFG_Node *timestamp_root = cfg_node_new(rd_state->cfg, di, str8_lit("timestamp"));
|
||||
cfg_node_new(rd_state->cfg, path_root, new_path);
|
||||
cfg_node_newf(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CFG_Node *timestamp_root = cfg_node_child_from_string_or_alloc(rd_state->cfg, found_di, str8_lit("timestamp"));
|
||||
cfg_node_new_replacef(rd_state->cfg, timestamp_root, "%I64u", debug_info_path->timestamp);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case D_EventKind_ProcessEnd:
|
||||
if(rd_state->quit_after_success)
|
||||
{
|
||||
@@ -16251,6 +16573,19 @@ rd_frame(void)
|
||||
U64 frame_time_us = end_time_us-begin_time_us;
|
||||
rd_state->frame_time_us_history[rd_state->frame_index%ArrayCount(rd_state->frame_time_us_history)] = frame_time_us;
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: [windows] clear pages from working set shortly after startup, many of which will not be needed
|
||||
//
|
||||
#if OS_WINDOWS
|
||||
if(di_load_count() < 50)
|
||||
{
|
||||
if(rd_state->frame_index == 15) ProfScope("SetProcessWorkingSetSize")
|
||||
{
|
||||
SetProcessWorkingSetSize(GetCurrentProcess(), max_U64, max_U64);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: bump frame time counters
|
||||
//
|
||||
@@ -16287,16 +16622,6 @@ rd_frame(void)
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- rjf: [windows] clear pages from working set shortly after startup, many of which will not be needed
|
||||
//
|
||||
#if OS_WINDOWS
|
||||
if(rd_state->frame_index == 10)
|
||||
{
|
||||
SetProcessWorkingSetSize(GetCurrentProcess(), max_U64, max_U64);
|
||||
}
|
||||
#endif
|
||||
|
||||
rd_state->frame_depth -= 1;
|
||||
scratch_end(scratch);
|
||||
ProfEnd();
|
||||
|
||||
@@ -258,6 +258,16 @@ RD_FontSlot;
|
||||
////////////////////////////////
|
||||
//~ rjf: Per-Window State
|
||||
|
||||
typedef struct RD_DropCompletionTask RD_DropCompletionTask;
|
||||
struct RD_DropCompletionTask
|
||||
{
|
||||
RD_DropCompletionTask *next;
|
||||
B32 exe;
|
||||
B32 dbg;
|
||||
B32 cfg;
|
||||
String8List paths;
|
||||
};
|
||||
|
||||
typedef struct RD_WindowState RD_WindowState;
|
||||
struct RD_WindowState
|
||||
{
|
||||
@@ -298,7 +308,8 @@ struct RD_WindowState
|
||||
|
||||
// rjf: drop-completion state
|
||||
Arena *drop_completion_arena;
|
||||
String8List drop_completion_paths;
|
||||
CFG_ID drop_completion_panel;
|
||||
RD_DropCompletionTask *top_drop_completion_task;
|
||||
|
||||
// rjf: query state
|
||||
B32 query_is_active;
|
||||
@@ -343,6 +354,24 @@ struct RD_WindowStateSlot
|
||||
////////////////////////////////
|
||||
//~ rjf: Main Per-Process Graphical State
|
||||
|
||||
typedef struct RD_LoadedDbgInfoNode RD_LoadedDbgInfoNode;
|
||||
struct RD_LoadedDbgInfoNode
|
||||
{
|
||||
RD_LoadedDbgInfoNode *hash_next;
|
||||
RD_LoadedDbgInfoNode *hash_prev;
|
||||
RD_LoadedDbgInfoNode *lru_next;
|
||||
RD_LoadedDbgInfoNode *lru_prev;
|
||||
DI_Key key;
|
||||
U64 last_tick_idx_touched;
|
||||
};
|
||||
|
||||
typedef struct RD_LoadedDbgInfoSlot RD_LoadedDbgInfoSlot;
|
||||
struct RD_LoadedDbgInfoSlot
|
||||
{
|
||||
RD_LoadedDbgInfoNode *first;
|
||||
RD_LoadedDbgInfoNode *last;
|
||||
};
|
||||
|
||||
typedef struct RD_AmbiguousPathNode RD_AmbiguousPathNode;
|
||||
struct RD_AmbiguousPathNode
|
||||
{
|
||||
@@ -480,6 +509,13 @@ struct RD_State
|
||||
CFG_State *cfg;
|
||||
CFG_SchemaTable *cfg_schema_table;
|
||||
|
||||
// rjf: loaded debug info cache
|
||||
U64 loaded_dbg_info_slots_count;
|
||||
RD_LoadedDbgInfoSlot *loaded_dbg_info_slots;
|
||||
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_first;
|
||||
RD_LoadedDbgInfoNode *loaded_dbg_info_lru_last;
|
||||
RD_LoadedDbgInfoNode *free_loaded_dbg_info_node;
|
||||
|
||||
// rjf: window state cache
|
||||
U64 window_state_slots_count;
|
||||
RD_WindowStateSlot *window_state_slots;
|
||||
|
||||
@@ -294,38 +294,40 @@ E_TYPE_ACCESS_FUNCTION_DEF(schema)
|
||||
CFG_Node *child = cfg_node_child_from_string(cfg, child_schema->string);
|
||||
E_TypeKey child_type_key = zero_struct;
|
||||
B32 wrap_child_w_meta_expr = 0;
|
||||
B32 is_query_child = md_node_has_tag(child_schema, str8_lit("query"), 0);
|
||||
E_TypeFlags type_flags = (!!is_query_child * E_TypeFlag_IsNotEditable);
|
||||
if(0){}
|
||||
|
||||
//- rjf: ctrl entity members
|
||||
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("label"), 0))
|
||||
{
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsCodeText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsCodeText);
|
||||
}
|
||||
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("exe"), 0))
|
||||
{
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, E_TypeFlag_IsPathText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), entity->string.size, type_flags|E_TypeFlag_IsPathText);
|
||||
}
|
||||
else if(entity != &ctrl_entity_nil && str8_match(child_schema->string, str8_lit("dbg"), 0))
|
||||
{
|
||||
CTRL_Entity *dbg = ctrl_entity_child_from_kind(entity, CTRL_EntityKind_DebugInfoPath);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, E_TypeFlag_IsPathText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), dbg->string.size, type_flags|E_TypeFlag_IsPathText);
|
||||
}
|
||||
|
||||
//- rjf: cfg members
|
||||
else if(str8_match(child_schema->first->string, str8_lit("code_string"), 0) ||
|
||||
str8_match(child_schema->first->string, str8_lit("expr_string"), 0))
|
||||
{
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsCodeText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsCodeText);
|
||||
}
|
||||
else if(str8_match(child_schema->first->string, str8_lit("path"), 0) ||
|
||||
str8_match(child_schema->first->string, str8_lit("path_pt"), 0))
|
||||
{
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPathText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPathText);
|
||||
}
|
||||
|
||||
else if(str8_match(child_schema->first->string, str8_lit("string"), 0))
|
||||
{
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, E_TypeFlag_IsPlainText);
|
||||
child_type_key = e_type_key_cons_array(e_type_key_basic(E_TypeKind_U8), child->first->string.size, type_flags|E_TypeFlag_IsPlainText);
|
||||
}
|
||||
|
||||
//- rjf: catchall cases
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
// [ ] list of all tabs in palette
|
||||
// [ ] u64 + (ptr - ptr) seems to produce unexpected results - double check with C rules?
|
||||
//
|
||||
//- flow notes
|
||||
// [ ] "skip breakpoint, run to source", when stopped at a non-source location
|
||||
// [ ] adjust menu bar rendering when not focused
|
||||
// [ ] treat int 0x29 similarly to int3
|
||||
// [ ] auto_step, launching terminal, terminal steals focus from debugger...
|
||||
//
|
||||
//- memory view
|
||||
// [ ] have smaller visible range than entire memory
|
||||
// space, within some bounds (e.g. 64KB)
|
||||
// [ ] dynamically expand memory space, based on
|
||||
// scrolling
|
||||
// [ ] have smaller visible range than entire memory space, within some bounds (e.g. 64KB)
|
||||
// [ ] dynamically expand memory space, based on scrolling
|
||||
// [ ] fix clicking through occluded panels etc.
|
||||
// [ ] disambiguate . character in ASCII columns
|
||||
// [ ] fix type intepretations of cursor in bottom pane
|
||||
//
|
||||
//- bug fixes
|
||||
// [x] disassembly sometimes has a problem where source line annotations are
|
||||
// periodically removed/inserted... maybe updating on fs change when we
|
||||
// shouldn't, non-deterministic line annotation path?
|
||||
//
|
||||
//- watch improvements
|
||||
// [ ] *ALL* expressions in watch windows need to be editable.
|
||||
//
|
||||
@@ -113,7 +112,6 @@
|
||||
// [ ] multidimensional `array`
|
||||
// [ ] 2-vector, 3-vector, quaternion
|
||||
// [ ] audio waveform views
|
||||
// [x] linked list view
|
||||
//
|
||||
//- eval improvements
|
||||
// [ ] maybe add extra caching layer to process memory querying? we pay a pretty
|
||||
@@ -149,13 +147,6 @@
|
||||
//
|
||||
//- late-conversion performance improvements
|
||||
// [ ] live++ investigations - ctrl+alt+f11 in UE?
|
||||
// [x] investigate wide-conversion performance
|
||||
// [x] oversubscribing cores?
|
||||
// [x] conversion crashes?
|
||||
//
|
||||
//- memory usage improvements
|
||||
// [x] "root" concept in hash store, which buckets keys & allows usage code to
|
||||
// jettison a collection of keys in retained mode fashion
|
||||
//
|
||||
//- short-to-medium term future features
|
||||
// [ ] search-in-all-files
|
||||
@@ -183,20 +174,6 @@
|
||||
// [ ] font cache eviction (both for font tags, closing fp handles, and
|
||||
// rasterizations)
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Recently Completed Task Log
|
||||
//
|
||||
// [x] if a breakpoint matches the entry point's starting address, its hit count
|
||||
// is not correctly incremented.
|
||||
// [x] output: add option for scroll-to-bottom - ensure this shows up in universal ctx menu
|
||||
// [x] auto-annotations for non-locals
|
||||
// [x] []string being sized by [0], due to `.` applying to first ^string
|
||||
// [x] process memory cache sometimes is not correctly updating - best repro
|
||||
// case so far is (for some reason?) only hover evaluation - only spotted
|
||||
// on laptop in debug builds. g0 ctrl_bindings.bindings initialization.
|
||||
// [x] evaluate `foo.bar` symbol names without escape hatch?
|
||||
// [x] fastpath lookup to determine debug info relevance?
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Build Options
|
||||
|
||||
|
||||
@@ -1251,9 +1251,6 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
|
||||
CTRL_Entity *selected_thread_process = ctrl_entity_ancestor_from_kind(selected_thread, CTRL_EntityKind_Process);
|
||||
U64 selected_thread_rip_unwind_vaddr = d_query_cached_rip_from_thread_unwind(selected_thread, rd_regs()->unwind_count);
|
||||
CTRL_Entity *selected_thread_module = ctrl_module_from_process_vaddr(selected_thread_process, selected_thread_rip_unwind_vaddr);
|
||||
F32 selected_thread_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_alive_t_%p", selected_thread), 1.f);
|
||||
F32 selected_thread_module_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_module_alive_t_%p", selected_thread_module), 1.f);
|
||||
F32 selected_thread_arch_alive_t = ui_anim(ui_key_from_stringf(ui_key_zero(), "###selected_thread_arch_alive_t_%i", selected_thread->arch), 1.f);
|
||||
CTRL_Event stop_event = d_ctrl_last_stop_event();
|
||||
CTRL_Entity *stopper_thread = ctrl_entity_from_handle(&d_state->ctrl_entity_store->ctx, stop_event.entity);
|
||||
B32 is_focused = ui_is_focus_active();
|
||||
@@ -1552,9 +1549,9 @@ rd_code_slice(RD_CodeSliceParams *params, TxtPt *cursor, TxtPt *mark, S64 *prefe
|
||||
line_num <= params->line_num_range.max;
|
||||
line_num += 1, line_idx += 1)
|
||||
{
|
||||
CTRL_EntityList line_ips = params->line_ips[line_idx];
|
||||
CFG_NodePtrList line_bps = params->line_bps[line_idx];
|
||||
CFG_NodePtrList line_pins = params->line_pins[line_idx];
|
||||
CTRL_EntityList line_ips = params->line_ips[line_idx];
|
||||
CFG_NodePtrList line_bps = params->line_bps[line_idx];
|
||||
CFG_NodePtrList line_pins = params->line_pins[line_idx];
|
||||
ui_set_next_hover_cursor(OS_Cursor_HandPoint);
|
||||
ui_set_next_background_color(v4f32(0, 0, 0, 0));
|
||||
UI_Box *line_margin_box = ui_build_box_from_stringf(UI_BoxFlag_Clickable*!!(params->flags & RD_CodeSliceFlag_Clickable)|UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawActiveEffects, "line_margin_%I64x", line_num);
|
||||
|
||||
+5
-1
@@ -62,6 +62,9 @@
|
||||
"typedef union RDI_SHA256 RDI_SHA256;";
|
||||
"union RDI_SHA256 {RDI_U8 u8[32]; RDI_U64 u64[4];};";
|
||||
"";
|
||||
"typedef union RDI_GUID RDI_GUID;";
|
||||
"union RDI_GUID {RDI_U8 u8[16]; RDI_U64 u64[2];};";
|
||||
"";
|
||||
"////////////////////////////////////////////////////////////////";
|
||||
"//~ Overridable Enabling/Disabling Of Table Index Typechecking";
|
||||
"";
|
||||
@@ -74,7 +77,7 @@
|
||||
"";
|
||||
"// \"raddbg\\0\\0\"";
|
||||
"#define RDI_MAGIC_CONSTANT 0x0000676264646172";
|
||||
"#define RDI_ENCODING_VERSION 16";
|
||||
"#define RDI_ENCODING_VERSION 17";
|
||||
"";
|
||||
"////////////////////////////////////////////////////////////////";
|
||||
"//~ Format Types & Functions";
|
||||
@@ -495,6 +498,7 @@ RDI_TopLevelInfoMemberTable:
|
||||
{exe_name_string_idx RDI_U32 ""}
|
||||
{exe_hash RDI_U64 ""}
|
||||
{voff_max RDI_U64 ""}
|
||||
{guid RDI_GUID ""}
|
||||
{producer_name_string_idx RDI_U32 ""}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,22 @@
|
||||
#include "lib_rdi/rdi.c"
|
||||
#include "lib_rdi/rdi_parse.c"
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: RDI Enum <=> Base Enum
|
||||
|
||||
internal Arch
|
||||
arch_from_rdi_arch(RDI_Arch arch)
|
||||
{
|
||||
Arch result = Arch_Null;
|
||||
switch((RDI_ArchEnum)arch)
|
||||
{
|
||||
case RDI_Arch_NULL:{}break;
|
||||
case RDI_Arch_X86:{result = Arch_x86;}break;
|
||||
case RDI_Arch_X64:{result = Arch_x64;}break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Lookup Helpers
|
||||
|
||||
@@ -571,11 +587,14 @@ lane_sync(); if(flags & RDI_DumpSubsetFlag_##name) ProfScope(#name)
|
||||
{
|
||||
RDI_TopLevelInfo *tli = rdi_element_from_name_idx(rdi, TopLevelInfo, 0);
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
Guid guid = {0};
|
||||
MemoryCopy(&guid, &tli->guid, Min(sizeof guid, sizeof tli->guid));
|
||||
dumpf("\n");
|
||||
dumpf(" arch: %S\n", rdi_string_from_arch(scratch.arena, tli->arch));
|
||||
dumpf(" exe_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->exe_name_string_idx));
|
||||
dumpf(" voff_max: %#08llx\n", tli->voff_max);
|
||||
dumpf(" producer_name: '%S'\n", str8_from_rdi_string_idx(rdi, tli->producer_name_string_idx));
|
||||
dumpf(" guid: %S\n", string_from_guid(scratch.arena, guid));
|
||||
scratch_end(scratch);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,11 @@ read_only global String8 rdi_name_title_from_dump_subset_table[] =
|
||||
#undef X
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: RDI Enum <=> Base Enum
|
||||
|
||||
internal Arch arch_from_rdi_arch(RDI_Arch arch);
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Lookup Helpers
|
||||
|
||||
|
||||
@@ -1002,30 +1002,30 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
|
||||
checksum_value.size = Min(checksum->len, checksum_value.size);
|
||||
}
|
||||
|
||||
// rjf: file name -> normalized file path
|
||||
String8 file_path = seq_file_name;
|
||||
String8 file_path_normalized = lower_from_str8(scratch2.arena, str8_skip_chop_whitespace(file_path));
|
||||
// rjf: file name -> sanitized file path
|
||||
String8 file_path = seq_file_name;
|
||||
String8 file_path_sanitized = str8_copy(scratch2.arena, str8_skip_chop_whitespace(file_path));
|
||||
{
|
||||
PathStyle file_path_normalized_style = path_style_from_str8(file_path_normalized);
|
||||
String8List file_path_normalized_parts = str8_split_path(scratch2.arena, file_path_normalized);
|
||||
if(file_path_normalized_style == PathStyle_Relative)
|
||||
PathStyle file_path_sanitized_style = path_style_from_str8(file_path_sanitized);
|
||||
String8List file_path_sanitized_parts = str8_split_path(scratch2.arena, file_path_sanitized);
|
||||
if(file_path_sanitized_style == PathStyle_Relative)
|
||||
{
|
||||
String8List obj_folder_path_parts = str8_split_path(scratch2.arena, obj_folder_path);
|
||||
str8_list_concat_in_place(&obj_folder_path_parts, &file_path_normalized_parts);
|
||||
file_path_normalized_parts = obj_folder_path_parts;
|
||||
file_path_normalized_style = path_style_from_str8(obj_folder_path);
|
||||
str8_list_concat_in_place(&obj_folder_path_parts, &file_path_sanitized_parts);
|
||||
file_path_sanitized_parts = obj_folder_path_parts;
|
||||
file_path_sanitized_style = path_style_from_str8(obj_folder_path);
|
||||
}
|
||||
str8_path_list_resolve_dots_in_place(&file_path_normalized_parts, file_path_normalized_style);
|
||||
file_path_normalized = str8_path_list_join_by_style(scratch2.arena, &file_path_normalized_parts, file_path_normalized_style);
|
||||
str8_path_list_resolve_dots_in_place(&file_path_sanitized_parts, file_path_sanitized_style);
|
||||
file_path_sanitized = str8_path_list_join_by_style(scratch2.arena, &file_path_sanitized_parts, file_path_sanitized_style);
|
||||
}
|
||||
|
||||
// rjf: normalized file path -> source file node
|
||||
U64 file_path_normalized_hash = rdi_hash(file_path_normalized.str, file_path_normalized.size);
|
||||
U64 hit_path_slot = file_path_normalized_hash%hit_path_slots_count;
|
||||
// rjf: sanitized file path -> source file node
|
||||
U64 file_path_sanitized_hash = rdi_hash(file_path_sanitized.str, file_path_sanitized.size);
|
||||
U64 hit_path_slot = file_path_sanitized_hash%hit_path_slots_count;
|
||||
String8Node *hit_path_node = 0;
|
||||
for(String8Node *n = hit_path_slots[hit_path_slot]; n != 0; n = n->next)
|
||||
{
|
||||
if(str8_match(n->string, file_path_normalized, 0))
|
||||
if(str8_match(n->string, file_path_sanitized, 0))
|
||||
{
|
||||
hit_path_node = n;
|
||||
break;
|
||||
@@ -1035,11 +1035,11 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
|
||||
{
|
||||
hit_path_node = push_array(scratch2.arena, String8Node, 1);
|
||||
SLLStackPush(hit_path_slots[hit_path_slot], hit_path_node);
|
||||
hit_path_node->string = file_path_normalized;
|
||||
P2R_SrcFileStubNode *stub_n = push_array(scratch.arena, P2R_SrcFileStubNode, 1);
|
||||
hit_path_node->string = file_path_sanitized;
|
||||
P2R_SrcFileStubNode *stub_n = push_array(scratch2.arena, P2R_SrcFileStubNode, 1);
|
||||
SLLQueuePush(first_src_file_stub, last_src_file_stub, stub_n);
|
||||
src_file_stub_count += 1;
|
||||
stub_n->v.file_path = str8_copy(scratch.arena, file_path_normalized);
|
||||
stub_n->v.file_path = str8_copy(scratch.arena, file_path_sanitized);
|
||||
stub_n->v.checksum_kind = checksum_kind;
|
||||
stub_n->v.checksum = str8_copy(scratch.arena, checksum_value);
|
||||
}
|
||||
@@ -1801,7 +1801,6 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
|
||||
for EachInRange(idx, range)
|
||||
{
|
||||
CV_TypeId itype = (CV_TypeId)idx;
|
||||
if(itype < itype_first) { continue; }
|
||||
|
||||
//- rjf: push initial itype - should be final-visited-itype for this itype
|
||||
{
|
||||
@@ -4396,6 +4395,7 @@ p2r_convert(Arena *arena, P2R_ConvertParams *params)
|
||||
top_level_info.voff_max = exe_voff_max;
|
||||
if(!params->deterministic)
|
||||
{
|
||||
MemoryCopy(&top_level_info.guid.u8[0], &pdb_info->auth_guid.v[0], Min(sizeof top_level_info.guid.u8, sizeof pdb_info->auth_guid.v));
|
||||
top_level_info.producer_name = str8_lit(BUILD_TITLE_STRING_LITERAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2994,6 +2994,7 @@ rdim_bake(Arena *arena, RDIM_BakeParams *params)
|
||||
rdim_shared->baked_top_level_info.top_level_info.exe_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.exe_name);
|
||||
rdim_shared->baked_top_level_info.top_level_info.exe_hash = params->top_level_info.exe_hash;
|
||||
rdim_shared->baked_top_level_info.top_level_info.voff_max = params->top_level_info.voff_max;
|
||||
rdim_shared->baked_top_level_info.top_level_info.guid = params->top_level_info.guid;
|
||||
rdim_shared->baked_top_level_info.top_level_info.producer_name_string_idx = rdim_bake_idx_from_string(bake_strings, params->top_level_info.producer_name);
|
||||
}
|
||||
if(lane_idx() == lane_from_task_idx(1)) ProfScope("bake binary sections")
|
||||
|
||||
Vendored
+4
-4
@@ -46,9 +46,9 @@ static inline void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE]);
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define MD5_GET32LE(ptr) *((const _UNALIGNED uint32_t*)(ptr))
|
||||
# define MD5_SET32LE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = (x)
|
||||
# define MD5_SET64LE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = (x)
|
||||
# define MD5_GET32LE(ptr) *((const __unaligned uint32_t*)(ptr))
|
||||
# define MD5_SET32LE(ptr,x) *((__unaligned uint32_t*)(ptr)) = (x)
|
||||
# define MD5_SET64LE(ptr,x) *((__unaligned uint64_t*)(ptr)) = (x)
|
||||
#else
|
||||
# define MD5_GET32LE(ptr) \
|
||||
( \
|
||||
@@ -431,5 +431,5 @@ void md5_finish(md5_ctx* ctx, uint8_t digest[MD5_DIGEST_SIZE])
|
||||
}
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
# pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
Vendored
+232
-17
@@ -50,9 +50,9 @@ static inline void sha1_finish(sha1_ctx* ctx, uint8_t digest[SHA1_DIGEST_SIZE]);
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <stdlib.h>
|
||||
# define SHA1_GET32BE(ptr) _byteswap_ulong( *((const _UNALIGNED uint32_t*)(ptr)) )
|
||||
# define SHA1_SET32BE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = _byteswap_ulong(x)
|
||||
# define SHA1_SET64BE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = _byteswap_uint64(x)
|
||||
# define SHA1_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) )
|
||||
# define SHA1_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x)
|
||||
# define SHA1_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x)
|
||||
#else
|
||||
# define SHA1_GET32BE(ptr) \
|
||||
( \
|
||||
@@ -137,36 +137,86 @@ static inline int sha1_cpuid(void)
|
||||
SHA1_TARGET("ssse3,sha")
|
||||
static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
const __m128i* buffer = (const __m128i*)block;
|
||||
// in SHA1 each round has two parts:
|
||||
// 1) calculate message schedule dwords in w[i]
|
||||
// 2) do round functions to update a/b/c/d/e state values using w[i]
|
||||
|
||||
// for performing two operations in one:
|
||||
// 1) dwords need to be loaded as big-endian
|
||||
// 2) order of dwords need to be reversed for sha instructions: [0,1,2,3] -> [3,2,1,0]
|
||||
const __m128i bswap = _mm_setr_epi8(15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0);
|
||||
// w[i] in first 16 rounds is just loaded from block bytes, as 32-bit big-endian load
|
||||
|
||||
// for next rounds it is done as:
|
||||
// w[i] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16])
|
||||
// where ROL(x) = 32-bit rotate left by 1
|
||||
|
||||
// this means it is possible to keep just the last 16 of w's in circular buffer
|
||||
// and every new w calculated will need to update 1 to 3 previous w's
|
||||
|
||||
// unrolling round calculations by 4 we get:
|
||||
// w[i+0] = ROL(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16])
|
||||
// w[i+1] = ROL(w[i-2] ^ w[i-7] ^ w[i-13] ^ w[i-15])
|
||||
// w[i+2] = ROL(w[i-1] ^ w[i-6] ^ w[i-12] ^ w[i-14])
|
||||
// w[i+3] = ROL(w[i+0] ^ w[i-5] ^ w[i-11] ^ w[i-13])
|
||||
|
||||
// now if you store 4 w[..] values in 128-bit SSE register, then
|
||||
// W(i) = ROL( r0 ^ r1 ^ r2 ^ r3 )
|
||||
// with caveat that r0 lane 3 depends on W(i) lane 0
|
||||
|
||||
// [3] [2] [1] [0] // lanes
|
||||
// r0 = [ special, w[i-1], w[i-2], w[i-3] ]
|
||||
// r1 = [ w[i-5], w[i-6], w[i-7], w[i-8] ]
|
||||
// r2 = [ w[i-11], w[i-12], w[i-13], w[i-14] ]
|
||||
// r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ]
|
||||
|
||||
// in each 4-round i'th step it is possible to incrementally update new W(..) value when
|
||||
// keeping W(i) values in 4 xmm element circular buffer
|
||||
|
||||
// rounds i>0: W(i-1) = r2 ^ r3 = _mm_sha1msg1_epu32(W(i-1), W(i))
|
||||
// rounds i>1: W(i-2) = W(i-2) ^ r1 = _mm_xor_si128 (W(i-2), W(i))
|
||||
// rounds i>2: W(i-3) = ROL(W(i-3) ^ r0) = _mm_sha1msg2_epu32(W(i-3), W(i))
|
||||
// then the new W(i) can be used in round function calculations
|
||||
// _mm_sha1msg2_epu32 correctly handles r0 lane 3 dependency on W(i) lane 0
|
||||
|
||||
// to perform round functions on two SIMD registers with state as:
|
||||
// abcd = [a,b,c,d]
|
||||
// e0 = [e,0,0,0]
|
||||
// use the following code to get next abcd/e0 state 4 rounds at a time:
|
||||
|
||||
// tmp = _mm_sha1nexte_epu32(e0, W(i)) // rotates e0 and adds message dwords
|
||||
// abcd_next = _mm_sha1rnds4_epu32(abcd, tmp, Fn) // with Fn = 0..3 round function selection
|
||||
// e0_next = abcd
|
||||
|
||||
// sha1nexte is not needed on first round, just regular add32(e0, W(i)) should be used
|
||||
// after last round need to do extra rotation, which sha1nexte takes care when adding to last_e0
|
||||
|
||||
#define W(i) w[(i)%4]
|
||||
|
||||
// 4 wide round calculations
|
||||
#define QROUND(i) do { \
|
||||
/* first four rounds loads input message */ \
|
||||
/* first 4 rounds load input block */ \
|
||||
if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \
|
||||
/* update previous message dwords for next rounds */ \
|
||||
/* update message schedule */ \
|
||||
if (i > 0 && i < 17) W(i-1) = _mm_sha1msg1_epu32(W(i-1), W(i)); \
|
||||
if (i > 1 && i < 18) W(i-2) = _mm_xor_si128(W(i-2), W(i)); \
|
||||
if (i > 1 && i < 18) W(i-2) = _mm_xor_si128 (W(i-2), W(i)); \
|
||||
if (i > 2 && i < 19) W(i-3) = _mm_sha1msg2_epu32(W(i-3), W(i)); \
|
||||
/* calculate E from message dwords */ \
|
||||
if (i == 0) tmp = _mm_add_epi32(e0, W(i)); \
|
||||
/* calculate E plus message schedule */ \
|
||||
if (i == 0) tmp = _mm_add_epi32 (e0, W(i)); \
|
||||
if (i != 0) tmp = _mm_sha1nexte_epu32(e0, W(i)); \
|
||||
/* round function */ \
|
||||
/* 4 round functions */ \
|
||||
e0 = abcd; \
|
||||
abcd = _mm_sha1rnds4_epu32(abcd, tmp, (i/5)%4); \
|
||||
abcd = _mm_sha1rnds4_epu32(abcd, tmp, i/5); \
|
||||
} while(0)
|
||||
|
||||
const __m128i* buffer = (const __m128i*)block;
|
||||
|
||||
// for performing two operations in one:
|
||||
// 1) dwords need to be loaded as big-endian
|
||||
// 2) order of dwords need to be reversed for sha1 instructions: [0,1,2,3] -> [3,2,1,0]
|
||||
const __m128i bswap = _mm_setr_epi8(15,14,13,12, 11,10,9,8, 7,6,5,4, 3,2,1,0);
|
||||
|
||||
// load initial state
|
||||
__m128i abcd = _mm_loadu_si128((const __m128i*)state); // [d,c,b,a]
|
||||
__m128i e0 = _mm_loadu_si32(&state[4]); // [0,0,0,e]
|
||||
|
||||
// change dword order
|
||||
// flip dword order, to what sha1 instructions use
|
||||
abcd = _mm_shuffle_epi32(abcd, _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d] where a is in the top lane
|
||||
e0 = _mm_slli_si128(e0, 12); // [e,0,0,0] where e is in top lane
|
||||
|
||||
@@ -183,16 +233,19 @@ static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t cou
|
||||
QROUND(2);
|
||||
QROUND(3);
|
||||
QROUND(4);
|
||||
|
||||
QROUND(5);
|
||||
QROUND(6);
|
||||
QROUND(7);
|
||||
QROUND(8);
|
||||
QROUND(9);
|
||||
|
||||
QROUND(10);
|
||||
QROUND(11);
|
||||
QROUND(12);
|
||||
QROUND(13);
|
||||
QROUND(14);
|
||||
|
||||
QROUND(15);
|
||||
QROUND(16);
|
||||
QROUND(17);
|
||||
@@ -221,6 +274,159 @@ static void sha1_process_shani(uint32_t* state, const uint8_t* block, size_t cou
|
||||
|
||||
#endif // defined(__x86_64__) || defined(_M_AMD64)
|
||||
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
|
||||
#if defined(__clang__)
|
||||
# define SHA1_TARGET __attribute__((target("sha2")))
|
||||
#elif defined(__GNUC__)
|
||||
# define SHA1_TARGET __attribute__((target("+sha2")))
|
||||
#elif defined(_MSC_VER)
|
||||
# define SHA1_TARGET
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__linux__)
|
||||
# include <sys/auxv.h>
|
||||
# include <asm/hwcap.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#define SHA1_CPUID_INIT (1 << 0)
|
||||
#define SHA1_CPUID_ARM64 (1 << 1)
|
||||
|
||||
static inline int sha1_cpuid(void)
|
||||
{
|
||||
#if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2)
|
||||
int result = SHA1_CPUID_ARM64;
|
||||
#else
|
||||
static int cpuid;
|
||||
|
||||
int result = cpuid;
|
||||
if (result == 0)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
|
||||
#elif defined(__linux__)
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
int has_arm64 = hwcap & HWCAP_SHA1;
|
||||
#elif defined(__APPLE__)
|
||||
int value = 0;
|
||||
size_t valuelen = sizeof(value);
|
||||
int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA1", &value, &valuelen, NULL, 0) == 0 && value != 0;
|
||||
#else
|
||||
#error unknown platform
|
||||
#endif
|
||||
result |= SHA1_CPUID_INIT;
|
||||
if (has_arm64)
|
||||
{
|
||||
result |= SHA1_CPUID_ARM64;
|
||||
}
|
||||
|
||||
cpuid = result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SHA1_CPUID_MASK)
|
||||
result &= SHA1_CPUID_MASK;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SHA1_TARGET
|
||||
static void sha1_process_arm64(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
// code here is similar to x64 shani implementation
|
||||
|
||||
// message array is 16 element circular buffer
|
||||
// each iteration updates 4 rounds at the same time
|
||||
|
||||
#define W(i) w[(i)%4]
|
||||
|
||||
#define QROUND(i,F,k) do { \
|
||||
/* update message schedule */ \
|
||||
if (i >= 4) W(i) = vsha1su0q_u32(W(i), W(i-3), W(i-2)); \
|
||||
if (i >= 4) W(i) = vsha1su1q_u32(W(i), W(i-1)); \
|
||||
/* add round constant */ \
|
||||
uint32x4_t tmp = vaddq_u32(W(i), k); \
|
||||
/* 4 round functions */ \
|
||||
uint32_t x = e0; \
|
||||
e0 = vsha1h_u32(vgetq_lane_u32(abcd, 0)); \
|
||||
abcd = F(abcd, x, tmp); \
|
||||
} while (0)
|
||||
|
||||
const uint32x4_t k0 = vdupq_n_u32(0x5a827999);
|
||||
const uint32x4_t k1 = vdupq_n_u32(0x6ed9eba1);
|
||||
const uint32x4_t k2 = vdupq_n_u32(0x8f1bbcdc);
|
||||
const uint32x4_t k3 = vdupq_n_u32(0xca62c1d6);
|
||||
|
||||
// load state - a,b,c,d,e
|
||||
uint32x4_t abcd = vld1q_u32(state);
|
||||
uint32_t e0 = state[4];
|
||||
|
||||
do
|
||||
{
|
||||
// remember current state
|
||||
uint32x4_t last_abcd = abcd;
|
||||
uint32_t last_e0 = e0;
|
||||
|
||||
// load 64-byte block and advance pointer to next block
|
||||
uint8x16x4_t msg = vld1q_u8_x4(block);
|
||||
block += SHA1_BLOCK_SIZE;
|
||||
|
||||
uint32x4_t w[4];
|
||||
|
||||
// for first 16 w's reverse the byte order in each 32-bit lane
|
||||
W(0) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[0]));
|
||||
W(1) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[1]));
|
||||
W(2) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[2]));
|
||||
W(3) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[3]));
|
||||
|
||||
QROUND( 0, vsha1cq_u32, k0);
|
||||
QROUND( 1, vsha1cq_u32, k0);
|
||||
QROUND( 2, vsha1cq_u32, k0);
|
||||
QROUND( 3, vsha1cq_u32, k0);
|
||||
QROUND( 4, vsha1cq_u32, k0);
|
||||
|
||||
QROUND( 5, vsha1pq_u32, k1);
|
||||
QROUND( 6, vsha1pq_u32, k1);
|
||||
QROUND( 7, vsha1pq_u32, k1);
|
||||
QROUND( 8, vsha1pq_u32, k1);
|
||||
QROUND( 9, vsha1pq_u32, k1);
|
||||
|
||||
QROUND(10, vsha1mq_u32, k2);
|
||||
QROUND(11, vsha1mq_u32, k2);
|
||||
QROUND(12, vsha1mq_u32, k2);
|
||||
QROUND(13, vsha1mq_u32, k2);
|
||||
QROUND(14, vsha1mq_u32, k2);
|
||||
|
||||
QROUND(15, vsha1pq_u32, k3);
|
||||
QROUND(16, vsha1pq_u32, k3);
|
||||
QROUND(17, vsha1pq_u32, k3);
|
||||
QROUND(18, vsha1pq_u32, k3);
|
||||
QROUND(19, vsha1pq_u32, k3);
|
||||
|
||||
// update next state
|
||||
abcd = vaddq_u32(abcd, last_abcd);
|
||||
e0 += last_e0;
|
||||
}
|
||||
while (--count);
|
||||
|
||||
// save state
|
||||
vst1q_u32(state, abcd);
|
||||
state[4] = e0;
|
||||
|
||||
#undef QROUND
|
||||
#undef W
|
||||
}
|
||||
|
||||
#endif // defined(__aarch64__) || defined(_M_ARM64)
|
||||
|
||||
static void sha1_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_AMD64)
|
||||
@@ -232,12 +438,21 @@ static void sha1_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
int cpuid = sha1_cpuid();
|
||||
if (cpuid & SHA1_CPUID_ARM64)
|
||||
{
|
||||
sha1_process_arm64(state, block, count);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define F1(x,y,z) (0x5a827999 + ((x & (y ^ z)) ^ z))
|
||||
#define F2(x,y,z) (0x6ed9eba1 + (x ^ y ^ z))
|
||||
#define F3(x,y,z) (0x8f1bbcdc + ((x & y) | (z & (x | y))))
|
||||
#define F4(x,y,z) (0xca62c1d6 + (x ^ y ^ z))
|
||||
|
||||
#define W(i) w[(i+16)%16]
|
||||
#define W(i) w[(i)%16]
|
||||
|
||||
#define ROUND(i,a,b,c,d,e,F) do \
|
||||
{ \
|
||||
|
||||
+288
-108
@@ -58,9 +58,9 @@ static inline void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_S
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# include <stdlib.h>
|
||||
# define SHA256_GET32BE(ptr) _byteswap_ulong( *((const _UNALIGNED uint32_t*)(ptr)) )
|
||||
# define SHA256_SET32BE(ptr,x) *((_UNALIGNED uint32_t*)(ptr)) = _byteswap_ulong(x)
|
||||
# define SHA256_SET64BE(ptr,x) *((_UNALIGNED uint64_t*)(ptr)) = _byteswap_uint64(x)
|
||||
# define SHA256_GET32BE(ptr) _byteswap_ulong( *((const __unaligned uint32_t*)(ptr)) )
|
||||
# define SHA256_SET32BE(ptr,x) *((__unaligned uint32_t*)(ptr)) = _byteswap_ulong(x)
|
||||
# define SHA256_SET64BE(ptr,x) *((__unaligned uint64_t*)(ptr)) = _byteswap_uint64(x)
|
||||
#else
|
||||
# define SHA256_GET32BE(ptr) \
|
||||
( \
|
||||
@@ -91,6 +91,26 @@ static inline void sha224_finish(sha224_ctx* ctx, uint8_t digest[SHA224_DIGEST_S
|
||||
while (0)
|
||||
#endif
|
||||
|
||||
static const uint32_t SHA256_K[64] =
|
||||
{
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||
};
|
||||
|
||||
#if defined(__x86_64__) || defined(_M_AMD64)
|
||||
|
||||
#include <tmmintrin.h> // SSSE3
|
||||
@@ -145,47 +165,64 @@ static inline int sha256_cpuid(void)
|
||||
SHA256_TARGET("ssse3,sha")
|
||||
static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
const __m128i* buffer = (const __m128i*)block;
|
||||
// similar way how sha1 works in with shani
|
||||
|
||||
// to byteswap when doing big-ending load for message dwords
|
||||
const __m128i bswap = _mm_setr_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12);
|
||||
// first 16 rounds loads message schedule dwords as 32-bit big endian values
|
||||
|
||||
static const uint32_t K[16][4] =
|
||||
{
|
||||
{ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5 },
|
||||
{ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5 },
|
||||
{ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3 },
|
||||
{ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174 },
|
||||
{ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc },
|
||||
{ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da },
|
||||
{ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7 },
|
||||
{ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967 },
|
||||
{ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13 },
|
||||
{ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85 },
|
||||
{ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3 },
|
||||
{ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070 },
|
||||
{ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5 },
|
||||
{ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3 },
|
||||
{ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208 },
|
||||
{ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 },
|
||||
};
|
||||
// for next rounds message schedule is prepared as:
|
||||
// w[i] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16]
|
||||
|
||||
// unrolled by 4:
|
||||
// w[i+0] = SSig1(w[i-2]) + w[i-7] + SSig0(w[i-15]) + w[i-16]
|
||||
// w[i+1] = SSig1(w[i-1]) + w[i-6] + SSig0(w[i-14]) + w[i-15]
|
||||
// w[i+2] = SSig1(w[i+0]) + w[i-5] + SSig0(w[i-13]) + w[i-14]
|
||||
// w[i+3] = SSig1(w[i+1]) + w[i-4] + SSig0(w[i-12]) + w[i-13]
|
||||
|
||||
// there is tricky dependency for lanes 2 and 3 on result of lanes 0 and 1, but sha256msg2 op takes care of that
|
||||
|
||||
// by storing W[i] word in 128-bit simd register, the message schedule becomes:
|
||||
// W(i) = SSig1(r0) + r1 + SSig0(r2) + r3
|
||||
// where + is 32-bit lane addition
|
||||
|
||||
// [3] [2] [1] [0] // lanes
|
||||
// r0 = [ special, special, w[i-1], w[i-2] ]
|
||||
// r1 = [ w[i-4], w[i-5], w[i-6], w[i-7] ]
|
||||
// r2 = [ w[i-12], w[i-13], w[i-14], w[i-15] ]
|
||||
// r3 = [ w[i-13], w[i-14], w[i-15], w[i-16] ]
|
||||
|
||||
// rN's can be calculated from previous W(..) values:
|
||||
// r0 from W(i)
|
||||
// r1 from _mm_alignr_epi8(W(i), W(i-1), 4)
|
||||
// r2 from W(i-1) and W(i)
|
||||
// r3 from W(i-1)
|
||||
|
||||
// rounds i>2: W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32( W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4) ), W(i))
|
||||
// rounds i>0: W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i))
|
||||
|
||||
// round functions are done with _mm_sha256rnds2_epu32 which performs it for 2 rounds
|
||||
// thus repeat it two times, as input use W(i) + K(i) - message schedule added with sha256 constants
|
||||
|
||||
#define W(i) w[(i)%4]
|
||||
|
||||
// 4 wide round calculations
|
||||
#define QROUND(i) do { \
|
||||
/* first four rounds loads input message */ \
|
||||
/* first 4 rounds load input block */ \
|
||||
if (i < 4) W(i) = _mm_shuffle_epi8(_mm_loadu_si128(&buffer[i]), bswap); \
|
||||
/* add round constant */ \
|
||||
tmp = _mm_add_epi32(W(i), _mm_loadu_si128((const __m128i*)K[i])); \
|
||||
/* update previous message dwords for next rounds */ \
|
||||
/* update message schedule */ \
|
||||
if (i > 2 && i < 15) W(i-3) = _mm_sha256msg2_epu32(_mm_add_epi32(W(i-3), _mm_alignr_epi8(W(i), W(i-1), 4)), W(i)); \
|
||||
if (i > 0 && i < 13) W(i-1) = _mm_sha256msg1_epu32(W(i-1), W(i)); \
|
||||
/* round functions */ \
|
||||
/* add round constants */ \
|
||||
__m128i tmp = _mm_add_epi32(W(i), _mm_loadu_si128((const __m128i*)&SHA256_K[4*i])); \
|
||||
/* 4 round functions */ \
|
||||
state1 = _mm_sha256rnds2_epu32(state1, state0, tmp); \
|
||||
state0 = _mm_sha256rnds2_epu32(state0, state1, _mm_shuffle_epi32(tmp, _MM_SHUFFLE(0,0,3,2))); \
|
||||
} while(0)
|
||||
|
||||
|
||||
const __m128i* buffer = (const __m128i*)block;
|
||||
|
||||
// to byteswap when doing big-ending load for message dwords
|
||||
const __m128i bswap = _mm_setr_epi8(3,2,1,0, 7,6,5,4, 11,10,9,8, 15,14,13,12);
|
||||
|
||||
// load initial state
|
||||
__m128i abcd = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[0]), _MM_SHUFFLE(0,1,2,3)); // [a,b,c,d]
|
||||
__m128i efgh = _mm_shuffle_epi32(_mm_loadu_si128((const __m128i*)&state[4]), _MM_SHUFFLE(0,1,2,3)); // [e,f,g,h]
|
||||
@@ -200,18 +237,18 @@ static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t c
|
||||
__m128i last0 = state0;
|
||||
__m128i last1 = state1;
|
||||
|
||||
__m128i tmp, w[4];
|
||||
__m128i w[4];
|
||||
|
||||
QROUND(0);
|
||||
QROUND(1);
|
||||
QROUND(2);
|
||||
QROUND(3);
|
||||
QROUND(4);
|
||||
QROUND(5);
|
||||
QROUND(6);
|
||||
QROUND(7);
|
||||
QROUND(8);
|
||||
QROUND(9);
|
||||
QROUND( 0);
|
||||
QROUND( 1);
|
||||
QROUND( 2);
|
||||
QROUND( 3);
|
||||
QROUND( 4);
|
||||
QROUND( 5);
|
||||
QROUND( 6);
|
||||
QROUND( 7);
|
||||
QROUND( 8);
|
||||
QROUND( 9);
|
||||
QROUND(10);
|
||||
QROUND(11);
|
||||
QROUND(12);
|
||||
@@ -241,6 +278,140 @@ static void sha256_process_shani(uint32_t* state, const uint8_t* block, size_t c
|
||||
|
||||
#endif // defined(__x86_64__) || defined(_M_AMD64)
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
|
||||
#if defined(__clang__)
|
||||
# define SHA256_TARGET __attribute__((target("sha2")))
|
||||
#elif defined(__GNUC__)
|
||||
# define SHA256_TARGET __attribute__((target("+sha2")))
|
||||
#elif defined(_MSC_VER)
|
||||
# define SHA256_TARGET
|
||||
#endif
|
||||
|
||||
#include <arm_neon.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
# include <windows.h>
|
||||
#elif defined(__linux__)
|
||||
# include <sys/auxv.h>
|
||||
# include <asm/hwcap.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#define SHA256_CPUID_INIT (1 << 0)
|
||||
#define SHA256_CPUID_ARM64 (1 << 1)
|
||||
|
||||
static inline int sha256_cpuid(void)
|
||||
{
|
||||
#if defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_SHA2)
|
||||
int result = SHA256_CPUID_ARM64;
|
||||
#else
|
||||
static int cpuid;
|
||||
|
||||
int result = cpuid;
|
||||
if (result == 0)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
int has_arm64 = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
|
||||
#elif defined(__linux__)
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
int has_arm64 = hwcap & HWCAP_SHA2;
|
||||
#elif defined(__APPLE__)
|
||||
int value = 0;
|
||||
size_t valuelen = sizeof(value);
|
||||
int has_arm64 = sysctlbyname("hw.optional.arm.FEAT_SHA256", &value, &valuelen, NULL, 0) == 0 && value != 0;
|
||||
#else
|
||||
#error unknown platform
|
||||
#endif
|
||||
result |= SHA256_CPUID_INIT;
|
||||
if (has_arm64)
|
||||
{
|
||||
result |= SHA256_CPUID_ARM64;
|
||||
}
|
||||
|
||||
cpuid = result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SHA256_CPUID_MASK)
|
||||
result &= SHA256_CPUID_MASK;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SHA256_TARGET
|
||||
static void sha256_process_arm64(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
// code here is similar to x64 shani implementation
|
||||
|
||||
#define W(i) w[(i)%4]
|
||||
|
||||
#define QROUND(i) do { \
|
||||
/* load 16 round constants */ \
|
||||
if ((i % 4) == 0) rk = vld1q_u32_x4(&SHA256_K[4*i]); \
|
||||
/* first 4 rounds reverse byte order in each 32-bit lane of input block */ \
|
||||
if (i < 4) W(i) = vreinterpretq_u32_u8(vrev32q_u8(msg.val[i])); \
|
||||
/* update message schedule */ \
|
||||
if (i >= 4) W(i) = vsha256su0q_u32(W(i), W(i-3)); \
|
||||
if (i >= 4) W(i) = vsha256su1q_u32(W(i), W(i-2), W(i-1)); \
|
||||
/* add round constants */ \
|
||||
uint32x4_t tmp = vaddq_u32(W(i), rk.val[i%4]); \
|
||||
/* 4 round functions */ \
|
||||
uint32x4_t x = vstate.val[0]; \
|
||||
vstate.val[0] = vsha256hq_u32(vstate.val[0], vstate.val[1], tmp); \
|
||||
vstate.val[1] = vsha256h2q_u32(vstate.val[1], x, tmp); \
|
||||
} while (0)
|
||||
|
||||
// load initial state
|
||||
uint32x4x2_t vstate = vld1q_u32_x2(state);
|
||||
|
||||
do
|
||||
{
|
||||
// remember current state
|
||||
uint32x4x2_t vlast = vstate;
|
||||
|
||||
// load 64-byte block
|
||||
uint8x16x4_t msg = vld1q_u8_x4(block);
|
||||
|
||||
uint32x4x4_t rk;
|
||||
uint32x4_t w[4];
|
||||
|
||||
QROUND( 0);
|
||||
QROUND( 1);
|
||||
QROUND( 2);
|
||||
QROUND( 3);
|
||||
QROUND( 4);
|
||||
QROUND( 5);
|
||||
QROUND( 6);
|
||||
QROUND( 7);
|
||||
QROUND( 8);
|
||||
QROUND( 9);
|
||||
QROUND(10);
|
||||
QROUND(11);
|
||||
QROUND(12);
|
||||
QROUND(13);
|
||||
QROUND(14);
|
||||
QROUND(15);
|
||||
|
||||
// update next state
|
||||
vstate.val[0] = vaddq_u32(vstate.val[0], vlast.val[0]);
|
||||
vstate.val[1] = vaddq_u32(vstate.val[1], vlast.val[1]);
|
||||
|
||||
block += SHA256_BLOCK_SIZE;
|
||||
}
|
||||
while (--count);
|
||||
|
||||
// save the new state
|
||||
vst1q_u32_x2(state, vstate);
|
||||
|
||||
#undef QROUND
|
||||
#undef W
|
||||
}
|
||||
|
||||
#endif // defined(__aarch64__) || defined(_M_ARM64)
|
||||
|
||||
static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_AMD64)
|
||||
@@ -252,6 +423,15 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__aarch64__) || defined(_M_ARM64)
|
||||
int cpuid = sha256_cpuid();
|
||||
if (cpuid & SHA256_CPUID_ARM64)
|
||||
{
|
||||
sha256_process_arm64(state, block, count);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define Ch(x,y,z) ((x & (y ^ z)) ^ z)
|
||||
#define Maj(x,y,z) ((x & y) | (z & (x | y)))
|
||||
|
||||
@@ -262,13 +442,13 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
|
||||
#define W(i) w[(i+16)%16]
|
||||
|
||||
#define ROUND(i,a,b,c,d,e,f,g,h,K) do \
|
||||
#define ROUND(i,a,b,c,d,e,f,g,h) do \
|
||||
{ \
|
||||
uint32_t w0; \
|
||||
if (i < 16) W(i) = w0 = SHA256_GET32BE(block + i*sizeof(uint32_t)); \
|
||||
if (i >= 16) W(i) = w0 = SSig1(W(i-2)) + W(i-7) + SSig0(W(i-15)) + W(i-16); \
|
||||
\
|
||||
uint32_t t1 = h + BSig1(e) + Ch(e,f,g) + K + w0; \
|
||||
uint32_t t1 = h + BSig1(e) + Ch(e,f,g) + SHA256_K[i] + w0; \
|
||||
uint32_t t2 = BSig0(a) + Maj(a,b,c); \
|
||||
d += t1; \
|
||||
h = t1 + t2; \
|
||||
@@ -287,70 +467,70 @@ static void sha256_process(uint32_t* state, const uint8_t* block, size_t count)
|
||||
|
||||
uint32_t w[16];
|
||||
|
||||
ROUND( 0, a, b, c, d, e, f, g, h, 0x428a2f98);
|
||||
ROUND( 1, h, a, b, c, d, e, f, g, 0x71374491);
|
||||
ROUND( 2, g, h, a, b, c, d, e, f, 0xb5c0fbcf);
|
||||
ROUND( 3, f, g, h, a, b, c, d, e, 0xe9b5dba5);
|
||||
ROUND( 4, e, f, g, h, a, b, c, d, 0x3956c25b);
|
||||
ROUND( 5, d, e, f, g, h, a, b, c, 0x59f111f1);
|
||||
ROUND( 6, c, d, e, f, g, h, a, b, 0x923f82a4);
|
||||
ROUND( 7, b, c, d, e, f, g, h, a, 0xab1c5ed5);
|
||||
ROUND( 8, a, b, c, d, e, f, g, h, 0xd807aa98);
|
||||
ROUND( 9, h, a, b, c, d, e, f, g, 0x12835b01);
|
||||
ROUND(10, g, h, a, b, c, d, e, f, 0x243185be);
|
||||
ROUND(11, f, g, h, a, b, c, d, e, 0x550c7dc3);
|
||||
ROUND(12, e, f, g, h, a, b, c, d, 0x72be5d74);
|
||||
ROUND(13, d, e, f, g, h, a, b, c, 0x80deb1fe);
|
||||
ROUND(14, c, d, e, f, g, h, a, b, 0x9bdc06a7);
|
||||
ROUND(15, b, c, d, e, f, g, h, a, 0xc19bf174);
|
||||
ROUND(16, a, b, c, d, e, f, g, h, 0xe49b69c1);
|
||||
ROUND(17, h, a, b, c, d, e, f, g, 0xefbe4786);
|
||||
ROUND(18, g, h, a, b, c, d, e, f, 0x0fc19dc6);
|
||||
ROUND(19, f, g, h, a, b, c, d, e, 0x240ca1cc);
|
||||
ROUND(20, e, f, g, h, a, b, c, d, 0x2de92c6f);
|
||||
ROUND(21, d, e, f, g, h, a, b, c, 0x4a7484aa);
|
||||
ROUND(22, c, d, e, f, g, h, a, b, 0x5cb0a9dc);
|
||||
ROUND(23, b, c, d, e, f, g, h, a, 0x76f988da);
|
||||
ROUND(24, a, b, c, d, e, f, g, h, 0x983e5152);
|
||||
ROUND(25, h, a, b, c, d, e, f, g, 0xa831c66d);
|
||||
ROUND(26, g, h, a, b, c, d, e, f, 0xb00327c8);
|
||||
ROUND(27, f, g, h, a, b, c, d, e, 0xbf597fc7);
|
||||
ROUND(28, e, f, g, h, a, b, c, d, 0xc6e00bf3);
|
||||
ROUND(29, d, e, f, g, h, a, b, c, 0xd5a79147);
|
||||
ROUND(30, c, d, e, f, g, h, a, b, 0x06ca6351);
|
||||
ROUND(31, b, c, d, e, f, g, h, a, 0x14292967);
|
||||
ROUND(32, a, b, c, d, e, f, g, h, 0x27b70a85);
|
||||
ROUND(33, h, a, b, c, d, e, f, g, 0x2e1b2138);
|
||||
ROUND(34, g, h, a, b, c, d, e, f, 0x4d2c6dfc);
|
||||
ROUND(35, f, g, h, a, b, c, d, e, 0x53380d13);
|
||||
ROUND(36, e, f, g, h, a, b, c, d, 0x650a7354);
|
||||
ROUND(37, d, e, f, g, h, a, b, c, 0x766a0abb);
|
||||
ROUND(38, c, d, e, f, g, h, a, b, 0x81c2c92e);
|
||||
ROUND(39, b, c, d, e, f, g, h, a, 0x92722c85);
|
||||
ROUND(40, a, b, c, d, e, f, g, h, 0xa2bfe8a1);
|
||||
ROUND(41, h, a, b, c, d, e, f, g, 0xa81a664b);
|
||||
ROUND(42, g, h, a, b, c, d, e, f, 0xc24b8b70);
|
||||
ROUND(43, f, g, h, a, b, c, d, e, 0xc76c51a3);
|
||||
ROUND(44, e, f, g, h, a, b, c, d, 0xd192e819);
|
||||
ROUND(45, d, e, f, g, h, a, b, c, 0xd6990624);
|
||||
ROUND(46, c, d, e, f, g, h, a, b, 0xf40e3585);
|
||||
ROUND(47, b, c, d, e, f, g, h, a, 0x106aa070);
|
||||
ROUND(48, a, b, c, d, e, f, g, h, 0x19a4c116);
|
||||
ROUND(49, h, a, b, c, d, e, f, g, 0x1e376c08);
|
||||
ROUND(50, g, h, a, b, c, d, e, f, 0x2748774c);
|
||||
ROUND(51, f, g, h, a, b, c, d, e, 0x34b0bcb5);
|
||||
ROUND(52, e, f, g, h, a, b, c, d, 0x391c0cb3);
|
||||
ROUND(53, d, e, f, g, h, a, b, c, 0x4ed8aa4a);
|
||||
ROUND(54, c, d, e, f, g, h, a, b, 0x5b9cca4f);
|
||||
ROUND(55, b, c, d, e, f, g, h, a, 0x682e6ff3);
|
||||
ROUND(56, a, b, c, d, e, f, g, h, 0x748f82ee);
|
||||
ROUND(57, h, a, b, c, d, e, f, g, 0x78a5636f);
|
||||
ROUND(58, g, h, a, b, c, d, e, f, 0x84c87814);
|
||||
ROUND(59, f, g, h, a, b, c, d, e, 0x8cc70208);
|
||||
ROUND(60, e, f, g, h, a, b, c, d, 0x90befffa);
|
||||
ROUND(61, d, e, f, g, h, a, b, c, 0xa4506ceb);
|
||||
ROUND(62, c, d, e, f, g, h, a, b, 0xbef9a3f7);
|
||||
ROUND(63, b, c, d, e, f, g, h, a, 0xc67178f2);
|
||||
ROUND( 0, a, b, c, d, e, f, g, h);
|
||||
ROUND( 1, h, a, b, c, d, e, f, g);
|
||||
ROUND( 2, g, h, a, b, c, d, e, f);
|
||||
ROUND( 3, f, g, h, a, b, c, d, e);
|
||||
ROUND( 4, e, f, g, h, a, b, c, d);
|
||||
ROUND( 5, d, e, f, g, h, a, b, c);
|
||||
ROUND( 6, c, d, e, f, g, h, a, b);
|
||||
ROUND( 7, b, c, d, e, f, g, h, a);
|
||||
ROUND( 8, a, b, c, d, e, f, g, h);
|
||||
ROUND( 9, h, a, b, c, d, e, f, g);
|
||||
ROUND(10, g, h, a, b, c, d, e, f);
|
||||
ROUND(11, f, g, h, a, b, c, d, e);
|
||||
ROUND(12, e, f, g, h, a, b, c, d);
|
||||
ROUND(13, d, e, f, g, h, a, b, c);
|
||||
ROUND(14, c, d, e, f, g, h, a, b);
|
||||
ROUND(15, b, c, d, e, f, g, h, a);
|
||||
ROUND(16, a, b, c, d, e, f, g, h);
|
||||
ROUND(17, h, a, b, c, d, e, f, g);
|
||||
ROUND(18, g, h, a, b, c, d, e, f);
|
||||
ROUND(19, f, g, h, a, b, c, d, e);
|
||||
ROUND(20, e, f, g, h, a, b, c, d);
|
||||
ROUND(21, d, e, f, g, h, a, b, c);
|
||||
ROUND(22, c, d, e, f, g, h, a, b);
|
||||
ROUND(23, b, c, d, e, f, g, h, a);
|
||||
ROUND(24, a, b, c, d, e, f, g, h);
|
||||
ROUND(25, h, a, b, c, d, e, f, g);
|
||||
ROUND(26, g, h, a, b, c, d, e, f);
|
||||
ROUND(27, f, g, h, a, b, c, d, e);
|
||||
ROUND(28, e, f, g, h, a, b, c, d);
|
||||
ROUND(29, d, e, f, g, h, a, b, c);
|
||||
ROUND(30, c, d, e, f, g, h, a, b);
|
||||
ROUND(31, b, c, d, e, f, g, h, a);
|
||||
ROUND(32, a, b, c, d, e, f, g, h);
|
||||
ROUND(33, h, a, b, c, d, e, f, g);
|
||||
ROUND(34, g, h, a, b, c, d, e, f);
|
||||
ROUND(35, f, g, h, a, b, c, d, e);
|
||||
ROUND(36, e, f, g, h, a, b, c, d);
|
||||
ROUND(37, d, e, f, g, h, a, b, c);
|
||||
ROUND(38, c, d, e, f, g, h, a, b);
|
||||
ROUND(39, b, c, d, e, f, g, h, a);
|
||||
ROUND(40, a, b, c, d, e, f, g, h);
|
||||
ROUND(41, h, a, b, c, d, e, f, g);
|
||||
ROUND(42, g, h, a, b, c, d, e, f);
|
||||
ROUND(43, f, g, h, a, b, c, d, e);
|
||||
ROUND(44, e, f, g, h, a, b, c, d);
|
||||
ROUND(45, d, e, f, g, h, a, b, c);
|
||||
ROUND(46, c, d, e, f, g, h, a, b);
|
||||
ROUND(47, b, c, d, e, f, g, h, a);
|
||||
ROUND(48, a, b, c, d, e, f, g, h);
|
||||
ROUND(49, h, a, b, c, d, e, f, g);
|
||||
ROUND(50, g, h, a, b, c, d, e, f);
|
||||
ROUND(51, f, g, h, a, b, c, d, e);
|
||||
ROUND(52, e, f, g, h, a, b, c, d);
|
||||
ROUND(53, d, e, f, g, h, a, b, c);
|
||||
ROUND(54, c, d, e, f, g, h, a, b);
|
||||
ROUND(55, b, c, d, e, f, g, h, a);
|
||||
ROUND(56, a, b, c, d, e, f, g, h);
|
||||
ROUND(57, h, a, b, c, d, e, f, g);
|
||||
ROUND(58, g, h, a, b, c, d, e, f);
|
||||
ROUND(59, f, g, h, a, b, c, d, e);
|
||||
ROUND(60, e, f, g, h, a, b, c, d);
|
||||
ROUND(61, d, e, f, g, h, a, b, c);
|
||||
ROUND(62, c, d, e, f, g, h, a, b);
|
||||
ROUND(63, b, c, d, e, f, g, h, a);
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
|
||||
+572
-375
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user