mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-10-09 01:15:41 +00:00
parser for .eh_frame versions of CIE and FDE and new helper for
mapping PC -> CFI Row
This commit is contained in:
committed by
Ryan Fleury
parent
ecbce1efdf
commit
da38f266d9
@@ -2237,7 +2237,8 @@ dw_dump_list_from_sections(Arena *arena,
|
||||
String8 cfi_regs_str = {0};
|
||||
{
|
||||
String8List cfi_regs_list = {0};
|
||||
for EachIndex(reg_idx, cfi_unwind->reg_count) {
|
||||
U64 reg_count = dw_reg_count_from_arch(arch);
|
||||
for EachIndex(reg_idx, reg_count) {
|
||||
DW_CFI_Register *cfi_reg = &cfi_unwind->row->regs[reg_idx];
|
||||
String8 rule_str = str8_lit("???");
|
||||
switch (cfi_reg->rule) {
|
||||
|
||||
@@ -61,7 +61,6 @@ read_only global String8 dw_name_title_from_dump_subset_table[] =
|
||||
internal String8 dw_string_from_reg_off(Arena *arena, Arch arch, DW_Reg reg_idx, S64 reg_off);
|
||||
internal String8List dw_string_list_from_expression (Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
|
||||
internal String8 dw_single_line_string_from_expression(Arena *arena, String8 raw_data, U64 cu_base, U64 address_size, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
|
||||
internal String8 dw_string_from_eh_ptr_enc (Arena *arena, EH_PtrEnc enc);
|
||||
|
||||
#if 0
|
||||
internal void dw_string_from_cfi_program (Arena *arena, String8List *out, String8 indent, String8 raw_data, DW_CIE *cie, EH_PtrCtx *ptr_ctx, Arch arch, DW_Version ver, DW_Ext ext, DW_Format format);
|
||||
|
||||
@@ -8,3 +8,4 @@
|
||||
#include "dwarf/dwarf_elf.c"
|
||||
#include "dwarf/dwarf_unwind.c"
|
||||
#include "dwarf/dwarf_dump.c"
|
||||
#include "dwarf/dwarf_help.c"
|
||||
|
||||
@@ -11,5 +11,6 @@
|
||||
#include "dwarf/dwarf_elf.h"
|
||||
#include "dwarf/dwarf_unwind.h"
|
||||
#include "dwarf/dwarf_dump.h"
|
||||
#include "dwarf/dwarf_help.h"
|
||||
|
||||
#endif // DWARF_INC_H
|
||||
|
||||
+39
-6
@@ -3383,18 +3383,18 @@ dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out)
|
||||
B32 is_parsed = 0;
|
||||
U64 cursor = format == DW_Format_32Bit ? 4 : 12;
|
||||
|
||||
U64 cie_id = 0;
|
||||
U64 cie_id = 0;
|
||||
U64 cie_id_size = str8_deserial_read_dwarf_uint(data, cursor, format, &cie_id);
|
||||
if (cie_id_size == 0) { goto exit; }
|
||||
cursor += cie_id_size;
|
||||
|
||||
U8 version = 0;
|
||||
U8 version = 0;
|
||||
U64 version_size = str8_deserial_read_struct(data, cursor, &version);
|
||||
if (version_size == 0) { goto exit; }
|
||||
cursor += version_size;
|
||||
|
||||
String8 aug_string = {0};
|
||||
U64 aug_string_size = str8_deserial_read_cstr(data, cursor, &aug_string);
|
||||
String8 aug_string = {0};
|
||||
U64 aug_string_size = str8_deserial_read_cstr(data, cursor, &aug_string);
|
||||
if (aug_string_size == 0) { goto exit; }
|
||||
cursor += aug_string_size;
|
||||
|
||||
@@ -3447,11 +3447,11 @@ exit:;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dw_parse_fde(String8 data,
|
||||
dw_parse_fde(String8 data,
|
||||
DW_Format format,
|
||||
DW_CIEFromOffsetFunc *cie_from_offset_func,
|
||||
void *cie_from_offset_ud,
|
||||
DW_FDE *fde_out)
|
||||
DW_FDE *fde_out)
|
||||
{
|
||||
B32 is_parsed = 0;
|
||||
U64 cursor = format == DW_Format_32Bit ? 4 : 12;
|
||||
@@ -3485,6 +3485,7 @@ dw_parse_fde(String8 data,
|
||||
// commit values to out
|
||||
fde_out->format = format;
|
||||
fde_out->cie_pointer = cie_pointer;
|
||||
fde_out->cie = cie;
|
||||
fde_out->pc_range = rng_1u64(pc_begin, pc_begin + pc_range);
|
||||
fde_out->insts = str8_skip(data, cursor);
|
||||
|
||||
@@ -3493,6 +3494,38 @@ exit:;
|
||||
return is_parsed;
|
||||
}
|
||||
|
||||
internal
|
||||
DW_CIE_FROM_OFFSET_FUNC(dw_parse_cfi_cie_from_offset)
|
||||
{
|
||||
return ud;
|
||||
}
|
||||
|
||||
internal B32
|
||||
dw_parse_cfi(String8 data, U64 fde_offset, Arch arch, DW_CIE *cie_out, DW_FDE *fde_out)
|
||||
{
|
||||
B32 is_parsed = 0;
|
||||
DW_DescriptorEntry fde_desc = {0};
|
||||
dw_parse_descriptor_entry_header(data, fde_offset, &fde_desc);
|
||||
if (fde_desc.type == DW_DescriptorEntryType_FDE) {
|
||||
U64 cie_pointer_off = fde_desc.format == DW_Format_32Bit ? 4 : 12;
|
||||
U64 cie_pointer = 0;
|
||||
U64 cie_pointer_size = str8_deserial_read_dwarf_uint(data, fde_offset + cie_pointer_off, fde_desc.format, &cie_pointer);
|
||||
if (cie_pointer_size) {
|
||||
DW_DescriptorEntry cie_desc = {0};
|
||||
dw_parse_descriptor_entry_header(data, cie_pointer, &cie_desc);
|
||||
if (cie_desc.type == DW_DescriptorEntryType_CIE) {
|
||||
if (dw_parse_cie(str8_substr(data, cie_desc.entry_range), cie_desc.format, arch, cie_out)) {
|
||||
if (dw_parse_fde(str8_substr(data, fde_desc.entry_range), fde_desc.format, dw_parse_cfi_cie_from_offset, cie_out, fde_out)) {
|
||||
is_parsed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return is_parsed;
|
||||
}
|
||||
|
||||
internal DW_CFA_ParseErrorCode
|
||||
dw_parse_cfa_inst(String8 data,
|
||||
U64 code_align_factor,
|
||||
|
||||
@@ -378,6 +378,7 @@ typedef struct DW_CIE
|
||||
U64 code_align_factor;
|
||||
S64 data_align_factor;
|
||||
U64 ret_addr_reg;
|
||||
U64 ext[4];
|
||||
DW_Format format;
|
||||
U8 version;
|
||||
U8 address_size;
|
||||
@@ -388,6 +389,7 @@ typedef struct DW_FDE
|
||||
{
|
||||
DW_Format format;
|
||||
U64 cie_pointer;
|
||||
DW_CIE *cie;
|
||||
Rng1U64 pc_range;
|
||||
String8 insts;
|
||||
} DW_FDE;
|
||||
@@ -529,8 +531,8 @@ internal DW_TagNode * dw_tag_node_from_info_off(DW_CompUnit *cu, U64 info_off);
|
||||
|
||||
// line info
|
||||
|
||||
internal U64 dw_read_line_file(String8 line_data, U64 line_off, DW_Input *input, DW_Version unit_version, DW_Format unit_format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, DW_LineFile *line_file_out);
|
||||
internal U64 dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out);
|
||||
internal U64 dw_read_line_file(String8 line_data, U64 line_off, DW_Input *input, DW_Version unit_version, DW_Format unit_format, DW_Ext ext, U64 address_size, DW_ListUnit *str_offsets, U64 enc_count, U64 *enc_arr, DW_LineFile *line_file_out);
|
||||
internal U64 dw_read_line_vm_header(Arena *arena, String8 line_data, U64 line_off, DW_Input *input, String8 cu_dir, String8 cu_name, U8 cu_address_size, DW_ListUnit *cu_str_offsets, DW_LineVMHeader *header_out);
|
||||
internal void dw_line_vm_reset(DW_LineVMState *state, B32 default_is_stmt);
|
||||
internal void dw_line_vm_advance(DW_LineVMState *state, U64 advance, U64 min_inst_len, U64 max_ops_for_inst);
|
||||
internal DW_LineSeqNode * dw_push_line_seq(Arena* arena, DW_LineTableParseResult *parsed_tbl);
|
||||
@@ -558,6 +560,7 @@ internal U64 dw_read_debug_frame_ptr(String8 data, DW_CIE *cie, U64 *ptr_out);
|
||||
internal U64 dw_parse_descriptor_entry_header(String8 data, U64 off, DW_DescriptorEntry *desc_out);
|
||||
internal B32 dw_parse_cie(String8 data, DW_Format format, Arch arch, DW_CIE *cie_out);
|
||||
internal B32 dw_parse_fde(String8 data, DW_Format format, DW_CIEFromOffsetFunc *cie_from_offset_func, void *cie_from_offset_ud, DW_FDE *fde_out);
|
||||
internal B32 dw_parse_cfi(String8 data, U64 fde_offset, Arch arch, DW_CIE *cie_out, DW_FDE *fde_out);
|
||||
|
||||
internal DW_CFA_ParseErrorCode dw_parse_cfa_inst(String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud, U64 *bytes_read_out, DW_CFA_Inst *inst_out);
|
||||
internal DW_CFA_InstList dw_parse_cfa_inst_list(Arena *arena, String8 data, U64 code_align_factor, S64 data_align_factor, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud);
|
||||
|
||||
+75
-27
@@ -1,10 +1,10 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal DW_CFA_Row *
|
||||
dw_make_cfa_row(Arena *arena, U64 reg_count)
|
||||
internal DW_CFI_Row *
|
||||
dw_make_cfi_row(Arena *arena, U64 reg_count)
|
||||
{
|
||||
DW_CFA_Row *row = push_array(arena, DW_CFA_Row, 1);
|
||||
DW_CFI_Row *row = push_array(arena, DW_CFI_Row, 1);
|
||||
row->regs = push_array(arena, DW_CFI_Register, reg_count);
|
||||
for EachIndex(reg_idx, reg_count) {
|
||||
row->regs[reg_idx].rule = DW_CFI_RegisterRule_SameValue;
|
||||
@@ -12,12 +12,18 @@ dw_make_cfa_row(Arena *arena, U64 reg_count)
|
||||
return row;
|
||||
}
|
||||
|
||||
internal DW_CFA_Row *
|
||||
dw_copy_cfa_row(Arena *arena, U64 reg_count, DW_CFA_Row *row)
|
||||
internal void
|
||||
dw_memcpy_cfi_row(DW_CFI_Row *dst, DW_CFI_Row *src, U64 reg_count)
|
||||
{
|
||||
DW_CFA_Row *new_row = dw_make_cfa_row(arena, reg_count);
|
||||
new_row->cfa = row->cfa;
|
||||
MemoryCopyTyped(new_row->regs, row->regs, reg_count);
|
||||
dst->cfa = src->cfa;
|
||||
MemoryCopyTyped(dst->regs, src->regs, reg_count);
|
||||
}
|
||||
|
||||
internal DW_CFI_Row *
|
||||
dw_copy_cfi_row(Arena *arena, DW_CFI_Row *row, U64 reg_count)
|
||||
{
|
||||
DW_CFI_Row *new_row = dw_make_cfi_row(arena, reg_count);
|
||||
dw_memcpy_cfi_row(new_row, row, reg_count);
|
||||
return new_row;
|
||||
}
|
||||
|
||||
@@ -35,19 +41,21 @@ dw_cfi_unwind_init(Arena *arena,
|
||||
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;
|
||||
uw->fde = fde;
|
||||
uw->reg_count = dw_reg_count_from_arch(arch);
|
||||
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_cfa_row(arena, uw->reg_count);
|
||||
uw->row = dw_make_cfi_row(arena, uw->reg_count);
|
||||
uw->curr_inst = initial_insts.first;
|
||||
dw_cfi_next_row(arena, uw);
|
||||
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_cfa_row(arena, uw->reg_count, uw->initial_row);
|
||||
uw->row = dw_copy_cfi_row(arena, uw->initial_row, uw->reg_count);
|
||||
uw->curr_inst = uw->insts.first;
|
||||
|
||||
scratch_end(scratch);
|
||||
@@ -156,12 +164,12 @@ dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw)
|
||||
|
||||
// Row State Instructions
|
||||
case DW_CFA_RememberState: {
|
||||
DW_CFA_Row *new_row = dw_copy_cfa_row(arena, uw->reg_count, uw->row);
|
||||
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_CFA_Row *free_row = uw->row;
|
||||
DW_CFI_Row *free_row = uw->row;
|
||||
SLLStackPop(uw->row);
|
||||
SLLStackPush(uw->free_rows, free_row);
|
||||
} break;
|
||||
@@ -183,17 +191,54 @@ exit:;
|
||||
return is_row_valid;
|
||||
}
|
||||
|
||||
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);
|
||||
DW_CFI_Row *row = dw_copy_cfi_row(scratch.arena, uw->row, uw->reg_count);
|
||||
U64 prev_pc = uw->pc;
|
||||
while (dw_cfi_next_row(scratch.arena, uw)) {
|
||||
if (prev_pc <= pc && pc < uw->pc) {
|
||||
is_row_found = 1;
|
||||
break;
|
||||
}
|
||||
dw_memcpy_cfi_row(row, uw->row, uw->reg_count);
|
||||
prev_pc = uw->pc;
|
||||
}
|
||||
|
||||
// handle last row
|
||||
if (!is_row_found) {
|
||||
if (prev_pc <= pc && pc < uw->pc && contains_1u64(fde->pc_range, pc)) {
|
||||
row = uw->row;
|
||||
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 DW_UnwindStatus
|
||||
dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
DW_MemRead *mem_read_func, void *mem_read_ud,
|
||||
DW_RegRead *reg_read_func, void *reg_read_ud,
|
||||
DW_RegWrite *reg_write_func, void *reg_write_ud)
|
||||
dw_cfi_apply_register_rules(Arch arch,
|
||||
DW_CIE *cie,
|
||||
DW_CFI_Row *row,
|
||||
DW_MemRead *mem_read_func, void *mem_read_ud,
|
||||
DW_RegRead *reg_read_func, void *reg_read_ud,
|
||||
DW_RegWrite *reg_write_func, void *reg_write_ud)
|
||||
{
|
||||
Temp scratch = scratch_begin(0,0);
|
||||
DW_UnwindStatus unwind_status = DW_UnwindStatus_Ok;
|
||||
|
||||
DW_CFA_Row *row = uw->row;
|
||||
|
||||
// establish CFA
|
||||
U64 cfa = 0;
|
||||
switch (row->cfa.rule) {
|
||||
@@ -201,7 +246,7 @@ dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
case DW_CFA_Rule_RegOff: {
|
||||
// TODO: report error (invalid register read)
|
||||
U64 cfa_reg_value = 0;
|
||||
U64 reg_size = dw_reg_size_from_code(uw->arch, row->cfa.reg);
|
||||
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 != DW_UnwindStatus_Ok) { goto exit; }
|
||||
@@ -212,11 +257,12 @@ dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
} break;
|
||||
}
|
||||
|
||||
U64 max_reg_size = dw_reg_max_size_from_arch(uw->arch);
|
||||
U64 max_reg_size = dw_reg_max_size_from_arch(arch);
|
||||
void *reg_buffer = push_array(scratch.arena, U8, max_reg_size);
|
||||
|
||||
for EachIndex(reg_idx, uw->reg_count) {
|
||||
DW_CFI_Register *reg = &uw->row->regs[reg_idx];
|
||||
U64 reg_count = dw_reg_count_from_arch(arch);
|
||||
for EachIndex(reg_idx, reg_count) {
|
||||
DW_CFI_Register *reg = &row->regs[reg_idx];
|
||||
switch (reg->rule) {
|
||||
case DW_CFI_RegisterRule_Undefined: {
|
||||
// TODO: ???
|
||||
@@ -226,7 +272,7 @@ dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
case DW_CFI_RegisterRule_Offset: {
|
||||
// read register value from memory
|
||||
U64 addr = cfa + reg->n;
|
||||
U64 reg_size = dw_reg_size_from_code(uw->arch, reg_idx);
|
||||
U64 reg_size = dw_reg_size_from_code(arch, reg_idx);
|
||||
unwind_status = mem_read_func(addr, reg_size, reg_buffer, mem_read_ud);
|
||||
if (unwind_status != DW_UnwindStatus_Ok) { goto exit; }
|
||||
|
||||
@@ -239,13 +285,13 @@ dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
U64 reg_value = cfa + reg->n;
|
||||
|
||||
// write register value to the thread context
|
||||
U64 reg_size = dw_reg_size_from_code(uw->arch, reg_idx);
|
||||
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 != DW_UnwindStatus_Ok) { goto exit; }
|
||||
} break;
|
||||
case DW_CFI_RegisterRule_Register: {
|
||||
// read register value from another register
|
||||
U64 reg_size = dw_reg_size_from_code(uw->arch, reg_idx);
|
||||
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 != DW_UnwindStatus_Ok) { goto exit; }
|
||||
|
||||
@@ -264,8 +310,10 @@ dw_cfi_apply_register_rules(DW_CFI_Unwind *uw,
|
||||
case DW_CFI_RegisterRule_Architectural: {
|
||||
NotImplemented;
|
||||
} break;
|
||||
default: { InvalidPath; } break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exit:;
|
||||
scratch_end(scratch);
|
||||
|
||||
+13
-11
@@ -44,25 +44,25 @@ typedef struct DW_CFI_Register
|
||||
};
|
||||
} DW_CFI_Register;
|
||||
|
||||
typedef struct DW_CFA_Row
|
||||
typedef struct DW_CFI_Row
|
||||
{
|
||||
DW_CFA cfa;
|
||||
DW_CFA cfa;
|
||||
DW_CFI_Register *regs;
|
||||
struct DW_CFA_Row *next;
|
||||
} DW_CFA_Row;
|
||||
struct DW_CFI_Row *next;
|
||||
} DW_CFI_Row;
|
||||
|
||||
typedef struct DW_CFI_Unwind
|
||||
{
|
||||
DW_CFA_InstList insts;
|
||||
DW_CIE *cie;
|
||||
DW_FDE *fde;
|
||||
DW_CFA_Row *initial_row;
|
||||
DW_CFA_Row *row;
|
||||
DW_CFI_Row *initial_row;
|
||||
DW_CFI_Row *row;
|
||||
DW_CFA_InstNode *curr_inst;
|
||||
DW_CFA_Row *free_rows;
|
||||
DW_Reg reg_count;
|
||||
DW_CFI_Row *free_rows;
|
||||
U64 pc;
|
||||
Arch arch;
|
||||
U64 reg_count;
|
||||
} DW_CFI_Unwind;
|
||||
|
||||
typedef enum {
|
||||
@@ -82,12 +82,14 @@ typedef DW_MEM_READ(DW_MemRead);
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal DW_CFA_Row * dw_make_cfa_row(Arena *arena, U64 reg_count);
|
||||
internal DW_CFA_Row * dw_copy_cfa_row(Arena *arena, U64 reg_count, DW_CFA_Row *row);
|
||||
internal DW_CFI_Row * dw_make_cfi_row(Arena *arena, U64 reg_count);
|
||||
internal DW_CFI_Row * dw_copy_cfi_row(Arena *arena, DW_CFI_Row *row, U64 reg_count);
|
||||
|
||||
internal DW_CFI_Unwind * dw_cfi_unwind_init(Arena *arena, Arch arch, DW_CIE *cie, DW_FDE *fde, DW_DecodePtr *decode_ptr_func, void *decode_ptr_ud);
|
||||
internal B32 dw_cfi_next_row(Arena *arena, DW_CFI_Unwind *uw);
|
||||
internal DW_UnwindStatus dw_cfi_apply_register_rules(DW_CFI_Unwind *uw, DW_MemRead *mem_read_func, void *mem_read_ud, DW_RegRead *reg_read_func, void *reg_read_ud, DW_RegWrite *reg_write_func, void *reg_write_ud);
|
||||
|
||||
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 DW_UnwindStatus dw_cfi_apply_register_rules(Arch arch, DW_CIE *cie, DW_CFI_Row *row, DW_MemRead *mem_read_func, void *mem_read_ud, DW_RegRead *reg_read_func, void *reg_read_ud, DW_RegWrite *reg_write_func, void *reg_write_ud);
|
||||
|
||||
#endif // DWARF_UNWIND_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user