mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-10-09 01:15:41 +00:00
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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -1739,6 +1739,11 @@ typedef enum DW_RegX64Enum
|
||||
DW_RegX64_Last
|
||||
} DW_RegX64Enum;
|
||||
|
||||
////////////////////////////////
|
||||
//~ rjf: Generated Code
|
||||
|
||||
#include "dwarf/generated/dwarf.meta.h"
|
||||
|
||||
////////////////////////////////
|
||||
// Speced Encodings
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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, ®_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, ®_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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
//- GENERATED CODE
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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)`
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user