ctrl entity string allocation & tracking, for thread names & module names; fix process memory cache in edge cases

This commit is contained in:
Ryan Fleury
2024-03-12 14:56:02 -07:00
parent d1e88f781e
commit 8639faabdd
4 changed files with 165 additions and 35 deletions
+139 -32
View File
@@ -471,6 +471,8 @@ ctrl_entity_store_alloc(void)
Arena *arena = arena_alloc();
CTRL_EntityStore *store = push_array(arena, CTRL_EntityStore, 1);
store->arena = arena;
store->hash_slots_count = 1024;
store->hash_slots = push_array(arena, CTRL_EntityHashSlot, store->hash_slots_count);
return store;
}
@@ -480,10 +482,101 @@ ctrl_entity_store_release(CTRL_EntityStore *cache)
arena_release(cache->arena);
}
internal U64
ctrl_name_bucket_idx_from_string_size(U64 size)
{
U64 size_rounded = u64_up_to_pow2(size+1);
size_rounded = ClampBot((1<<4), size_rounded);
U64 bucket_idx = 0;
switch(size_rounded)
{
case 1<<4: {bucket_idx = 0;}break;
case 1<<5: {bucket_idx = 1;}break;
case 1<<6: {bucket_idx = 2;}break;
case 1<<7: {bucket_idx = 3;}break;
case 1<<8: {bucket_idx = 4;}break;
case 1<<9: {bucket_idx = 5;}break;
case 1<<10:{bucket_idx = 6;}break;
default:{bucket_idx = ArrayCount(((CTRL_EntityStore *)0)->free_string_chunks)-1;}break;
}
return bucket_idx;
}
internal String8
ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string)
{
if(string.size == 0) {return str8_zero();}
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
CTRL_EntityStringChunkNode *node = store->free_string_chunks[bucket_idx];
// rjf: pull from bucket free list
if(node != 0)
{
if(bucket_idx == ArrayCount(store->free_string_chunks)-1)
{
node = 0;
CTRL_EntityStringChunkNode *prev = 0;
for(CTRL_EntityStringChunkNode *n = store->free_string_chunks[bucket_idx];
n != 0;
prev = n, n = n->next)
{
if(n->size >= string.size+1)
{
if(prev == 0)
{
store->free_string_chunks[bucket_idx] = n->next;
}
else
{
prev->next = n->next;
}
node = n;
break;
}
}
}
else
{
SLLStackPop(store->free_string_chunks[bucket_idx]);
}
}
// rjf: no found node -> allocate new
if(node == 0)
{
U64 chunk_size = 0;
if(bucket_idx < ArrayCount(store->free_string_chunks)-1)
{
chunk_size = 1<<(bucket_idx+4);
}
else
{
chunk_size = u64_up_to_pow2(string.size);
}
U8 *chunk_memory = push_array(store->arena, U8, chunk_size);
node = (CTRL_EntityStringChunkNode *)chunk_memory;
}
// rjf: fill string & return
String8 allocated_string = str8((U8 *)node, string.size);
MemoryCopy((U8 *)node, string.str, string.size);
return allocated_string;
}
internal void
ctrl_entity_string_release(CTRL_EntityStore *store, String8 string)
{
if(string.size == 0) {return;}
U64 bucket_idx = ctrl_name_bucket_idx_from_string_size(string.size);
CTRL_EntityStringChunkNode *node = (CTRL_EntityStringChunkNode *)string.str;
node->size = u64_up_to_pow2(string.size);
SLLStackPush(store->free_string_chunks[bucket_idx], node);
}
//- rjf: entity construction/deletion
internal CTRL_Entity *
ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, CTRL_MachineID machine_id, DMN_Handle handle)
ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Architecture arch, CTRL_MachineID machine_id, DMN_Handle handle)
{
CTRL_Entity *entity = &ctrl_entity_nil;
{
@@ -504,6 +597,7 @@ ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind
// rjf: fill
{
entity->kind = kind;
entity->arch = arch;
entity->machine_id = machine_id;
entity->handle = handle;
entity->parent = parent;
@@ -603,6 +697,18 @@ ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity)
}
}
//- rjf: entity equipment
internal void
ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string)
{
if(entity->string.size != 0)
{
ctrl_entity_string_release(store, entity->string);
}
entity->string = ctrl_entity_string_alloc(store, string);
}
//- rjf: entity store lookups
internal CTRL_Entity *
@@ -634,8 +740,8 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list)
//- rjf: construct root-level entities
if(!store->root)
{
CTRL_Entity *root = store->root = ctrl_entity_alloc(store, &ctrl_entity_nil, CTRL_EntityKind_Root, 0, dmn_handle_zero());
CTRL_Entity *local_machine = ctrl_entity_alloc(store, root, CTRL_EntityKind_Machine, CTRL_MachineID_Local, dmn_handle_zero());
CTRL_Entity *root = store->root = ctrl_entity_alloc(store, &ctrl_entity_nil, CTRL_EntityKind_Root, Architecture_Null, 0, dmn_handle_zero());
CTRL_Entity *local_machine = ctrl_entity_alloc(store, root, CTRL_EntityKind_Machine, architecture_from_context(), CTRL_MachineID_Local, dmn_handle_zero());
(void)local_machine;
}
@@ -649,8 +755,7 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list)
case CTRL_EventKind_NewProc:
{
CTRL_Entity *machine = ctrl_entity_from_machine_id_handle(store, event->machine_id, dmn_handle_zero());
CTRL_Entity *process = ctrl_entity_alloc(store, machine, CTRL_EntityKind_Process, event->machine_id, event->entity);
process->arch = event->arch;
CTRL_Entity *process = ctrl_entity_alloc(store, machine, CTRL_EntityKind_Process, event->arch, event->machine_id, event->entity);
}break;
case CTRL_EventKind_EndProc:
{
@@ -662,21 +767,25 @@ ctrl_entity_store_apply_events(CTRL_EntityStore *store, CTRL_EventList *list)
case CTRL_EventKind_NewThread:
{
CTRL_Entity *process = ctrl_entity_from_machine_id_handle(store, event->machine_id, event->parent);
CTRL_Entity *thread = ctrl_entity_alloc(store, process, CTRL_EntityKind_Thread, event->machine_id, event->entity);
thread->arch = event->arch;
CTRL_Entity *thread = ctrl_entity_alloc(store, process, CTRL_EntityKind_Thread, event->arch, event->machine_id, event->entity);
}break;
case CTRL_EventKind_EndThread:
{
CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(store, event->machine_id, event->entity);
ctrl_entity_release(store, thread);
}break;
case CTRL_EventKind_ThreadName:
{
CTRL_Entity *thread = ctrl_entity_from_machine_id_handle(store, event->machine_id, event->entity);
ctrl_entity_equip_string(store, thread, event->string);
}break;
//- rjf: modules
case CTRL_EventKind_NewModule:
{
CTRL_Entity *process = ctrl_entity_from_machine_id_handle(store, event->machine_id, event->parent);
CTRL_Entity *module = ctrl_entity_alloc(store, process, CTRL_EntityKind_Module, event->machine_id, event->entity);
module->arch = event->arch;
CTRL_Entity *module = ctrl_entity_alloc(store, process, CTRL_EntityKind_Module, event->arch, event->machine_id, event->entity);
ctrl_entity_equip_string(store, module, event->string);
}break;
case CTRL_EventKind_EndModule:
{
@@ -811,31 +920,23 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle
B32 is_stale = 0;
OS_MutexScopeR(process_stripe->rw_mutex)
{
for(;;)
for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next)
{
for(CTRL_ProcessMemoryCacheNode *n = process_slot->first; n != 0; n = n->next)
if(n->machine_id == machine_id && ctrl_handle_match(n->process, process))
{
if(n->machine_id == machine_id && ctrl_handle_match(n->process, process))
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
{
U64 range_slot_idx = range_hash%n->range_hash_slots_count;
CTRL_ProcessMemoryRangeHashSlot *range_slot = &n->range_hash_slots[range_slot_idx];
for(CTRL_ProcessMemoryRangeHashNode *range_n = range_slot->first; range_n != 0; range_n = range_n->next)
if(MemoryMatchStruct(&range_n->vaddr_range, &range) && range_n->zero_terminated == zero_terminated)
{
if(MemoryMatchStruct(&range_n->vaddr_range, &range) && range_n->zero_terminated == zero_terminated)
{
result = range_n->hash;
is_good = 1;
is_stale = range_n->memgen_idx < ctrl_memgen_idx();
goto read_cache__break_all;
}
result = range_n->hash;
is_good = 1;
is_stale = (range_n->memgen_idx < ctrl_memgen_idx());
goto read_cache__break_all;
}
}
}
if(os_now_microseconds() >= endt_us)
{
break;
}
os_condition_variable_wait_rw_r(process_stripe->cv, process_stripe->rw_mutex, endt_us);
}
read_cache__break_all:;
}
@@ -918,6 +1019,12 @@ ctrl_stored_hash_from_process_vaddr_range(CTRL_MachineID machine_id, DMN_Handle
{
break;
}
//- rjf: done? -> exit
if(is_good && !is_stale)
{
break;
}
}
return result;
}
@@ -1245,7 +1352,7 @@ ctrl_unwind_from_thread(Arena *arena, CTRL_EntityStore *store, CTRL_MachineID ma
if(contains_1u64(m->vaddr_range, rip))
{
module = m->handle;
module_name = m->name;
module_name = m->string;
module_vaddr_range = m->vaddr_range;
break;
}
@@ -1551,7 +1658,7 @@ ctrl_thread__append_resolved_module_user_bp_traps(Arena *arena, CTRL_MachineID m
Temp scratch = scratch_begin(&arena, 1);
DBGI_Scope *scope = dbgi_scope_open();
CTRL_Entity *module_entity = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, machine_id, module);
String8 exe_path = module_entity->name;
String8 exe_path = module_entity->string;
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, max_U64);
RDI_Parsed *rdi = &dbgi->rdi;
U64 base_vaddr = module_entity->vaddr_range.min;
@@ -1729,7 +1836,7 @@ ctrl_thread__next_dmn_event(Arena *arena, CTRL_Msg *msg, DMN_RunCtrls *run_ctrls
// rjf: determine base address of asan shadow space
U64 asan_shadow_base_vaddr = 0;
B32 asan_shadow_variable_exists_but_is_zero = 0;
String8 module_path = module->name;
String8 module_path = module->string;
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, module_path, max_U64);
RDI_Parsed *rdi = &dbgi->rdi;
RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_GlobalVariables);
@@ -2239,7 +2346,7 @@ ctrl_thread__launch_and_init(CTRL_Msg *msg)
CTRL_Entity *process = ctrl_entity_from_machine_id_handle(ctrl_state->ctrl_thread_entity_store, CTRL_MachineID_Local, run_ctrls.run_entities[process_idx]);
CTRL_Entity *module = process->first;
U64 module_base_vaddr = module->vaddr_range.min;
String8 exe_path = module->name;
String8 exe_path = module->string;
DBGI_Parse *dbgi = dbgi_parse_from_exe_path(scope, exe_path, max_U64);
RDI_Parsed *rdi = &dbgi->rdi;
RDI_NameMap *unparsed_map = rdi_name_map_from_kind(rdi, RDI_NameMapKind_Procedures);
@@ -2873,7 +2980,7 @@ ctrl_thread__run(CTRL_Msg *msg)
{
if(contains_1u64(module->vaddr_range, thread_rip_vaddr))
{
module_name = module->name;
module_name = module->string;
module_base_vaddr = module->vaddr_range.min;
thread_rip_voff = thread_rip_vaddr - module->vaddr_range.min;
break;
+18 -3
View File
@@ -65,7 +65,7 @@ struct CTRL_Entity
CTRL_MachineID machine_id;
DMN_Handle handle;
Rng1U64 vaddr_range;
String8 name;
String8 string;
};
typedef struct CTRL_EntityHashNode CTRL_EntityHashNode;
@@ -83,6 +83,13 @@ struct CTRL_EntityHashSlot
CTRL_EntityHashNode *last;
};
typedef struct CTRL_EntityStringChunkNode CTRL_EntityStringChunkNode;
struct CTRL_EntityStringChunkNode
{
CTRL_EntityStringChunkNode *next;
U64 size;
};
typedef struct CTRL_EntityStore CTRL_EntityStore;
struct CTRL_EntityStore
{
@@ -92,6 +99,7 @@ struct CTRL_EntityStore
CTRL_EntityHashSlot *hash_slots;
CTRL_EntityHashNode *hash_node_free;
U64 hash_slots_count;
CTRL_EntityStringChunkNode *free_string_chunks[8];
};
////////////////////////////////
@@ -593,12 +601,19 @@ internal CTRL_Event ctrl_event_from_serialized_string(Arena *arena, String8 stri
//- rjf: cache creation/destruction
internal CTRL_EntityStore *ctrl_entity_store_alloc(void);
internal void ctrl_entity_store_release(CTRL_EntityStore *cache);
internal void ctrl_entity_store_release(CTRL_EntityStore *store);
//- rjf: string allocation/deletion
internal String8 ctrl_entity_string_alloc(CTRL_EntityStore *store, String8 string);
internal void ctrl_entity_string_release(CTRL_EntityStore *store, String8 string);
//- rjf: entity construction/deletion
internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, CTRL_MachineID machine_id, DMN_Handle handle);
internal CTRL_Entity *ctrl_entity_alloc(CTRL_EntityStore *store, CTRL_Entity *parent, CTRL_EntityKind kind, Architecture arch, CTRL_MachineID machine_id, DMN_Handle handle);
internal void ctrl_entity_release(CTRL_EntityStore *store, CTRL_Entity *entity);
//- rjf: entity equipment
internal void ctrl_entity_equip_string(CTRL_EntityStore *store, CTRL_Entity *entity, String8 string);
//- rjf: entity store lookups
internal CTRL_Entity *ctrl_entity_from_machine_id_handle(CTRL_EntityStore *store, CTRL_MachineID machine_id, DMN_Handle handle);
+1
View File
@@ -189,6 +189,7 @@ internal B32 dmn_process_write(DMN_Handle process, Rng1U64 range, void *src);
#define dmn_process_write_struct(process, vaddr, ptr) dmn_process_write((process), r1u64((vaddr), (vaddr)+(sizeof(*ptr))), ptr)
//- rjf: threads
internal Architecture dmn_arch_from_thread(DMN_Handle handle);
internal U64 dmn_stack_base_vaddr_from_thread(DMN_Handle handle);
internal U64 dmn_tls_root_vaddr_from_thread(DMN_Handle handle);
internal B32 dmn_thread_read_reg_block(DMN_Handle handle, void *reg_block);
+7
View File
@@ -2333,6 +2333,13 @@ dmn_process_write(DMN_Handle process, Rng1U64 range, void *src)
//- rjf: threads
internal Architecture
dmn_arch_from_thread(DMN_Handle handle)
{
DMN_W32_Entity *entity = dmn_w32_entity_from_handle(handle);
return entity->arch;
}
internal U64
dmn_stack_base_vaddr_from_thread(DMN_Handle handle)
{