upgrade eval space reads with staleness/bad/change info, to expand process memory cache reading abilities to all evaluation spaces; unmapped address visualization (both memory view & single line eval)

This commit is contained in:
Ryan Fleury
2026-05-13 14:48:00 -07:00
parent e6d83f7450
commit 58caf0d3d5
13 changed files with 130 additions and 46 deletions
+1 -1
View File
@@ -1164,7 +1164,7 @@ e_value_eval_from_eval(E_Eval eval)
MemoryZeroStruct(&eval.value);
if(!e_type_key_match(type_key, e_type_key_zero()) &&
type_byte_size <= sizeof(E_Value) &&
e_space_read(eval.space, &eval.value, value_vaddr_range))
e_space_read(eval.space, &eval.value, 0, value_vaddr_range))
{
eval.irtree.mode = E_Mode_Value;
+20 -3
View File
@@ -757,8 +757,25 @@ struct E_AutoHookParams
////////////////////////////////
//~ rjf: Evaluation Context
typedef U32 E_SpaceRangeFlags;
enum
{
E_SpaceRangeFlag_AnyByteBad = (1<<0),
E_SpaceRangeFlag_AnyByteChanged = (1<<1),
E_SpaceRangeFlag_Stale = (1<<2),
};
typedef struct E_SpaceRangeInfo E_SpaceRangeInfo;
struct E_SpaceRangeInfo
{
U64 *byte_bad_flags;
U64 *byte_changed_flags;
E_SpaceRangeFlags flags;
};
typedef U64 E_SpaceGenFunction(E_Space space);
typedef B32 E_SpaceRWFunction(E_Space space, void *out, Rng1U64 offset_range);
typedef B32 E_SpaceReadFunction(E_Space space, void *out, E_SpaceRangeInfo *out_range_info, Rng1U64 offset_range);
typedef B32 E_SpaceWriteFunction(E_Space space, void *out, Rng1U64 offset_range);
//- rjf: base context
@@ -785,8 +802,8 @@ struct E_BaseCtx
// rjf: space hooks
E_SpaceGenFunction *space_gen;
E_SpaceRWFunction *space_read;
E_SpaceRWFunction *space_write;
E_SpaceReadFunction *space_read;
E_SpaceWriteFunction *space_write;
};
//- rjf: ir generation context
+66 -16
View File
@@ -46,7 +46,7 @@ e_space_gen(E_Space space)
}
internal B32
e_space_read(E_Space space, void *out, Rng1U64 range)
e_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_info, Rng1U64 range)
{
ProfBeginFunction();
B32 result = 0;
@@ -77,6 +77,8 @@ e_space_read(E_Space space, void *out, Rng1U64 range)
//- rjf: file reads
case E_SpaceKind_File:
{
Access *access = access_open();
// rjf: unpack space/path
U64 file_path_string_id = space.u64_0;
String8 file_path = e_string_from_id(file_path_string_id);
@@ -88,22 +90,70 @@ e_space_read(E_Space space, void *out, Rng1U64 range)
containing_range.max += chunk_size-1;
containing_range.max -= containing_range.max%chunk_size;
// rjf: map to hash
// rjf: map to hashes
C_Key key = fs_key_from_path_range(file_path, containing_range, 0);
U128 hash = c_hash_from_key(key, 0);
// rjf: look up from hash store
Access *access = access_open();
U128 hash = {0};
U128 prev_hash = {0};
U64 desired_hash_count = 1;
if(out_range_info != 0 && out_range_info->byte_changed_flags != 0)
{
String8 data = c_data_from_hash(access, hash);
Rng1U64 legal_range = r1u64(containing_range.min, containing_range.min + data.size);
Rng1U64 read_range = intersect_1u64(range, legal_range);
if(read_range.min < read_range.max)
desired_hash_count = 2;
}
{
U64 hashes_count = 0;
U128 hashes[2] = {0};
for(U64 rewind_idx = 0; rewind_idx < C_KEY_HASH_HISTORY_COUNT && hashes_count < ArrayCount(hashes) && hashes_count < desired_hash_count; rewind_idx += 1)
{
result = 1;
MemoryCopy(out, data.str + read_range.min - containing_range.min, dim_1u64(read_range));
U128 h = c_hash_from_key(key, rewind_idx);
if(!u128_match(u128_zero(), h))
{
hashes[hashes_count] = h;
hashes_count += 1;
}
}
hash = hashes[0];
prev_hash = hashes[1];
}
// rjf: unpack hashes
String8 data = c_data_from_hash(access, hash);
String8 prev_data = c_data_from_hash(access, prev_hash);
// rjf: unpack read range
Rng1U64 legal_range = r1u64(containing_range.min, containing_range.min + data.size);
Rng1U64 read_range = intersect_1u64(range, legal_range);
// rjf: fill out byte bad flags
if(out_range_info != 0 && out_range_info->byte_bad_flags != 0)
{
// TODO(rjf): need to know whole space range here
}
// rjf: fill out byte changed flags
if(out_range_info != 0 && out_range_info->byte_changed_flags != 0)
{
U64 num_bytes_read = dim_1u64(read_range);
if(data.size >= num_bytes_read && data.size == prev_data.size)
{
U64 byte_base_idx = read_range.min - containing_range.min;
for(U64 byte_idx = 0; byte_idx < num_bytes_read; byte_idx += 1)
{
if(data.str[byte_base_idx + byte_idx] != prev_data.str[byte_base_idx + byte_idx])
{
out_range_info->byte_changed_flags[byte_idx/64] |= (1ull<<(byte_idx%64));
out_range_info->flags |= E_SpaceRangeFlag_AnyByteChanged;
}
}
}
}
// rjf: fill output data from data
if(read_range.min < read_range.max)
{
result = 1;
MemoryCopy(out, data.str + read_range.min - containing_range.min, dim_1u64(read_range));
}
access_close(access);
}break;
@@ -128,7 +178,7 @@ e_space_read(E_Space space, void *out, Rng1U64 range)
default:
if(e_base_ctx->space_read != 0)
{
result = e_base_ctx->space_read(space, out, range);
result = e_base_ctx->space_read(space, out, out_range_info, range);
}break;
}
}
@@ -277,7 +327,7 @@ e_interpret(String8 bytecode)
{
U64 addr = svals[0].u64;
U64 size = imm.u64;
B32 good_read = e_space_read(selected_space, &nval, r1u64(addr, addr+size));
B32 good_read = e_space_read(selected_space, &nval, 0, r1u64(addr, addr+size));
if(!good_read)
{
result.code = E_InterpretationCode_BadMemRead;
@@ -299,7 +349,7 @@ e_interpret(String8 bytecode)
Rng1U16 rng = arch_info->reg_code_rng_table[base_reg_code];
U64 off = (U64)rng.min + byte_off;
U64 size = (U64)byte_size;
good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
good_read = e_space_read(e_interpret_ctx->reg_space, &nval, 0, r1u64(off, off+size));
}
if(!good_read)
{
@@ -312,7 +362,7 @@ e_interpret(String8 bytecode)
{
U64 off = svals[0].u64;
U64 size = bit_size_from_arch(e_interpret_ctx->reg_arch)/8;
B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, r1u64(off, off+size));
B32 good_read = e_space_read(e_interpret_ctx->reg_space, &nval, 0, r1u64(off, off+size));
if(!good_read)
{
result.code = E_InterpretationCode_BadRegRead;
+1 -1
View File
@@ -34,7 +34,7 @@ internal void e_select_interpret_ctx(E_InterpretCtx *ctx, RDI_Parsed *primary_rd
//~ rjf: Space Reading Helpers
internal U64 e_space_gen(E_Space space);
internal B32 e_space_read(E_Space space, void *out, Rng1U64 range);
internal B32 e_space_read(E_Space space, void *out, E_SpaceRangeInfo *out_range_info, Rng1U64 range);
internal B32 e_space_write(E_Space space, void *in, Rng1U64 range);
////////////////////////////////
+1 -1
View File
@@ -2386,7 +2386,7 @@ e_push_irtree_and_type_from_expr(Arena *arena, E_IRTreeAndType *root_parent, E_I
U64 class_base_vaddr = interpret.value.u64;
U64 vtable_vaddr = 0;
U64 addr_size = e_type_byte_size_from_key(type_key);
if(e_space_read(interpret.space, &vtable_vaddr, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
if(e_space_read(interpret.space, &vtable_vaddr, 0, r1u64(class_base_vaddr, class_base_vaddr+addr_size)))
{
Arch arch = e_base_ctx->primary_module->arch;
U32 dbg_info_num = 0;
+2 -2
View File
@@ -2587,7 +2587,7 @@ e_list_gather_artifact_create(String8 key, B32 *cancel_signal, B32 *retry_out, U
U64 base_off = 0;
U64 member_element_off = 0;
U64 member_size = 0;
E_SpaceRWFunction *space_read = 0;
E_SpaceReadFunction *space_read = 0;
{
U64 key_read_off = 0;
key_read_off += str8_deserial_read_struct(key, key_read_off, &process);
@@ -2812,7 +2812,7 @@ E_TYPE_IREXT_FUNCTION_DEF(list)
U64 base_off;
U64 member_element_off;
U64 member_size;
E_SpaceRWFunction *space_read;
E_SpaceReadFunction *space_read;
}
key_data =
{