eliminate os_core, move into base; eliminate regs, move into arch abstraction layer, define x64 regs in x64 layer; move win32 backend for os core (now base) functionality to top-level win32 layer

This commit is contained in:
Ryan Fleury
2026-05-08 15:21:21 -07:00
parent 24c858171f
commit aea4a4ff9d
148 changed files with 7942 additions and 5268 deletions
+5
View File
@@ -1,6 +1,11 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
////////////////////////////////
//~ rjf: Generated Code
#include "dwarf/generated/dwarf.meta.c"
internal DW_AttribClass
dw_attrib_class_from_attrib_v2(DW_AttribKind k)
{
+5
View File
@@ -1739,6 +1739,11 @@ typedef enum DW_RegX64Enum
DW_RegX64_Last
} DW_RegX64Enum;
////////////////////////////////
//~ rjf: Generated Code
#include "dwarf/generated/dwarf.meta.h"
////////////////////////////////
// Speced Encodings
+89
View File
@@ -0,0 +1,89 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
@table(name code byte_size)
DW_RegCodeTableX64:
{
{rax 0 8}
{rdx 1 8}
{rcx 2 8}
{rbx 3 8}
{rsi 4 8}
{rdi 5 8}
{rbp 6 8}
{rsp 7 8}
{r8 8 8}
{r9 9 8}
{r10 10 8}
{r11 11 8}
{r12 12 8}
{r13 13 8}
{r14 14 8}
{r15 15 8}
{rip 16 8}
{zmm0 17 16}
{zmm1 18 16}
{zmm2 19 16}
{zmm3 20 16}
{zmm4 21 16}
{zmm5 22 16}
{zmm6 23 16}
{zmm7 24 16}
{zmm8 25 16}
{zmm9 26 16}
{zmm10 27 16}
{zmm11 28 16}
{zmm12 29 16}
{zmm13 30 16}
{zmm14 31 16}
{zmm15 32 16}
{zmm16 67 16}
{zmm17 68 16}
{zmm18 69 16}
{zmm19 70 16}
{zmm20 71 16}
{zmm21 72 16}
{zmm22 73 16}
{zmm23 74 16}
{zmm24 75 16}
{zmm25 76 16}
{zmm26 77 16}
{zmm27 78 16}
{zmm28 79 16}
{zmm29 80 16}
{zmm30 81 16}
{zmm31 82 16}
{st0 33 10}
{st1 34 10}
{st2 35 10}
{st3 36 10}
{st4 37 10}
{st5 38 10}
{st6 39 10}
{st7 40 10}
{mm0 41 8}
{mm1 42 8}
{mm2 43 8}
{mm3 44 8}
{mm4 45 8}
{mm5 46 8}
{mm6 47 8}
{mm7 48 8}
{rflags 49 4}
{es 50 2}
{cs 51 2}
{ss 52 2}
{ds 53 2}
{fs 54 2}
{gs 55 2}
{fsbase 58 8}
{gsbase 59 8}
// privileged registers:
// {Tr 62 ???}
// {Ldtr 63 ???}
}
@enum DW_RegCodeX64:
{
@expand(DW_RegCodeTableX64 a) `$(a.name) = $(a.code)`,
}
+1120 -1106
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -227,7 +227,7 @@ 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);
// evaluator
internal DW_ExprEvalResult dw_eval_expr(Arena *arena, Arch arch, DW_Format format, U64 frame_base, U64 cfa, U64 tls_base, U64 op_limit, DW_Expr expr, MachineOp_RegRead *reg_read, void *reg_read_ud, MachineOp_MemRead *mem_read, void *mem_read_ud, DW_ExprValue *value_out);
internal DW_ExprEvalResult dw_eval_expr(Arena *arena, Arch arch, DW_Format format, U64 frame_base, U64 cfa, U64 tls_base, U64 op_limit, DW_Expr expr, void *reg_block, MachineOp_MemRead *mem_read, void *mem_read_ud, DW_ExprValue *value_out);
// encoder
internal String8 dw_encode_expr(Arena *arena, Arch arch, DW_Format format, DW_ExprEnc *encs, U64 encs_count);
+3
View File
@@ -13,3 +13,6 @@
#include "dwarf/dwarf_parse_2.c"
#include "dwarf/eh_frame.c"
#include "dwarf/eh_dump.c"
#if defined(X64_H)
# include "dwarf/x64/dwarf_x64.c"
#endif
+3
View File
@@ -16,5 +16,8 @@
#include "dwarf/dwarf_parse_2.h"
#include "dwarf/eh_frame.h"
#include "dwarf/eh_dump.h"
#if defined(X64_H)
# include "dwarf/x64/dwarf_x64.h"
#endif
#endif // DWARF_INC_H
+37
View File
@@ -56,6 +56,43 @@ dw2_read_fmt_u64(String8 data, U64 off, DW_Format format, U64 *out)
return bytes_read;
}
////////////////////////////////
//~ rjf: Unit Range Set Parsing (Top-Level .debug_info, .debug_aranges)
internal Rng1U64Array
dw2_unit_ranges_from_data(Arena *arena, String8 data)
{
Temp scratch = scratch_begin(&arena, 1);
Rng1U64List unit_range_list = {0};
for(U64 off = 0; off < data.size;)
{
U64 start_off = off;
// rjf: read next unit size
U64 unit_size = 0;
U64 unit_size_size = dw2_read_initial_length(data, off, &unit_size, 0);
// rjf: push
if(unit_size > 0)
{
rng1u64_list_push(scratch.arena, &unit_range_list, r1u64(off, off + unit_size_size + unit_size));
}
// rjf: advance
off += unit_size_size;
off += unit_size;
// rjf: break if no movement
if(off == start_off)
{
break;
}
}
Rng1U64Array result = rng1u64_array_from_list(arena, &unit_range_list);
scratch_end(scratch);
return result;
}
////////////////////////////////
//~ rjf: Unit Header Parsing
+5
View File
@@ -240,6 +240,11 @@ global read_only DW2_Attrib dw2_attrib_nil = {0};
internal U64 dw2_read_initial_length(String8 data, U64 off, U64 *out, DW_Format *fmt_out);
internal U64 dw2_read_fmt_u64(String8 data, U64 off, DW_Format format, U64 *out);
////////////////////////////////
//~ rjf: Unit Range Set Parsing (Top-Level .debug_info, .debug_aranges)
internal Rng1U64Array dw2_unit_ranges_from_data(Arena *arena, String8 data);
////////////////////////////////
//~ rjf: Unit Header Parsing
+212 -190
View File
@@ -36,7 +36,7 @@ dw_cfi_unwind_init(Arena *arena,
void *decode_ptr_ud)
{
Temp scratch = scratch_begin(&arena, 1);
DW_CFI_Unwind *uw = push_array(arena, DW_CFI_Unwind, 1);
uw->insts = dw_parse_cfa_inst_list(arena, fde->insts, cie->code_align_factor, cie->data_align_factor, decode_ptr_func, decode_ptr_ud);
uw->cie = cie;
@@ -44,7 +44,7 @@ dw_cfi_unwind_init(Arena *arena,
uw->pc = fde->pc_range.min;
uw->arch = arch;
uw->reg_count = dw_reg_count_from_arch(arch);
// setup initial register rules
DW_CFA_InstList initial_insts = dw_parse_cfa_inst_list(scratch.arena, cie->insts, cie->code_align_factor, cie->data_align_factor, decode_ptr_func, decode_ptr_ud);
uw->row = dw_make_cfi_row(arena, uw->reg_count);
@@ -52,12 +52,12 @@ dw_cfi_unwind_init(Arena *arena,
if (!dw_cfi_next_row(arena, uw)) {
AssertAlways(0 && "unable to interpret initial row instructions");
}
// make first row from initial rules
uw->initial_row = uw->row;
uw->row = dw_copy_cfi_row(arena, uw->initial_row, uw->reg_count);
uw->curr_inst = uw->insts.first;
scratch_end(scratch);
return uw;
}
@@ -67,7 +67,7 @@ dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw)
{
B32 is_row_valid = 0;
DW_CFA_InstNode *row_inst = uw->curr_inst;
// skip leading nops
while (uw->curr_inst) {
if (uw->curr_inst->v.opcode != DW_CFA_Nop) {
@@ -75,10 +75,10 @@ dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw)
}
uw->curr_inst = uw->curr_inst->next;
}
while (uw->curr_inst) {
DW_CFA_Inst *inst = &uw->curr_inst->v;
// validate register operands
DW_CFA_OperandType *operand_types = dw_operand_types_from_cfa_op(inst->opcode);
U64 operand_count = dw_operand_count_from_cfa_opcode(inst->opcode);
@@ -89,113 +89,113 @@ dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw)
}
}
}
switch (inst->opcode) {
// Row Creation Instructions
case DW_CFA_SetLoc: {
uw->pc = inst->operands[0].u64;
} break;
case DW_CFA_AdvanceLoc:
case DW_CFA_AdvanceLoc1:
case DW_CFA_AdvanceLoc2:
case DW_CFA_AdvanceLoc4: {
uw->pc += inst->operands[0].u64;
} break;
// CFA Definition Instructions
case DW_CFA_DefCfa:
case DW_CFA_DefCfaSf: {
U64 reg = inst->operands[0].u64;
S64 off = inst->operands[1].s64;
uw->row->cfa.rule = DW_CFA_Rule_RegOff;
uw->row->cfa.reg = reg;
uw->row->cfa.off = off;
} break;
case DW_CFA_DefCfaRegister: {
// TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset
if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; }
U64 reg = inst->operands[0].u64;
uw->row->cfa.reg = reg;
} break;
case DW_CFA_DefCfaOffset:
case DW_CFA_DefCfaOffsetSf: {
// TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset
if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; }
uw->row->cfa.off = inst->operands[0].s64;
} break;
case DW_CFA_DefCfaExpr: {
uw->row->cfa.rule = DW_CFA_Rule_Expression;
uw->row->cfa.expr = inst->operands[0].block;
} break;
// Register Rule Instructions
case DW_CFA_Undefined: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Undefined;
} break;
case DW_CFA_SameValue: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_SameValue;
} break;
case DW_CFA_Offset:
case DW_CFA_OffsetExt:
case DW_CFA_OffsetExtSf: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Offset;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_ValOffset:
case DW_CFA_ValOffsetSf: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValOffset;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_Register: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Register;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_Expr: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Expression;
uw->row->regs[reg].expr = inst->operands[1].block;
} break;
case DW_CFA_ValExpr: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValExpression;
uw->row->regs[reg].expr = inst->operands[1].block;
} break;
case DW_CFA_Restore:
case DW_CFA_RestoreExt: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg] = uw->initial_row->regs[reg];
} break;
// Row Creation Instructions
case DW_CFA_SetLoc: {
uw->pc = inst->operands[0].u64;
} break;
case DW_CFA_AdvanceLoc:
case DW_CFA_AdvanceLoc1:
case DW_CFA_AdvanceLoc2:
case DW_CFA_AdvanceLoc4: {
uw->pc += inst->operands[0].u64;
} break;
// Row State Instructions
case DW_CFA_RememberState: {
DW_CFI_Row *new_row = dw_copy_cfi_row(arena, uw->row, uw->reg_count);
SLLStackPush(uw->row, new_row);
} break;
case DW_CFA_RestoreState: {
if (uw->row == 0) { goto exit; } // TODO: report error: unbalanced number of pushes and pops
DW_CFI_Row *free_row = uw->row;
SLLStackPop(uw->row);
SLLStackPush(uw->free_rows, free_row);
} break;
case DW_CFA_Nop: {} break;
default: { NotImplemented; } break; // TODO: report error: unknown CFA opcode
// CFA Definition Instructions
case DW_CFA_DefCfa:
case DW_CFA_DefCfaSf: {
U64 reg = inst->operands[0].u64;
S64 off = inst->operands[1].s64;
uw->row->cfa.rule = DW_CFA_Rule_RegOff;
uw->row->cfa.reg = reg;
uw->row->cfa.off = off;
} break;
case DW_CFA_DefCfaRegister: {
// TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset
if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; }
U64 reg = inst->operands[0].u64;
uw->row->cfa.reg = reg;
} break;
case DW_CFA_DefCfaOffset:
case DW_CFA_DefCfaOffsetSf: {
// TODO: report error: this operation is valid only if the current CFA rule is defined to register+offset
if (uw->row->cfa.rule != DW_CFA_Rule_RegOff) { goto exit; }
uw->row->cfa.off = inst->operands[0].s64;
} break;
case DW_CFA_DefCfaExpr: {
uw->row->cfa.rule = DW_CFA_Rule_Expression;
uw->row->cfa.expr = inst->operands[0].block;
} break;
// Register Rule Instructions
case DW_CFA_Undefined: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Undefined;
} break;
case DW_CFA_SameValue: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_SameValue;
} break;
case DW_CFA_Offset:
case DW_CFA_OffsetExt:
case DW_CFA_OffsetExtSf: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Offset;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_ValOffset:
case DW_CFA_ValOffsetSf: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValOffset;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_Register: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Register;
uw->row->regs[reg].n = inst->operands[1].s64;
} break;
case DW_CFA_Expr: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_Expression;
uw->row->regs[reg].expr = inst->operands[1].block;
} break;
case DW_CFA_ValExpr: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg].rule = DW_CFI_RegisterRule_ValExpression;
uw->row->regs[reg].expr = inst->operands[1].block;
} break;
case DW_CFA_Restore:
case DW_CFA_RestoreExt: {
U64 reg = inst->operands[0].u64;
uw->row->regs[reg] = uw->initial_row->regs[reg];
} break;
// Row State Instructions
case DW_CFA_RememberState: {
DW_CFI_Row *new_row = dw_copy_cfi_row(arena, uw->row, uw->reg_count);
SLLStackPush(uw->row, new_row);
} break;
case DW_CFA_RestoreState: {
if (uw->row == 0) { goto exit; } // TODO: report error: unbalanced number of pushes and pops
DW_CFI_Row *free_row = uw->row;
SLLStackPop(uw->row);
SLLStackPush(uw->free_rows, free_row);
} break;
case DW_CFA_Nop: {} break;
default: { NotImplemented; } break; // TODO: report error: unknown CFA opcode
}
uw->curr_inst = uw->curr_inst->next;
if (uw->curr_inst) {
if (dw_is_new_row_cfa_opcode(uw->curr_inst->v.opcode)) { break; }
}
}
is_row_valid = row_inst != 0;
exit:;
exit:;
return is_row_valid;
}
@@ -203,7 +203,7 @@ internal DW_CFI_Row *
dw_cfi_row_from_pc(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ctx, U64 pc)
{
Temp scratch = scratch_begin(&arena, 1);
B32 is_row_found = 0;
U64 reg_count = dw_reg_count_from_arch(arch);
DW_CFI_Unwind *uw = dw_cfi_unwind_init(scratch.arena, arch, cie, fde, decode_ptr_func, decode_ptr_ctx);
@@ -217,7 +217,7 @@ dw_cfi_row_from_pc(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodeP
dw_memcpy_cfi_row(row, uw->row, uw->reg_count);
prev_pc = uw->pc;
}
// handle last row
if (!is_row_found) {
if (contains_1u64(fde->pc_range, pc)) {
@@ -225,116 +225,138 @@ dw_cfi_row_from_pc(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodeP
is_row_found = 1;
}
}
// copy out final row
DW_CFI_Row *result = 0;
if (is_row_found) {
result = dw_copy_cfi_row(arena, row, reg_count);
}
scratch_end(scratch);
return result;
}
internal MachineOpResult
dw_compute_cfa(Arch arch,
DW_CFI_Row *row,
MachineOp_MemRead *mem_read_func, void *mem_read_ud,
MachineOp_RegRead *reg_read_func, void *reg_read_ud,
U64 *cfa_out)
dw_compute_cfa(Arch arch, DW_CFI_Row *row, void *reg_block, MachineOp_MemRead *mem_read_func, void *mem_read_ud, U64 *cfa_out)
{
MachineOpResult unwind_status = MachineOpResult_Fail;
switch (row->cfa.rule) {
case DW_CFA_Rule_Null: break;
case DW_CFA_Rule_RegOff: {
// TODO: report error (invalid register read)
U64 cfa_reg_value = 0;
U64 reg_size = dw_reg_size_from_code(arch, row->cfa.reg);
AssertAlways(reg_size <= sizeof(cfa_reg_value));
unwind_status = reg_read_func(row->cfa.reg, &cfa_reg_value, reg_size, reg_read_ud);
if (unwind_status != MachineOpResult_Ok) { break; }
*cfa_out = cfa_reg_value + row->cfa.off;
} break;
case DW_CFA_Rule_Expression: {
// TODO: evaluate expression
NotImplemented;
} break;
ARCH_Info *arch_info = arch_info_from_arch(arch);
switch(row->cfa.rule)
{
case DW_CFA_Rule_Null:{}break;
case DW_CFA_Rule_RegOff:
{
// TODO: report error (invalid register read)
U64 cfa_reg_value = 0;
U64 reg_size = dw_reg_size_from_code(arch, row->cfa.reg);
AssertAlways(reg_size <= sizeof(cfa_reg_value));
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, row->cfa.reg);
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
if(!arch_reg_block_read_range(arch_info, reg_block, reg_rng, &cfa_reg_value))
{
unwind_status = MachineOpResult_Fail;
break;
}
*cfa_out = cfa_reg_value + row->cfa.off;
}break;
case DW_CFA_Rule_Expression:
{
// TODO: evaluate expression
NotImplemented;
}break;
}
return unwind_status;
}
internal MachineOpResult
dw_cfi_apply_register_rules(Arch arch,
U64 cfa,
DW_CFI_Row *row,
MachineOp_MemRead *mem_read_func, void *mem_read_ud,
MachineOp_RegRead *reg_read_func, void *reg_read_ud,
MachineOp_RegWrite *reg_write_func, void *reg_write_ud)
dw_cfi_apply_register_rules(Arch arch, U64 cfa, DW_CFI_Row *row, void *reg_block, MachineOp_MemRead *mem_read_func, void *mem_read_ud)
{
Temp scratch = scratch_begin(0,0);
MachineOpResult unwind_status = MachineOpResult_Ok;
ARCH_Info *arch_info = arch_info_from_arch(arch);
U64 max_reg_size = dw_reg_max_size_from_arch(arch);
void *reg_buffer = push_array(scratch.arena, U8, max_reg_size);
U64 reg_count = dw_reg_count_from_arch(arch);
for EachIndex(reg_idx, reg_count) {
for EachIndex(reg_idx, reg_count)
{
DW_CFI_Register *reg = &row->regs[reg_idx];
switch (reg->rule) {
case DW_CFI_RegisterRule_Undefined: {} break;
case DW_CFI_RegisterRule_SameValue: {} break;
case DW_CFI_RegisterRule_Offset: {
// read register value from memory
U64 addr = cfa + reg->n;
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
unwind_status = mem_read_func(addr, reg_buffer, reg_size, mem_read_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
// write register value to the thread context
unwind_status = reg_write_func(reg_idx, reg_buffer, reg_size, reg_write_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
} break;
case DW_CFI_RegisterRule_ValOffset: {
// compute register value
U64 reg_value = cfa + reg->n;
// write register value to the thread context
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
unwind_status = reg_write_func(reg_idx, &reg_value, reg_size, reg_write_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
} break;
case DW_CFI_RegisterRule_Register: {
// read register value from another register
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
unwind_status = reg_read_func(reg->n, reg_buffer, reg_size, reg_read_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
// write register value to the thread context
unwind_status = reg_write_func(reg_idx, reg_buffer, reg_size, reg_write_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
} break;
case DW_CFI_RegisterRule_Expression: {
// TODO: evaluate expression
NotImplemented;
} break;
case DW_CFI_RegisterRule_ValExpression: {
// TODO: evaluate expression
NotImplemented;
} break;
case DW_CFI_RegisterRule_Architectural: {
NotImplemented;
} break;
default: { InvalidPath; } break;
ARCH_RegCode reg_code = arch_reg_code_from_dw(arch, reg_idx);
Rng1U16 reg_rng = arch_info->reg_code_rng_table[reg_code];
switch(reg->rule)
{
default:{}break;
case DW_CFI_RegisterRule_Undefined: {} break;
case DW_CFI_RegisterRule_SameValue: {} break;
case DW_CFI_RegisterRule_Offset:
{
// read register value from memory
U64 addr = cfa + reg->n;
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
unwind_status = mem_read_func(addr, reg_buffer, reg_size, mem_read_ud);
if (unwind_status != MachineOpResult_Ok) { goto exit; }
// write register value to the thread context
if(!arch_reg_block_write_range(arch_info, reg_block, reg_rng, reg_buffer))
{
unwind_status = MachineOpResult_Fail;
goto exit;
}
}break;
case DW_CFI_RegisterRule_ValOffset:
{
// compute register value
U64 reg_value = cfa + reg->n;
// write register value to the thread context
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
if(!arch_reg_block_write_range(arch_info, reg_block, reg_rng, &reg_value))
{
unwind_status = MachineOpResult_Fail;
goto exit;
}
}break;
case DW_CFI_RegisterRule_Register:
{
// read register value from another register
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
if(!arch_reg_block_read_range(arch_info, reg_block, reg_rng, reg_buffer))
{
unwind_status = MachineOpResult_Fail;
goto exit;
}
// write register value to the thread context
if(!arch_reg_block_write_range(arch_info, reg_block, reg_rng, reg_buffer))
{
unwind_status = MachineOpResult_Fail;
goto exit;
}
if (unwind_status != MachineOpResult_Ok) { goto exit; }
}break;
case DW_CFI_RegisterRule_Expression:
{
// TODO: evaluate expression
NotImplemented;
}break;
case DW_CFI_RegisterRule_ValExpression:
{
// TODO: evaluate expression
NotImplemented;
}break;
case DW_CFI_RegisterRule_Architectural:
{
NotImplemented;
}break;
}
}
// update stack pointer
U64 sp = dw_sp_from_arch(arch);
reg_write_func(sp, &cfa, sizeof(cfa), reg_write_ud);
exit:;
arch_reg_block_write_sp(arch_info, reg_block, cfa);
exit:;
scratch_end(scratch);
return unwind_status;
}
+2 -1
View File
@@ -74,7 +74,8 @@ internal DW_CFI_Unwind * dw_cfi_unwind_init(Arena *arena, Arch arch, DW_CIE *cie
internal B32 dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw);
internal DW_CFI_Row * dw_cfi_row_from_pc(Arena *arena, Arch arch, struct DW_CIE *cie, struct DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ctx, U64 pc);
internal MachineOpResult dw_cfi_apply_register_rules(Arch arch, U64 cfa, DW_CFI_Row *row, MachineOp_MemRead *mem_read_func, void *mem_read_ud, MachineOp_RegRead *reg_read_func, void *reg_read_ud, MachineOp_RegWrite *reg_write_func, void *reg_write_ud);
internal MachineOpResult dw_compute_cfa(Arch arch, DW_CFI_Row *row, void *reg_block, MachineOp_MemRead *mem_read_func, void *mem_read_ud, U64 *cfa_out);
internal MachineOpResult dw_cfi_apply_register_rules(Arch arch, U64 cfa, DW_CFI_Row *row, void *reg_block, MachineOp_MemRead *mem_read_func, void *mem_read_ud);
#endif // DWARF_UNWIND_H
+5
View File
@@ -0,0 +1,5 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
+87
View File
@@ -0,0 +1,87 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
#ifndef DWARF_META_H
#define DWARF_META_H
typedef enum DW_RegCodeX64
{
DW_RegCodeX64_rax = 0,
DW_RegCodeX64_rdx = 1,
DW_RegCodeX64_rcx = 2,
DW_RegCodeX64_rbx = 3,
DW_RegCodeX64_rsi = 4,
DW_RegCodeX64_rdi = 5,
DW_RegCodeX64_rbp = 6,
DW_RegCodeX64_rsp = 7,
DW_RegCodeX64_r8 = 8,
DW_RegCodeX64_r9 = 9,
DW_RegCodeX64_r10 = 10,
DW_RegCodeX64_r11 = 11,
DW_RegCodeX64_r12 = 12,
DW_RegCodeX64_r13 = 13,
DW_RegCodeX64_r14 = 14,
DW_RegCodeX64_r15 = 15,
DW_RegCodeX64_rip = 16,
DW_RegCodeX64_zmm0 = 17,
DW_RegCodeX64_zmm1 = 18,
DW_RegCodeX64_zmm2 = 19,
DW_RegCodeX64_zmm3 = 20,
DW_RegCodeX64_zmm4 = 21,
DW_RegCodeX64_zmm5 = 22,
DW_RegCodeX64_zmm6 = 23,
DW_RegCodeX64_zmm7 = 24,
DW_RegCodeX64_zmm8 = 25,
DW_RegCodeX64_zmm9 = 26,
DW_RegCodeX64_zmm10 = 27,
DW_RegCodeX64_zmm11 = 28,
DW_RegCodeX64_zmm12 = 29,
DW_RegCodeX64_zmm13 = 30,
DW_RegCodeX64_zmm14 = 31,
DW_RegCodeX64_zmm15 = 32,
DW_RegCodeX64_zmm16 = 67,
DW_RegCodeX64_zmm17 = 68,
DW_RegCodeX64_zmm18 = 69,
DW_RegCodeX64_zmm19 = 70,
DW_RegCodeX64_zmm20 = 71,
DW_RegCodeX64_zmm21 = 72,
DW_RegCodeX64_zmm22 = 73,
DW_RegCodeX64_zmm23 = 74,
DW_RegCodeX64_zmm24 = 75,
DW_RegCodeX64_zmm25 = 76,
DW_RegCodeX64_zmm26 = 77,
DW_RegCodeX64_zmm27 = 78,
DW_RegCodeX64_zmm28 = 79,
DW_RegCodeX64_zmm29 = 80,
DW_RegCodeX64_zmm30 = 81,
DW_RegCodeX64_zmm31 = 82,
DW_RegCodeX64_st0 = 33,
DW_RegCodeX64_st1 = 34,
DW_RegCodeX64_st2 = 35,
DW_RegCodeX64_st3 = 36,
DW_RegCodeX64_st4 = 37,
DW_RegCodeX64_st5 = 38,
DW_RegCodeX64_st6 = 39,
DW_RegCodeX64_st7 = 40,
DW_RegCodeX64_mm0 = 41,
DW_RegCodeX64_mm1 = 42,
DW_RegCodeX64_mm2 = 43,
DW_RegCodeX64_mm3 = 44,
DW_RegCodeX64_mm4 = 45,
DW_RegCodeX64_mm5 = 46,
DW_RegCodeX64_mm6 = 47,
DW_RegCodeX64_mm7 = 48,
DW_RegCodeX64_rflags = 49,
DW_RegCodeX64_es = 50,
DW_RegCodeX64_cs = 51,
DW_RegCodeX64_ss = 52,
DW_RegCodeX64_ds = 53,
DW_RegCodeX64_fs = 54,
DW_RegCodeX64_gs = 55,
DW_RegCodeX64_fsbase = 58,
DW_RegCodeX64_gsbase = 59,
} DW_RegCodeX64;
#endif // DWARF_META_H
+4
View File
@@ -0,0 +1,4 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#include "dwarf/x64/generated/dwarf_x64.meta.c"
+9
View File
@@ -0,0 +1,9 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
#ifndef DWARF_X64_H
#define DWARF_X64_H
#include "dwarf/x64/generated/dwarf_x64.meta.h"
#endif // DWARF_X64_H
+7
View File
@@ -0,0 +1,7 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
@data(U8) dw_reg_code_from_x64_table:
{
@expand(X64_RegTable a) `$(a.has_dwarf == 'x' -> "DW_RegCodeX64_" .. a.name)$(a.has_dwarf != 'x' -> 0)`
}
+201
View File
@@ -0,0 +1,201 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
C_LINKAGE_BEGIN
U8 dw_reg_code_from_x64_table[189] =
{
0,
DW_RegCodeX64_rax,
DW_RegCodeX64_rcx,
DW_RegCodeX64_rdx,
DW_RegCodeX64_rbx,
DW_RegCodeX64_rsp,
DW_RegCodeX64_rbp,
DW_RegCodeX64_rsi,
DW_RegCodeX64_rdi,
DW_RegCodeX64_r8,
DW_RegCodeX64_r9,
DW_RegCodeX64_r10,
DW_RegCodeX64_r11,
DW_RegCodeX64_r12,
DW_RegCodeX64_r13,
DW_RegCodeX64_r14,
DW_RegCodeX64_r15,
DW_RegCodeX64_fsbase,
DW_RegCodeX64_gsbase,
DW_RegCodeX64_rip,
DW_RegCodeX64_rflags,
0,
0,
0,
0,
0,
0,
0,
0,
DW_RegCodeX64_st0,
DW_RegCodeX64_st1,
DW_RegCodeX64_st2,
DW_RegCodeX64_st3,
DW_RegCodeX64_st4,
DW_RegCodeX64_st5,
DW_RegCodeX64_st6,
DW_RegCodeX64_st7,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
DW_RegCodeX64_ss,
DW_RegCodeX64_cs,
DW_RegCodeX64_ds,
DW_RegCodeX64_es,
DW_RegCodeX64_fs,
DW_RegCodeX64_gs,
DW_RegCodeX64_zmm0,
DW_RegCodeX64_zmm1,
DW_RegCodeX64_zmm2,
DW_RegCodeX64_zmm3,
DW_RegCodeX64_zmm4,
DW_RegCodeX64_zmm5,
DW_RegCodeX64_zmm6,
DW_RegCodeX64_zmm7,
DW_RegCodeX64_zmm8,
DW_RegCodeX64_zmm9,
DW_RegCodeX64_zmm10,
DW_RegCodeX64_zmm11,
DW_RegCodeX64_zmm12,
DW_RegCodeX64_zmm13,
DW_RegCodeX64_zmm14,
DW_RegCodeX64_zmm15,
DW_RegCodeX64_zmm16,
DW_RegCodeX64_zmm17,
DW_RegCodeX64_zmm18,
DW_RegCodeX64_zmm19,
DW_RegCodeX64_zmm20,
DW_RegCodeX64_zmm21,
DW_RegCodeX64_zmm22,
DW_RegCodeX64_zmm23,
DW_RegCodeX64_zmm24,
DW_RegCodeX64_zmm25,
DW_RegCodeX64_zmm26,
DW_RegCodeX64_zmm27,
DW_RegCodeX64_zmm28,
DW_RegCodeX64_zmm29,
DW_RegCodeX64_zmm30,
DW_RegCodeX64_zmm31,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
DW_RegCodeX64_mm0,
DW_RegCodeX64_mm1,
DW_RegCodeX64_mm2,
DW_RegCodeX64_mm3,
DW_RegCodeX64_mm4,
DW_RegCodeX64_mm5,
DW_RegCodeX64_mm6,
DW_RegCodeX64_mm7,
};
C_LINKAGE_END
+14
View File
@@ -0,0 +1,14 @@
// Copyright (c) Epic Games Tools
// Licensed under the MIT license (https://opensource.org/license/mit/)
//- GENERATED CODE
#ifndef DWARF_X64_META_H
#define DWARF_X64_META_H
C_LINKAGE_BEGIN
extern U8 dw_reg_code_from_x64_table[189];
C_LINKAGE_END
#endif // DWARF_X64_META_H