mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-06-13 07:32:23 -07:00
type-info-table-driven pointer rebasing for meta evals; add callstack info to entity meta evals
This commit is contained in:
+1
-1
@@ -48,7 +48,7 @@ commands =
|
||||
//- rjf: fkey command slots (change locally but do not commit)
|
||||
.f1 = { .win = "build raddbg telemetry", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f2 = { .win = "build rdi_from_pdb", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --xuto_step && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
.f3 = { .win = "pushd build && raddbg.exe --user:local_dev.raddbg_user --project:local_dev.raddbg_project --auto_step && popd",.linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
//- rjf: local target builds
|
||||
.build_raddbg = { .win = "build raddbg", .linux = "", .out = "*compilation*", .footer_panel = true, .save_dirty_files = true, .cursor_at_end = false, },
|
||||
|
||||
+75
-26
@@ -25,6 +25,55 @@ member_from_name(Type *type, String8 name)
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info * Instance Operations
|
||||
|
||||
internal void
|
||||
typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr)
|
||||
{
|
||||
Temp scratch = scratch_begin(0, 0);
|
||||
typedef struct RebaseTypeTask RebaseTypeTask;
|
||||
struct RebaseTypeTask
|
||||
{
|
||||
RebaseTypeTask *next;
|
||||
Type *type;
|
||||
U8 *ptr;
|
||||
};
|
||||
RebaseTypeTask start_task = {0, type, data.str};
|
||||
RebaseTypeTask *first_task = &start_task;
|
||||
RebaseTypeTask *last_task = first_task;
|
||||
for(RebaseTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
switch(t->type->kind)
|
||||
{
|
||||
default:{}break;
|
||||
case TypeKind_Ptr:
|
||||
{
|
||||
*(U64 *)t->ptr = ((U64)(*(U8 **)t->ptr - (U8 *)base_ptr));
|
||||
}break;
|
||||
case TypeKind_Array:
|
||||
{
|
||||
for(U64 idx = 0; idx < t->type->count; idx += 1)
|
||||
{
|
||||
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->ptr = t->ptr + t->type->direct->size * idx;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}break;
|
||||
case TypeKind_Struct:
|
||||
{
|
||||
for(U64 idx = 0; idx < t->type->count; idx += 1)
|
||||
{
|
||||
Member *member = &t->type->members[idx];
|
||||
RebaseTypeTask *task = push_array(scratch.arena, RebaseTypeTask, 1);
|
||||
task->type = member->type;
|
||||
task->ptr = t->ptr + member->value;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
internal String8
|
||||
serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params)
|
||||
{
|
||||
@@ -32,10 +81,10 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
String8List strings = {0};
|
||||
str8_serial_begin(scratch.arena, &strings);
|
||||
{
|
||||
typedef struct Task Task;
|
||||
struct Task
|
||||
typedef struct SerializeTypeTask SerializeTypeTask;
|
||||
struct SerializeTypeTask
|
||||
{
|
||||
Task *next;
|
||||
SerializeTypeTask *next;
|
||||
Type *type;
|
||||
U64 count;
|
||||
U8 *src;
|
||||
@@ -43,10 +92,10 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
U8 *containing_ptr;
|
||||
B32 is_post_header;
|
||||
};
|
||||
Task start_task = {0, type, 1, data.str};
|
||||
Task *first_task = &start_task;
|
||||
Task *last_task = first_task;
|
||||
for(Task *t = first_task; t != 0; t = t->next)
|
||||
SerializeTypeTask start_task = {0, type, 1, data.str};
|
||||
SerializeTypeTask *first_task = &start_task;
|
||||
SerializeTypeTask *last_task = first_task;
|
||||
for(SerializeTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
switch(t->type->kind)
|
||||
{
|
||||
@@ -93,7 +142,7 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
// delimit our size, so push a new post-header task for pointer.
|
||||
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type;
|
||||
task->count = t->count;
|
||||
task->src = t->src;
|
||||
@@ -116,7 +165,7 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
}
|
||||
|
||||
// rjf: push task
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = count;
|
||||
task->src = *(void **)t->src;
|
||||
@@ -129,7 +178,7 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
//- rjf: arrays -> descend to underlying type, + count
|
||||
case TypeKind_Array:
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->type->count;
|
||||
task->src = t->src;
|
||||
@@ -150,10 +199,10 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->members[member_idx].type;
|
||||
task->count = 1;
|
||||
task->src = t->src + t->type->members[member_idx].value;
|
||||
task->src = t->src + idx*t->type->size + t->type->members[member_idx].value;
|
||||
task->containing_type = t->type;
|
||||
task->containing_ptr = t->src;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
@@ -164,7 +213,7 @@ serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerialize
|
||||
//- rjf: enum -> descend to basic type interpretation
|
||||
case TypeKind_Enum:
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
SerializeTypeTask *task = push_array(scratch.arena, SerializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->count;
|
||||
task->src = t->src;
|
||||
@@ -188,10 +237,10 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
result.str = push_array(arena, U8, result.size);
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
typedef struct Task Task;
|
||||
struct Task
|
||||
typedef struct DeserializeTypeTask DeserializeTypeTask;
|
||||
struct DeserializeTypeTask
|
||||
{
|
||||
Task *next;
|
||||
DeserializeTypeTask *next;
|
||||
Type *type;
|
||||
U64 count;
|
||||
U8 *dst;
|
||||
@@ -200,10 +249,10 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
B32 is_post_header;
|
||||
};
|
||||
U64 read_off = 0;
|
||||
Task start_task = {0, type, 1, result.str};
|
||||
Task *first_task = &start_task;
|
||||
Task *last_task = first_task;
|
||||
for(Task *t = first_task; t != 0; t = t->next)
|
||||
DeserializeTypeTask start_task = {0, type, 1, result.str};
|
||||
DeserializeTypeTask *first_task = &start_task;
|
||||
DeserializeTypeTask *last_task = first_task;
|
||||
for(DeserializeTypeTask *t = first_task; t != 0; t = t->next)
|
||||
{
|
||||
U8 *t_src = data.str + read_off;
|
||||
switch(t->type->kind)
|
||||
@@ -254,7 +303,7 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
// delimit our size, so push a new post-header task for pointer.
|
||||
else if(t->type->count_delimiter_name.size != 0 && !t->is_post_header)
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type;
|
||||
task->count = t->count;
|
||||
task->dst = t->dst;
|
||||
@@ -282,7 +331,7 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
MemoryCopy(t->dst, &ptr_dest_buffer, sizeof(ptr_dest_buffer));
|
||||
|
||||
// rjf: push task
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = count;
|
||||
task->dst = ptr_dest_buffer;
|
||||
@@ -295,7 +344,7 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
//- rjf: arrays -> descend to underlying type, + count
|
||||
case TypeKind_Array:
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->type->count;
|
||||
task->dst = t->dst;
|
||||
@@ -315,10 +364,10 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->members[member_idx].type;
|
||||
task->count = 1;
|
||||
task->dst = t->dst + t->type->members[member_idx].value;
|
||||
task->dst = t->dst + idx*t->type->size + t->type->members[member_idx].value;
|
||||
task->containing_type = t->type;
|
||||
task->containing_ptr = t->dst;
|
||||
SLLQueuePush(first_task, last_task, task);
|
||||
@@ -329,7 +378,7 @@ deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSeriali
|
||||
//- rjf: enum -> descend to basic type interpretation
|
||||
case TypeKind_Enum:
|
||||
{
|
||||
Task *task = push_array(scratch.arena, Task, 1);
|
||||
DeserializeTypeTask *task = push_array(scratch.arena, DeserializeTypeTask, 1);
|
||||
task->type = t->type->direct;
|
||||
task->count = t->count;
|
||||
task->dst = t->dst;
|
||||
|
||||
@@ -249,9 +249,11 @@ internal Member *member_from_name(Type *type, String8 name);
|
||||
////////////////////////////////
|
||||
//~ rjf: Type Info * Instance Operations
|
||||
|
||||
internal void typed_data_rebase_ptrs(Type *type, String8 data, void *base_ptr);
|
||||
internal String8 serialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
internal String8 deserialized_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
internal String8 deep_copy_from_typed_data(Arena *arena, Type *type, String8 data, TypeSerializeParams *params);
|
||||
#define struct_rebase_ptrs(T, ptr, base) typed_data_rebase_ptrs(type(T), str8_struct(ptr), (base))
|
||||
#define serialized_from_struct(arena, T, ptr, ...) serialized_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__})
|
||||
#define struct_from_serialized(arena, T, string, ...) (T *)deserialized_from_typed_data((arena), type(T), (string), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
|
||||
#define deep_copy_from_struct(arena, T, ptr, ...) (T *)deep_copy_from_typed_data((arena), type(T), str8_struct(ptr), &(TypeSerializeParams){.ptr_ref_infos = 0, __VA_ARGS__}).str
|
||||
|
||||
+27
-1
@@ -15,6 +15,31 @@ typedef U64 CTRL_MachineID;
|
||||
////////////////////////////////
|
||||
//~ rjf: Meta Evaluation Types
|
||||
|
||||
//- rjf: meta evaluation callstack
|
||||
typedef struct CTRL_MetaEvalFrame CTRL_MetaEvalFrame;
|
||||
struct CTRL_MetaEvalFrame
|
||||
{
|
||||
U64 vaddr;
|
||||
};
|
||||
struct_members(CTRL_MetaEvalFrame)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEvalFrame, type(U64), vaddr),
|
||||
};
|
||||
struct_type(CTRL_MetaEvalFrame);
|
||||
typedef struct CTRL_MetaEvalFrameArray CTRL_MetaEvalFrameArray;
|
||||
struct CTRL_MetaEvalFrameArray
|
||||
{
|
||||
U64 count;
|
||||
CTRL_MetaEvalFrame *v;
|
||||
};
|
||||
ptr_type(CTRL_MetaEvalFrameArray__v_ptr_type, type(CTRL_MetaEvalFrame), .count_delimiter_name = str8_lit_comp("count"));
|
||||
struct_members(CTRL_MetaEvalFrameArray)
|
||||
{
|
||||
member_lit_comp(CTRL_MetaEvalFrameArray, type(U64), count),
|
||||
{str8_lit_comp("v"), &CTRL_MetaEvalFrameArray__v_ptr_type, OffsetOf(CTRL_MetaEvalFrameArray, v)},
|
||||
};
|
||||
struct_type(CTRL_MetaEvalFrameArray);
|
||||
|
||||
//- rjf: meta evaluation instance
|
||||
typedef struct CTRL_MetaEval CTRL_MetaEval;
|
||||
struct CTRL_MetaEval
|
||||
@@ -27,7 +52,8 @@ X(U64, id)\
|
||||
X(U32, color)\
|
||||
X(String8, label)\
|
||||
X(String8, location)\
|
||||
X(String8, condition)
|
||||
X(String8, condition)\
|
||||
X(CTRL_MetaEvalFrameArray, callstack)
|
||||
#define X(T, name) T name;
|
||||
CTRL_MetaEval_MemberXList
|
||||
#undef X
|
||||
|
||||
+27
-24
@@ -1865,15 +1865,7 @@ rd_eval_space_read(void *u, E_Space space, void *out, Rng1U64 range)
|
||||
U64 pos_min = arena_pos(scratch.arena);
|
||||
String8 eval_srlzed = serialized_from_struct(scratch.arena, CTRL_MetaEval, eval);
|
||||
CTRL_MetaEval *eval_read = struct_from_serialized(scratch.arena, CTRL_MetaEval, eval_srlzed);
|
||||
for EachMember(CTRL_MetaEval, m)
|
||||
{
|
||||
if(str8_match(m->type->name, str8_lit("String8"), 0))
|
||||
{
|
||||
U64 ptr_value = *(U64 *)((U8 *)eval_read + m->value);
|
||||
U64 space_relative_ptr_value = ptr_value - (U64)eval_read;
|
||||
*(U64 *)((U8 *)eval_read + m->value) = space_relative_ptr_value;
|
||||
}
|
||||
}
|
||||
struct_rebase_ptrs(CTRL_MetaEval, eval_read, eval_read);
|
||||
U64 pos_opl = arena_pos(scratch.arena);
|
||||
Rng1U64 legal_range = r1u64(0, pos_opl-pos_min);
|
||||
if(contains_1u64(legal_range, range.min))
|
||||
@@ -10228,6 +10220,26 @@ rd_frame(void)
|
||||
meval->color = entity->rgba;
|
||||
meval->label = entity->string;
|
||||
meval->id = entity->id;
|
||||
if(entity->kind == CTRL_EntityKind_Thread)
|
||||
{
|
||||
CTRL_Entity *process = ctrl_entity_ancestor_from_kind(entity, CTRL_EntityKind_Process);
|
||||
CTRL_Unwind base_unwind = d_query_cached_unwind_from_thread(entity);
|
||||
D_Unwind rich_unwind = d_unwind_from_ctrl_unwind(scratch.arena, di_scope, process, &base_unwind);
|
||||
meval->callstack.count = rich_unwind.frames.total_frame_count;
|
||||
meval->callstack.v = push_array(scratch.arena, CTRL_MetaEvalFrame, meval->callstack.count);
|
||||
U64 idx = 0;
|
||||
for(U64 base_idx = 0; base_idx < rich_unwind.frames.concrete_frame_count; base_idx += 1)
|
||||
{
|
||||
U64 inline_idx = 0;
|
||||
for(D_UnwindInlineFrame *f = rich_unwind.frames.v[base_idx].first_inline_frame; f != 0; f = f->next, inline_idx += 1)
|
||||
{
|
||||
meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs);
|
||||
idx += 1;
|
||||
}
|
||||
meval->callstack.v[idx].vaddr = regs_rip_from_arch_block(entity->arch, rich_unwind.frames.v[base_idx].regs);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
meta_eval_idx += 1;
|
||||
}
|
||||
}
|
||||
@@ -10276,23 +10288,14 @@ rd_frame(void)
|
||||
ctx->macro_map = push_array(scratch.arena, E_String2ExprMap, 1);
|
||||
ctx->macro_map[0] = e_string2expr_map_make(scratch.arena, 512);
|
||||
|
||||
//- rjf: add macros for constants
|
||||
//- rjf: add macros for all evallable frontend entities
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//- rjf: add macros for all evallable control entities
|
||||
{
|
||||
// rjf: pid -> current process' ID
|
||||
if(process != &ctrl_entity_nil)
|
||||
{
|
||||
E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafU64, 0);
|
||||
expr->value.u64 = process->id;
|
||||
e_string2expr_map_insert(scratch.arena, ctx->macro_map, str8_lit("pid"), expr);
|
||||
}
|
||||
|
||||
// rjf: tid -> current thread's ID
|
||||
if(thread != &ctrl_entity_nil)
|
||||
{
|
||||
E_Expr *expr = e_push_expr(scratch.arena, E_ExprKind_LeafU64, 0);
|
||||
expr->value.u64 = thread->id;
|
||||
e_string2expr_map_insert(scratch.arena, ctx->macro_map, str8_lit("tid"), expr);
|
||||
}
|
||||
}
|
||||
|
||||
//- rjf: add macros for meta evaluations
|
||||
|
||||
Reference in New Issue
Block a user