WIP DWARF expression eval

- fixup jump offsets after expression is serialized
- use generalized machine ops for register reads
- add option to limit number of executed opcodes
This commit is contained in:
Nikita Smith
2025-12-16 11:12:43 -08:00
parent 44123e9712
commit 2b4e0f8b77
6 changed files with 1338 additions and 1326 deletions
+43 -43
View File
@@ -6,7 +6,7 @@ dw_reg_size_from_code_x64(DW_Reg reg_code)
{ {
switch (reg_code) { switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_size; #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_size;
DW_Regs_X64_XList(X) DW_Regs_X64_XList
#undef X #undef X
} }
return 0; return 0;
@@ -17,7 +17,7 @@ dw_reg_pos_from_code_x64(DW_Reg reg_code)
{ {
switch (reg_code) { switch (reg_code) {
#define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_pos; #define X(reg_name_dw, reg_code_dw, reg_name_rdi, reg_pos, reg_size) case DW_RegX64_##reg_name_dw: return reg_pos;
DW_Regs_X64_XList(X) DW_Regs_X64_XList
#undef X #undef X
} }
return max_U64; return max_U64;
@@ -84,7 +84,7 @@ dw_attrib_class_from_attrib_v2(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V2_XList(X) DW_AttribKind_ClassFlags_V2_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -95,7 +95,7 @@ dw_attrib_class_from_attrib_v3(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V3_XList(X) DW_AttribKind_ClassFlags_V3_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -106,7 +106,7 @@ dw_attrib_class_from_attrib_v4(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V4_XList(X) DW_AttribKind_ClassFlags_V4_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -117,7 +117,7 @@ dw_attrib_class_from_attrib_v5(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_V5_XList(X) DW_AttribKind_ClassFlags_V5_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -128,7 +128,7 @@ dw_attrib_class_from_attrib_gnu(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_GNU_XList(X) DW_AttribKind_ClassFlags_GNU_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -139,7 +139,7 @@ dw_attrib_class_from_attrib_llvm(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_LLVM_XList(X) DW_AttribKind_ClassFlags_LLVM_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -150,7 +150,7 @@ dw_attrib_class_from_attrib_apple(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_APPLE_XList(X) DW_AttribKind_ClassFlags_APPLE_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -161,7 +161,7 @@ dw_attrib_class_from_attrib_mips(DW_AttribKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_C) case DW_AttribKind_##_N: return _C; #define X(_N,_C) case DW_AttribKind_##_N: return _C;
DW_AttribKind_ClassFlags_MIPS_XList(X) DW_AttribKind_ClassFlags_MIPS_XList
#undef X #undef X
} }
return DW_AttribClass_Null; return DW_AttribClass_Null;
@@ -215,28 +215,28 @@ dw_attrib_class_from_form_kind(DW_Version ver, DW_FormKind k)
#define X(_N,_C) case DW_Form_##_N: return _C; #define X(_N,_C) case DW_Form_##_N: return _C;
switch (k) { switch (k) {
DW_Form_AttribClass_GNU_XList(X) DW_Form_AttribClass_GNU_XList
} }
switch (ver) { switch (ver) {
case DW_Version_5: { case DW_Version_5: {
switch (k) { switch (k) {
DW_Form_AttribClass_V5_XList(X) DW_Form_AttribClass_V5_XList
} }
} break; } break;
case DW_Version_4: { case DW_Version_4: {
switch (k) { switch (k) {
DW_Form_AttribClass_V4_XList(X) DW_Form_AttribClass_V4_XList
} }
} break; } break;
case DW_Version_3: { case DW_Version_3: {
switch (k) { switch (k) {
DW_Form_AttribClass_V2_XList(X) DW_Form_AttribClass_V2_XList
} }
} break; } break;
case DW_Version_2: { case DW_Version_2: {
switch (k) { switch (k) {
DW_Form_AttribClass_V2_XList(X) DW_Form_AttribClass_V2_XList
} }
} break; } break;
case DW_Version_1: { case DW_Version_1: {
@@ -261,7 +261,7 @@ dw_name_string_from_section_kind(DW_SectionKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_L); #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_L);
DW_SectionKind_XList(X) DW_SectionKind_XList
#undef X #undef X
} }
return str8_zero(); return str8_zero();
@@ -272,7 +272,7 @@ dw_mach_name_string_from_section_kind(DW_SectionKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_M); #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_M);
DW_SectionKind_XList(X) DW_SectionKind_XList
#undef X #undef X
} }
return str8_zero(); return str8_zero();
@@ -283,7 +283,7 @@ dw_dwo_name_string_from_section_kind(DW_SectionKind k)
{ {
switch (k) { switch (k) {
#define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_D); #define X(_N,_L,_M,_D) case DW_Section_##_N: return str8_lit(_D);
DW_SectionKind_XList(X) DW_SectionKind_XList
#undef X #undef X
} }
return str8_zero(); return str8_zero();
@@ -460,7 +460,7 @@ dw_operand_count_from_cfa_opcode(DW_CFA_Opcode opcode)
{ {
switch (opcode) { switch (opcode) {
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; } #define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return ArrayCount(t)-1; }
DW_CFA_Kind_XList(X) DW_CFA_Kind_XList
#undef X #undef X
default: { NotImplemented; } break; default: { NotImplemented; } break;
} }
@@ -513,7 +513,7 @@ dw_operand_types_from_cfa_op(DW_CFA_Opcode opcode)
{ {
switch (opcode) { switch (opcode) {
#define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; } #define X(_N, _ID, ...) case _ID: { local_persist DW_CFA_OperandType t[] = { DW_CFA_OperandType_Null, __VA_ARGS__ }; return &t[0] + 1; }
DW_CFA_Kind_XList(X) DW_CFA_Kind_XList
#undef X #undef X
default: { NotImplemented; } break; default: { NotImplemented; } break;
} }
@@ -581,9 +581,9 @@ dw_string_from_tag_kind(Arena *arena, DW_TagKind kind)
switch (kind) { switch (kind) {
case DW_TagKind_Null: return str8_lit("Null"); case DW_TagKind_Null: return str8_lit("Null");
#define X(_N,_ID) case DW_TagKind_##_N: return str8_lit(Stringify(_N)); #define X(_N,_ID) case DW_TagKind_##_N: return str8_lit(Stringify(_N));
DW_TagKind_V3_XList(X) DW_TagKind_V3_XList
DW_TagKind_V5_XList(X) DW_TagKind_V5_XList
DW_TagKind_GNU_XList(X) DW_TagKind_GNU_XList
#undef X #undef X
} }
return push_str8f(arena, "%llx", kind); return push_str8f(arena, "%llx", kind);
@@ -611,10 +611,10 @@ dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKi
{ {
default:{}break; default:{}break;
case DW_Ext_Null: break; case DW_Ext_Null: break;
case DW_Ext_GNU: switch (kind) { DW_AttribKind_GNU_XList(X) } break; case DW_Ext_GNU: switch (kind) { DW_AttribKind_GNU_XList } break;
case DW_Ext_LLVM: switch (kind) { DW_AttribKind_LLVM_XList(X) } break; case DW_Ext_LLVM: switch (kind) { DW_AttribKind_LLVM_XList } break;
case DW_Ext_APPLE: switch (kind) { DW_AttribKind_APPLE_XList(X) } break; case DW_Ext_APPLE: switch (kind) { DW_AttribKind_APPLE_XList } break;
case DW_Ext_MIPS: switch (kind) { DW_AttribKind_MIPS_XList(X) } break; case DW_Ext_MIPS: switch (kind) { DW_AttribKind_MIPS_XList } break;
} }
} }
} }
@@ -627,10 +627,10 @@ dw_string_from_attrib_kind(Arena *arena, DW_Version ver, DW_Ext ext, DW_AttribKi
DW_Version version = retry ? DW_Version_5 : ver; DW_Version version = retry ? DW_Version_5 : ver;
switch(version) switch(version)
{ {
case DW_Version_5: { switch(kind) { DW_AttribKind_V5_XList(X) } } // fall-through case DW_Version_5: { switch(kind) { DW_AttribKind_V5_XList } } // fall-through
case DW_Version_4: { switch(kind) { DW_AttribKind_V4_XList(X) } } // fall-through case DW_Version_4: { switch(kind) { DW_AttribKind_V4_XList } } // fall-through
case DW_Version_3: { switch(kind) { DW_AttribKind_V3_XList(X) } } // fall-through case DW_Version_3: { switch(kind) { DW_AttribKind_V3_XList } } // fall-through
case DW_Version_2: { switch(kind) { DW_AttribKind_V2_XList(X) } } // fall-through case DW_Version_2: { switch(kind) { DW_AttribKind_V2_XList } } // fall-through
case DW_Version_1: {}break; case DW_Version_1: {}break;
case DW_Version_Null:{}break; case DW_Version_Null:{}break;
default:{}break; default:{}break;
@@ -655,18 +655,18 @@ dw_string_from_form_kind(Arena *arena, DW_Version ver, DW_FormKind kind)
switch (ver) { switch (ver) {
case DW_Version_5: { case DW_Version_5: {
switch (kind) { switch (kind) {
DW_Form_V5_XList(X) DW_Form_V5_XList
} }
} // fall-through } // fall-through
case DW_Version_4: { case DW_Version_4: {
switch (kind) { switch (kind) {
DW_Form_V4_XList(X) DW_Form_V4_XList
} }
} // fall-through } // fall-through
case DW_Version_3: case DW_Version_3:
case DW_Version_2: { case DW_Version_2: {
switch (kind) { switch (kind) {
DW_Form_V2_XList(X) DW_Form_V2_XList
} }
} // fall-through } // fall-through
case DW_Version_Null: break; case DW_Version_Null: break;
@@ -681,7 +681,7 @@ dw_string_from_language(Arena *arena, DW_Language kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N)); #define X(_N,_ID) case DW_Language_##_N: return str8_lit(Stringify(_N));
DW_Language_XList(X) DW_Language_XList
#undef X #undef X
} }
return push_str8f(arena, "%x", kind); return push_str8f(arena, "%x", kind);
@@ -692,7 +692,7 @@ dw_string_from_inl(Arena *arena, DW_InlKind kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_Inl_XList(X) DW_Inl_XList
#undef X #undef X
} }
return push_str8f(arena, "%x", kind); return push_str8f(arena, "%x", kind);
@@ -703,7 +703,7 @@ dw_string_from_access_kind(Arena *arena, DW_AccessKind kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_AccessKind_XList(X) DW_AccessKind_XList
#undef X #undef X
} }
return push_str8f(arena, "%llx", kind); return push_str8f(arena, "%llx", kind);
@@ -714,7 +714,7 @@ dw_string_from_calling_convetion(Arena *arena, DW_CallingConventionKind kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_CallingConventionKind_XList(X) DW_CallingConventionKind_XList
#undef X #undef X
} }
return push_str8f(arena, "%llx", kind); return push_str8f(arena, "%llx", kind);
@@ -725,7 +725,7 @@ dw_string_from_attrib_type_encoding(Arena *arena, DW_ATE kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case _ID: return str8_lit(Stringify(_N)); #define X(_N,_ID) case _ID: return str8_lit(Stringify(_N));
DW_ATE_XList(X) DW_ATE_XList
#undef X #undef X
} }
return push_str8f(arena, "%llx", kind); return push_str8f(arena, "%llx", kind);
@@ -736,7 +736,7 @@ dw_string_from_std_opcode(Arena *arena, DW_StdOpcode kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N)); #define X(_N,_ID) case DW_StdOpcode_##_N: return str8_lit(Stringify(_N));
DW_StdOpcode_XList(X) DW_StdOpcode_XList
#undef X #undef X
} }
return push_str8f(arena, "%x", kind); return push_str8f(arena, "%x", kind);
@@ -747,7 +747,7 @@ dw_string_from_ext_opcode(Arena *arena, DW_ExtOpcode kind)
{ {
switch (kind) { switch (kind) {
#define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N)); #define X(_N,_ID) case DW_ExtOpcode_##_N: return str8_lit(Stringify(_N));
DW_ExtOpcode_XList(X) DW_ExtOpcode_XList
#undef X #undef X
default: InvalidPath; break; default: InvalidPath; break;
} }
@@ -784,7 +784,7 @@ dw_string_from_register(Arena *arena, Arch arch, U64 reg_id)
case Arch_x64: { case Arch_x64: {
switch (reg_id) { switch (reg_id) {
#define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break; #define X(_N, _ID, ...) case DW_RegX64_##_N: reg_str = str8_lit(Stringify(_N)); break;
DW_Regs_X64_XList(X) DW_Regs_X64_XList
#undef X #undef X
} }
} break; } break;
@@ -804,7 +804,7 @@ dw_string_from_cfa_opcode(DW_CFA_Opcode opcode)
{ {
switch (opcode) { switch (opcode) {
#define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME)); #define X(_NAME, _ID, ...) case _ID: return str8_lit(Stringify(_NAME));
DW_CFA_Kind_XList(X) DW_CFA_Kind_XList
#undef X #undef X
default: InvalidPath; break; default: InvalidPath; break;
} }
+1186 -1209
View File
File diff suppressed because it is too large Load Diff
+73 -38
View File
@@ -1127,23 +1127,30 @@ dw_expr_inst_from_delta(DW_ExprInst *inst, S16 delta)
return i; return i;
} }
internal DW_UnwindStatus internal DW_ExprEvalResult
dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_read, void *reg_read_ud, DW_ExprValue *value_out) dw_eval_expr(Arena *arena, Arch arch, DW_Format format, U64 cfa, U64 tls, U64 exec_op_limit, DW_Expr expr, MachineOp_RegRead *reg_read, void *reg_read_ud, DW_ExprValue *value_out)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
DW_UnwindStatus result = DW_UnwindStatus_Ok;
DW_PieceList pieces = {0}; DW_ExprEvalResult result = DW_ExprEvalResult_Fail;
DW_ExprStack *stack = push_array(scratch.arena, DW_ExprStack, 1); DW_PieceList pieces = {0};
B32 is_ok = 1; DW_ExprStack *stack = push_array(scratch.arena, DW_ExprStack, 1);
U64 exec_op_count = 0;
for EachNode(inst, DW_ExprInst, expr.first) { for EachNode(inst, DW_ExprInst, expr.first) {
again:; again:;
exec_op_count += 1;
if (exec_op_count > exec_op_limit) {
Assert(0 && "reached opcode exec limit on the expression");
result = DW_ExprEvalResult_ExecOpLimitReached;
goto exit;
}
U64 pop_count = dw_pop_count_from_expr_op(inst->opcode); U64 pop_count = dw_pop_count_from_expr_op(inst->opcode);
if (pop_count >= stack->count) { if (pop_count > stack->count) {
Assert(0 && "not enough values on the stack to evaluate the instruction"); Assert(0 && "not enough values on the stack to evaluate the instruction");
is_ok = 0; goto exit;
break;
} }
switch (inst->opcode) { switch (inst->opcode) {
@@ -1187,18 +1194,18 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29: case DW_ExprOp_Reg27: case DW_ExprOp_Reg28: case DW_ExprOp_Reg29:
case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: { case DW_ExprOp_Reg30: case DW_ExprOp_Reg31: {
DW_Reg reg_id = inst->opcode - DW_ExprOp_Reg0; DW_Reg reg_id = inst->opcode - DW_ExprOp_Reg0;
U64 reg_size = dw_reg_size_from_code(ctx->arch, reg_id); U64 reg_size = dw_reg_size_from_code(arch, reg_id);
U8 *reg_value = push_array(scratch.arena, U8, reg_size); U8 *reg_value = push_array(scratch.arena, U8, reg_size);
result = reg_read(reg_id, reg_value, reg_size, reg_read_ud); MachineOpResult reg_read_result = reg_read(reg_id, reg_value, reg_size, reg_read_ud);
if (result != DW_UnwindStatus_Ok) { goto exit; } if (reg_read_result != MachineOpResult_Ok) { goto exit; }
dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size); dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size);
} break; } break;
case DW_ExprOp_RegX: { case DW_ExprOp_RegX: {
U64 reg_size = dw_reg_size_from_code(ctx->arch, inst->operands[0].u64); U64 reg_size = dw_reg_size_from_code(arch, inst->operands[0].u64);
U8 *reg_value = push_array(scratch.arena, U8, reg_size); U8 *reg_value = push_array(scratch.arena, U8, reg_size);
result = reg_read(inst->operands[0].u64, reg_value, reg_size, reg_read_ud); MachineOpResult reg_read_result = reg_read(inst->operands[0].u64, reg_value, reg_size, reg_read_ud);
if (result != DW_UnwindStatus_Ok) { goto exit; } if (reg_read_result != MachineOpResult_Ok) { goto exit; }
dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size); dw_expr_stack_push_unsigned(scratch.arena, stack, reg_value, reg_size);
} break; } break;
@@ -1212,12 +1219,12 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
case DW_ExprOp_Piece: { case DW_ExprOp_Piece: {
if (stack->count) { if (stack->count) {
String8 value = dw_string_from_expr_value(arena, ctx->arch, dw_expr_stack_pop(stack)); String8 value = dw_string_from_expr_value(arena, arch, dw_expr_stack_pop(stack));
if (inst->operands[0].u64 <= value.size) { if (inst->operands[0].u64 <= value.size) {
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .value = { .ptr = value.str, .bit_size = inst->operands[0].u64 * 8 }}); dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .value = { .ptr = value.str, .bit_size = inst->operands[0].u64 * 8 }});
} else { } else {
Assert(0 && "out of bounds size in the piece opcode"); Assert(0 && "out of bounds size in the piece opcode");
result = DW_UnwindStatus_Fail; goto exit;
} }
} else { } else {
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .undef_bit_size = inst->operands[0].u64 * 8 }); dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .undef_bit_size = inst->operands[0].u64 * 8 });
@@ -1225,12 +1232,12 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
} break; } break;
case DW_ExprOp_BitPiece: { case DW_ExprOp_BitPiece: {
if (stack->count) { if (stack->count) {
String8 value = dw_string_from_expr_value(arena, ctx->arch, dw_expr_stack_pop(stack)); String8 value = dw_string_from_expr_value(arena, arch, dw_expr_stack_pop(stack));
if (inst->operands[0].u64 <= value.size * 8) { if (inst->operands[0].u64 <= value.size * 8) {
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .value = { .ptr = value.str, .bit_size = inst->operands[0].u64 }}); dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Value, .value = { .ptr = value.str, .bit_size = inst->operands[0].u64 }});
} else { } else {
Assert(0 && "out of bounds size in the bit piece opcode"); Assert(0 && "out of bounds size in the bit piece opcode");
result = DW_UnwindStatus_Fail; goto exit;
} }
} else { } else {
dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .undef_bit_size = inst->operands[0].u64 }); dw_piece_list_push(arena, &pieces, (DW_Piece){ .kind = DW_PieceKind_Undefined, .undef_bit_size = inst->operands[0].u64 });
@@ -1243,7 +1250,7 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
dw_expr_stack_push(scratch.arena, stack, src->v); dw_expr_stack_push(scratch.arena, stack, src->v);
} else { } else {
Assert(0 && "out of bounds stack index"); Assert(0 && "out of bounds stack index");
result = DW_UnwindStatus_Fail; goto exit;
} }
} break; } break;
@@ -1253,7 +1260,7 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
dw_expr_stack_push(scratch.arena, stack, src->v); dw_expr_stack_push(scratch.arena, stack, src->v);
} else { } else {
Assert(0 && "out of bounds stack index"); Assert(0 && "out of bounds stack index");
result = DW_UnwindStatus_Fail; goto exit;
} }
} break; } break;
@@ -1269,8 +1276,7 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
if (i == 0) { if (i == 0) {
Assert(0 && "seeking to an invalid offset"); Assert(0 && "seeking to an invalid offset");
result = DW_UnwindStatus_Fail; goto exit;
break;
} }
inst = i; inst = i;
@@ -1282,16 +1288,14 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
if (cond.type != DW_ExprValueType_S16) { if (cond.type != DW_ExprValueType_S16) {
Assert(0 && "unexpected value"); Assert(0 && "unexpected value");
result = DW_UnwindStatus_Fail; goto exit;
break;
} }
DW_ExprInst *i = dw_expr_inst_from_delta(inst, inst->operands[0].s16); DW_ExprInst *i = dw_expr_inst_from_delta(inst, inst->operands[0].s16);
if (i == 0) { if (i == 0) {
Assert(0 && "seeking to an invalid offset"); Assert(0 && "seeking to an invalid offset");
result = DW_UnwindStatus_Fail; goto exit;
break;
} }
inst = i; inst = i;
@@ -1334,18 +1338,17 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
case DW_ExprOp_EntryValue: case DW_ExprOp_EntryValue:
case DW_ExprOp_GNU_EntryValue: { case DW_ExprOp_GNU_EntryValue: {
DW_Expr entry_value_expr = dw_expr_from_data(scratch.arena, ctx->format, byte_size_from_arch(ctx->arch), inst->operands[0].block); DW_Expr entry_value_expr = dw_expr_from_data(scratch.arena, format, byte_size_from_arch(arch), inst->operands[0].block);
DW_ExprValue entry_value; DW_ExprValue entry_value;
result = dw_eval_expr(scratch.arena, ctx, entry_value_expr, reg_read, reg_read_ud, &entry_value); result = dw_eval_expr(scratch.arena, arch, format, cfa, tls, exec_op_limit, entry_value_expr, reg_read, reg_read_ud, &entry_value);
if (result == DW_UnwindStatus_Ok) { if (result != DW_ExprEvalResult_Ok) { goto exit; }
dw_expr_stack_push(scratch.arena, stack, entry_value); dw_expr_stack_push(scratch.arena, stack, entry_value);
}
} break; } break;
case DW_ExprOp_Addrx: { NotImplemented; } break; case DW_ExprOp_Addrx: { NotImplemented; } break;
case DW_ExprOp_CallFrameCfa: { case DW_ExprOp_CallFrameCfa: {
dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = ctx->cfa }); dw_expr_stack_push(scratch.arena, stack, (DW_ExprValue){ .type = DW_ExprValueType_U64, .u64 = cfa });
} break; } break;
case DW_ExprOp_PushObjectAddress: { NotImplemented; } break; case DW_ExprOp_PushObjectAddress: { NotImplemented; } break;
@@ -1399,35 +1402,43 @@ dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_re
} break; } break;
case DW_ExprOp_StackValue: { case DW_ExprOp_StackValue: {
stack->top->v.type = dw_expr_unsigned_value_type_from_bit_size(byte_size_from_arch(ctx->arch) * 8); stack->top->v.type = dw_expr_unsigned_value_type_from_bit_size(bit_size_from_arch(arch));
} break; } break;
case DW_ExprOp_GNU_PushTlsAddress: case DW_ExprOp_GNU_PushTlsAddress:
case DW_ExprOp_FormTlsAddress: { case DW_ExprOp_FormTlsAddress: {
DW_ExprValue tls_off = dw_expr_stack_pop(stack); DW_ExprValue tls_off = dw_expr_stack_pop(stack);
DW_ExprValue tls_base = { .type = DW_ExprValueType_Addr, .addr = ctx->tls_base }; DW_ExprValue tls_base = { .type = DW_ExprValueType_Addr, .addr = tls };
DW_ExprValue tls_addr = dw_expr_add(tls_base, tls_off); DW_ExprValue tls_addr = dw_expr_add(tls_base, tls_off);
dw_expr_stack_push(scratch.arena, stack, tls_addr); dw_expr_stack_push(scratch.arena, stack, tls_addr);
} break; } break;
} }
} }
result = DW_ExprEvalResult_Ok;
exit:; exit:;
scratch_end(scratch); scratch_end(scratch);
return result; return result;
} }
internal String8 internal String8
dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs, U64 encs_count) dw_encode_expr(Arena *arena, Arch arch, DW_Format format, DW_ExprEnc *encs, U64 encs_count)
{ {
Temp scratch = scratch_begin(&arena, 1); Temp scratch = scratch_begin(&arena, 1);
String8List *srl = push_array(scratch.arena, String8List, 1); String8List *srl = push_array(scratch.arena, String8List, 1);
str8_serial_begin(scratch.arena, srl); str8_serial_begin(scratch.arena, srl);
HashTable *label_map = hash_table_init(scratch.arena, 128);
struct Fixup { U64 offset; String8 label; struct Fixup *next; };
struct Fixup *first_fixup = 0, *last_fixup = 0;
for EachIndex(i, encs_count) { for EachIndex(i, encs_count) {
DW_ExprEnc *e = &encs[i]; DW_ExprEnc *e = &encs[i];
switch (e->type) { switch (e->type) {
case DW_ExprEncType_Null: {} break;
case DW_ExprEncType_Op: { case DW_ExprEncType_Op: {
str8_serial_push_struct(scratch.arena, srl, &e->op); str8_serial_push_struct(scratch.arena, srl, &e->op);
} break; } break;
@@ -1487,6 +1498,7 @@ dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs,
str8_serial_push_string(scratch.arena, srl, str8(buffer, buffer_size)); str8_serial_push_string(scratch.arena, srl, str8(buffer, buffer_size));
} break; } break;
case DW_ExprEncType_Addr: { case DW_ExprEncType_Addr: {
U64 addr_size = byte_size_from_arch(arch);
Assert(addr_size <= sizeof(e->addr)); Assert(addr_size <= sizeof(e->addr));
str8_serial_push_string(scratch.arena, srl, str8((U8 *)&e->addr, addr_size)); str8_serial_push_string(scratch.arena, srl, str8((U8 *)&e->addr, addr_size));
} break; } break;
@@ -1504,16 +1516,39 @@ dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs,
} }
} break; } break;
case DW_ExprEncType_Label: { case DW_ExprEncType_Label: {
// TODO: struct Fixup *fixup = push_array(scratch.arena, struct Fixup, 1);
fixup->offset = srl->total_size;
fixup->label = e->label;
SLLQueuePush(first_fixup, last_fixup, fixup);
S16 delta_placeholder = 0;
str8_serial_push_struct(scratch.arena, srl, &delta_placeholder);
} break; } break;
case DW_ExprEncType_DeclLabel: { case DW_ExprEncType_DeclLabel: {
// TODO: hash_table_push_string_u64(scratch.arena, label_map, e->label, srl->total_size);
} break; } break;
default: { InvalidPath; } break; default: { InvalidPath; } break;
} }
} }
// finalize expression
String8 expr = str8_serial_end(arena, srl); String8 expr = str8_serial_end(arena, srl);
// apply fixups
for EachNode(fixup, struct Fixup, first_fixup) {
U64 label_offset;
if (!hash_table_search_string_u64(label_map, fixup->label, &label_offset)) {
Assert(0 && "undefined label");
continue;
}
S64 delta = (S64)label_offset - (S64)fixup->offset;
AssertAlways(min_S16 <= delta && delta <= max_S16);
S16 *delta_ptr = (S16 *)(expr.str + fixup->offset);
*delta_ptr = delta;
}
scratch_end(scratch); scratch_end(scratch);
return expr; return expr;
} }
+33 -33
View File
@@ -7,14 +7,6 @@
//////////////////////////////// ////////////////////////////////
// evaluator // evaluator
typedef struct DW_ExprContext
{
Arch arch;
DW_Format format;
U64 cfa;
U64 tls_base;
} DW_ExprContext;
#define DW_ExprValueType_IsSigned(x) ((x) == DW_ExprValueType_S8 || (x) == DW_ExprValueType_S16 || (x) == DW_ExprValueType_S32 || (x) == DW_ExprValueType_S64 || (x) == DW_ExprValueType_S128 || (x) == DW_ExprValueType_S256 || (x) == DW_ExprValueType_S512) #define DW_ExprValueType_IsSigned(x) ((x) == DW_ExprValueType_S8 || (x) == DW_ExprValueType_S16 || (x) == DW_ExprValueType_S32 || (x) == DW_ExprValueType_S64 || (x) == DW_ExprValueType_S128 || (x) == DW_ExprValueType_S256 || (x) == DW_ExprValueType_S512)
#define DW_ExprValueType_IsUnsigned(x) ((x) == DW_ExprValueType_U8 || (x) == DW_ExprValueType_U16 || (x) == DW_ExprValueType_U32 || (x) == DW_ExprValueType_U64 || (x) == DW_ExprValueType_U128 || (x) == DW_ExprValueType_U256 || (x) == DW_ExprValueType_U512) #define DW_ExprValueType_IsUnsigned(x) ((x) == DW_ExprValueType_U8 || (x) == DW_ExprValueType_U16 || (x) == DW_ExprValueType_U32 || (x) == DW_ExprValueType_U64 || (x) == DW_ExprValueType_U128 || (x) == DW_ExprValueType_U256 || (x) == DW_ExprValueType_U512)
#define DW_ExprValueType_IsFloat(x) ((x) == DW_ExprValueType_F32 || (x) == DW_ExprValueType_F64) #define DW_ExprValueType_IsFloat(x) ((x) == DW_ExprValueType_F32 || (x) == DW_ExprValueType_F64)
@@ -75,12 +67,6 @@ typedef struct DW_ExprValueNode
struct DW_ExprValueNode *next; struct DW_ExprValueNode *next;
} DW_ExprValueNode; } DW_ExprValueNode;
typedef struct DW_ExprStack
{
U64 count;
DW_ExprValueNode *top;
} DW_ExprStack;
typedef enum typedef enum
{ {
DW_PieceKind_Null, DW_PieceKind_Null,
@@ -113,11 +99,25 @@ typedef struct DW_PieceList
DW_PieceNode *last; DW_PieceNode *last;
} DW_PieceList; } DW_PieceList;
typedef struct DW_ExprStack
{
U64 count;
DW_ExprValueNode *top;
} DW_ExprStack;
typedef struct DW_ExprResult typedef struct DW_ExprResult
{ {
int x; int x;
} DW_ExprResult; } DW_ExprResult;
typedef enum
{
DW_ExprEvalResult_Fail,
DW_ExprEvalResult_Ok,
DW_ExprEvalResult_Maybe,
DW_ExprEvalResult_ExecOpLimitReached,
} DW_ExprEvalResult;
//////////////////////////////// ////////////////////////////////
// encoder // encoder
@@ -157,26 +157,26 @@ typedef struct DW_ExprEnc
S64 s64; S64 s64;
U64 addr; U64 addr;
String8 block; String8 block;
char *label; String8 label;
}; };
} DW_ExprEnc; } DW_ExprEnc;
#define DW_ExprEnc_Op(v) { .type = DW_ExprEncType_Op, .op = DW_ExprOp_##v } #define DW_ExprEnc_Op(v) { .type = DW_ExprEncType_Op, .op = DW_ExprOp_##v }
#define DW_ExprEnc_U8(v) { .type = DW_ExprEncType_U8, .u8 = v } #define DW_ExprEnc_U8(v) { .type = DW_ExprEncType_U8, .u8 = v }
#define DW_ExprEnc_U16(v) { .type = DW_ExprEncType_U16, .u16 = v } #define DW_ExprEnc_U16(v) { .type = DW_ExprEncType_U16, .u16 = v }
#define DW_ExprEnc_U32(v) { .type = DW_ExprEncType_U32, .u32 = v } #define DW_ExprEnc_U32(v) { .type = DW_ExprEncType_U32, .u32 = v }
#define DW_ExprEnc_U64(v) { .type = DW_ExprEncType_U64, .u64 = v } #define DW_ExprEnc_U64(v) { .type = DW_ExprEncType_U64, .u64 = v }
#define DW_ExprEnc_S8(v) { .type = DW_ExprEncType_S8, .s8 = v } #define DW_ExprEnc_S8(v) { .type = DW_ExprEncType_S8, .s8 = v }
#define DW_ExprEnc_S16(v) { .type = DW_ExprEncType_S16, .s16 = v } #define DW_ExprEnc_S16(v) { .type = DW_ExprEncType_S16, .s16 = v }
#define DW_ExprEnc_S32(v) { .type = DW_ExprEncType_S32, .s32 = v } #define DW_ExprEnc_S32(v) { .type = DW_ExprEncType_S32, .s32 = v }
#define DW_ExprEnc_S64(v) { .type = DW_ExprEncType_S64, .s64 = v } #define DW_ExprEnc_S64(v) { .type = DW_ExprEncType_S64, .s64 = v }
#define DW_ExprEnc_ULEB128(v) { .type = DW_ExprEncType_ULEB128, .u64 = v } #define DW_ExprEnc_ULEB128(v) { .type = DW_ExprEncType_ULEB128, .u64 = v }
#define DW_ExprEnc_SLEB128(v) { .type = DW_ExprEncType_SLEB128, .s64 = v } #define DW_ExprEnc_SLEB128(v) { .type = DW_ExprEncType_SLEB128, .s64 = v }
#define DW_ExprEnc_Addr(v) { .type = DW_ExprEncType_Addr, .addr = v } #define DW_ExprEnc_Addr(v) { .type = DW_ExprEncType_Addr, .addr = v }
#define DW_ExprEnc_Block(v) { .type = DW_ExprEncType_Block, .block = v } #define DW_ExprEnc_Block(v) { .type = DW_ExprEncType_Block, .block = v }
#define DW_ExprEnc_UInt(v) { .type = DW_ExprEncType_DwarfUInt, .u64 = v } #define DW_ExprEnc_UInt(v) { .type = DW_ExprEncType_DwarfUInt, .u64 = v }
#define DW_ExprEnc_Label(v) { .type = DW_ExprEncType_Label, .label = v } #define DW_ExprEnc_Label(v) { .type = DW_ExprEncType_Label, .label = str8_lit_comp(v) }
#define DW_ExprEnc_DeclLabel(v) { .type = DW_ExprEncType_DeclLabel, .label = v } #define DW_ExprEnc_DeclLabel(v) { .type = DW_ExprEncType_DeclLabel, .label = str8_lit_comp(v) }
//////////////////////////////// ////////////////////////////////
@@ -235,10 +235,10 @@ internal DW_ExprValueNode * dw_expr_stack_pick(DW_ExprStack *stack, U64 idx);
internal String8 dw_string_from_expr_value(Arena *arena, U64 addr_size, DW_ExprValue v); internal String8 dw_string_from_expr_value(Arena *arena, U64 addr_size, DW_ExprValue v);
// evaluator // evaluator
internal DW_UnwindStatus dw_eval_expr(Arena *arena, DW_ExprContext *ctx, DW_Expr expr, DW_RegRead *reg_read, void *reg_read_ud, DW_ExprValue *value_out); internal DW_ExprEvalResult dw_eval_expr(Arena *arena, Arch arch, DW_Format format, U64 cfa, U64 tls_base, U64 op_limit, DW_Expr expr, MachineOp_RegRead *reg_read, void *reg_read_ud, DW_ExprValue *value_out);
// encoder // encoder
internal String8 dw_encode_expr(Arena *arena, DW_Format format, U64 addr_size, DW_ExprEnc *encs, U64 encs_count); internal String8 dw_encode_expr(Arena *arena, Arch arch, DW_Format format, DW_ExprEnc *encs, U64 encs_count);
#endif //DWARF_EXPR_H #endif //DWARF_EXPR_H
+2 -2
View File
@@ -176,7 +176,7 @@ dw_section_kind_from_string(String8 string)
#define X(_K,_L,_M,_W) \ #define X(_K,_L,_M,_W) \
if (str8_match_lit(_L, string, 0)) { s = DW_Section_##_K; } \ if (str8_match_lit(_L, string, 0)) { s = DW_Section_##_K; } \
if (str8_match_lit(_M, string, 0)) { s = DW_Section_##_K; } if (str8_match_lit(_M, string, 0)) { s = DW_Section_##_K; }
DW_SectionKind_XList(X) DW_SectionKind_XList
#undef X #undef X
return s; return s;
} }
@@ -187,7 +187,7 @@ dw_section_dwo_kind_from_string(String8 string)
DW_SectionKind s = DW_Section_Null; DW_SectionKind s = DW_Section_Null;
#define X(_K,_L,_M,_W) \ #define X(_K,_L,_M,_W) \
if (str8_match_lit(_W, string, 0)) { s = DW_Section_##_K; } if (str8_match_lit(_W, string, 0)) { s = DW_Section_##_K; }
DW_SectionKind_XList(X) DW_SectionKind_XList
#undef X #undef X
return s; return s;
} }
+1 -1
View File
@@ -73,7 +73,7 @@ d2r_rdi_reg_code_from_dw_reg_x64(DW_RegX64 v)
{ {
default:{}break; default:{}break;
#define X(reg_dw, val_dw, reg_rdi, off, size) case DW_RegX64_##reg_dw:{result = RDI_RegCodeX64_##reg_rdi;}break; #define X(reg_dw, val_dw, reg_rdi, off, size) case DW_RegX64_##reg_dw:{result = RDI_RegCodeX64_##reg_rdi;}break;
DW_Regs_X64_XList(X) DW_Regs_X64_XList
#undef X #undef X
} }
return result; return result;