get tls address calculation off of binary parsing path; do based on in-process memory

This commit is contained in:
Ryan Fleury
2024-05-20 12:55:20 -07:00
parent 5342fab86b
commit fd6befecc3
4 changed files with 92 additions and 20 deletions
+78 -1
View File
@@ -1534,6 +1534,46 @@ ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_MachineID machine_id, DMN_H
return first_pdata;
}
internal U64
ctrl_entry_point_voff_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle)
{
U64 result = 0;
U64 hash = ctrl_hash_from_machine_id_handle(machine_id, module_handle);
U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count;
U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count;
CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx];
CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx];
OS_MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next)
{
if(n->machine_id == machine_id && dmn_handle_match(n->module, module_handle))
{
result = n->entry_point_voff;
break;
}
}
return result;
}
internal Rng1U64
ctrl_tls_vaddr_range_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle)
{
Rng1U64 result = {0};
U64 hash = ctrl_hash_from_machine_id_handle(machine_id, module_handle);
U64 slot_idx = hash%ctrl_state->module_image_info_cache.slots_count;
U64 stripe_idx = slot_idx%ctrl_state->module_image_info_cache.stripes_count;
CTRL_ModuleImageInfoCacheSlot *slot = &ctrl_state->module_image_info_cache.slots[slot_idx];
CTRL_ModuleImageInfoCacheStripe *stripe = &ctrl_state->module_image_info_cache.stripes[stripe_idx];
OS_MutexScopeR(stripe->rw_mutex) for(CTRL_ModuleImageInfoCacheNode *n = slot->first; n != 0; n = n->next)
{
if(n->machine_id == machine_id && dmn_handle_match(n->module, module_handle))
{
result = n->tls_vaddr_range;
break;
}
}
return result;
}
////////////////////////////////
//~ rjf: Unwinding Functions
@@ -2892,6 +2932,8 @@ ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Hand
Arena *arena = arena_alloc();
PE_IntelPdata *pdatas = 0;
U64 pdatas_count = 0;
U64 entry_point_voff = 0;
Rng1U64 tls_vaddr_range = {0};
ProfScope("unpack relevant PE info")
{
B32 is_valid = 1;
@@ -2991,6 +3033,40 @@ ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Hand
pdatas = push_array(arena, PE_IntelPdata, pdatas_count);
dmn_process_read(process, r1u64(vaddr_range.min + pdatas_voff_range.min, vaddr_range.min + pdatas_voff_range.max), pdatas);
}
// rjf: extract tls header
PE_TLSHeader64 tls_header = {0};
if(data_dir_count > PE_DataDirectoryIndex_TLS)
{
PE_DataDirectory dir = {0};
dmn_process_read_struct(process, vaddr_range.min + opt_ext_off_range.min + reported_data_dir_offset + sizeof(PE_DataDirectory)*PE_DataDirectoryIndex_TLS, &dir);
Rng1U64 tls_voff_range = r1u64((U64)dir.virt_off, (U64)dir.virt_off + (U64)dir.virt_size);
switch(coff_header.machine)
{
default:{}break;
case COFF_MachineType_X86:
{
PE_TLSHeader32 tls_header32 = {0};
dmn_process_read_struct(process, vaddr_range.min + tls_voff_range.min, &tls_header32);
tls_header.raw_data_start = (U64)tls_header32.raw_data_start;
tls_header.raw_data_end = (U64)tls_header32.raw_data_end;
tls_header.index_address = (U64)tls_header32.index_address;
tls_header.callbacks_address = (U64)tls_header32.callbacks_address;
tls_header.zero_fill_size = (U64)tls_header32.zero_fill_size;
tls_header.characteristics = (U64)tls_header32.characteristics;
}break;
case COFF_MachineType_X64:
{
dmn_process_read_struct(process, vaddr_range.min + tls_voff_range.min, &tls_header);
}break;
}
}
// rjf: grab entry point vaddr
entry_point_voff = entry_point;
// rjf: calculate TLS vaddr range
tls_vaddr_range = r1u64(tls_header.index_address, tls_header.index_address+sizeof(U32));
}
}
@@ -3023,6 +3099,7 @@ ctrl_thread__module_open(CTRL_MachineID machine_id, DMN_Handle process, DMN_Hand
node->arena = arena;
node->pdatas = pdatas;
node->pdatas_count = pdatas_count;
node->entry_point_voff = entry_point_voff;
}
}
}
@@ -4076,7 +4153,7 @@ ctrl_thread__run(DMN_CtrlCtx *ctrl_ctx, CTRL_Msg *msg)
//- rjf: add trap for PE header entry
if(!entries_found)
{
U64 voff = dbgi->pe.entry_point;
U64 voff = ctrl_entry_point_voff_from_module(CTRL_MachineID_Local, module->handle);
if(voff != 0)
{
DMN_Trap trap = {process->handle, module_base_vaddr + voff};
+4
View File
@@ -510,6 +510,8 @@ struct CTRL_ModuleImageInfoCacheNode
Arena *arena;
PE_IntelPdata *pdatas;
U64 pdatas_count;
U64 entry_point_voff;
Rng1U64 tls_vaddr_range;
};
typedef struct CTRL_ModuleImageInfoCacheSlot CTRL_ModuleImageInfoCacheSlot;
@@ -738,6 +740,8 @@ internal B32 ctrl_thread_write_reg_block(CTRL_MachineID machine_id, DMN_Handle t
//- rjf: cache lookups
internal PE_IntelPdata *ctrl_intel_pdata_from_module_voff(Arena *arena, CTRL_MachineID machine_id, DMN_Handle module_handle, U64 voff);
internal U64 ctrl_entry_point_voff_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle);
internal Rng1U64 ctrl_tls_vaddr_range_from_module(CTRL_MachineID machine_id, DMN_Handle module_handle);
////////////////////////////////
//~ rjf: Unwinding Functions
+7 -13
View File
@@ -3541,20 +3541,14 @@ df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64
DBGI_Scope *scope = dbgi_scope_open();
if(!df_ctrl_targets_running())
{
//- rjf: unpack thread info
//- rjf: unpack module info
DF_Entity *module = df_module_from_process_vaddr(process, rip_vaddr);
DF_Entity *binary = df_binary_file_from_module(module);
DBGI_Parse *dbgi = df_dbgi_parse_from_binary_file(scope, binary);
String8 bin_data = str8((U8 *)dbgi->exe_base, dbgi->exe_props.size);
PE_BinInfo *bin = &dbgi->pe;
B32 bin_is_pe = 1; // TODO(rjf): this path needs to change for ELF
U64 addr_size = bit_size_from_arch(bin->arch)/8;
//- rjf: grab tls range
Rng1U64 tls_vaddr_range = pe_tls_rng_from_bin_base_vaddr(bin_data, bin, df_base_vaddr_from_module(module));
Rng1U64 tls_vaddr_range = ctrl_tls_vaddr_range_from_module(module->ctrl_machine_id, module->ctrl_handle);
U64 addr_size = bit_size_from_arch(process->arch)/8;
//- rjf: read module's TLS index
U64 tls_index = 0;
if(addr_size != 0)
{
CTRL_ProcessMemorySlice tls_index_slice = ctrl_query_cached_data_from_process_vaddr_range(scratch.arena, process->ctrl_machine_id, process->ctrl_handle, tls_vaddr_range, 0);
if(tls_index_slice.data.size >= addr_size)
@@ -3564,7 +3558,7 @@ df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64
}
//- rjf: PE path
if(bin_is_pe)
if(addr_size != 0)
{
U64 thread_info_addr = root_vaddr;
U64 tls_addr_off = tls_index*addr_size;
@@ -3584,10 +3578,10 @@ df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64
}
//- rjf: non-PE path (not implemented)
#if 0
if(!bin_is_pe)
{
// TODO(rjf): not supported. old code from the prototype that Nick had sketched out:
#if 0
// TODO(nick): This code works only if the linked c runtime library is glibc.
// Implement CRT detection here.
@@ -3614,8 +3608,8 @@ df_tls_base_vaddr_from_process_root_rip(DF_Entity *process, U64 root_vaddr, U64
{
demon_read_memory(process->demon_handle, &result, dtv_addr + dtv_size*tls_index, addr_size);
}
#endif
}
#endif
}
dbgi_scope_close(scope);
scratch_end(scratch);
+3 -6
View File
@@ -52,15 +52,10 @@
// since that's not normally how Windows fonts work.
////////////////////////////////
//~ rjf: Demon/Cleanup Pass Tasks
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
//
// [ ] TLS eval -> in-process-memory EXE info
// [ ] unwinding -> in-process-memory EXE info
// [ ] "root" concept in hash store, which buckets keys & allows usage code to
// jettison a collection of keys in retained mode fashion
////////////////////////////////
//~ rjf: Hot, Medium Priority Tasks (Low-Hanging-Fruit Features, UI Jank, Cleanup)
//
// [ ] Jeff Notes
// [ ] highlighted text & ctrl+f -> auto-fill search query
@@ -379,6 +374,8 @@
// function was displayed in the window by default next to the thread.
// [x] ** It would be nice if thread listings displayed the name of the
// thread, instead of just the ID.
// [x] TLS eval -> in-process-memory EXE info
// [x] unwinding -> in-process-memory EXE info
#ifndef RADDBG_H
#define RADDBG_H