Skip to content

Commit f6b2ccb

Browse files
moved eh_frame files to dwarf layer
1 parent 4fc8417 commit f6b2ccb

File tree

4 files changed

+776
-0
lines changed

4 files changed

+776
-0
lines changed

src/dwarf/eh_dump.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright (c) Epic Games Tools
2+
// Licensed under the MIT license (https://opensource.org/license/mit/)
3+
4+
internal String8List
5+
eh_dump_list_from_data(Arena *arena, Arch arch, U64 eh_frame_hdr_vaddr, U64 eh_frame_vaddr, String8 eh_frame_hdr, String8 eh_frame, EH_DumpSubsetFlags subset_flags)
6+
{
7+
Temp scratch = scratch_begin(&arena, 1);
8+
String8List strings = {0};
9+
#define dumpf(...) str8_list_pushf(arena, &strings, __VA_ARGS__)
10+
11+
EH_PtrCtx ptr_ctx = { .data_vaddr = eh_frame_hdr_vaddr };
12+
EH_FrameHdr hdr = eh_parse_frame_hdr(eh_frame_hdr, byte_size_from_arch(arch), &ptr_ctx);
13+
DW_Ext ext = DW_Ext_All;
14+
15+
if (subset_flags & EH_DumpSubsetFlag_EhFrameHdr) {
16+
dumpf("eh_frame_hdr:\n");
17+
dumpf("{\n");
18+
dumpf(" version: %u\n", hdr.version);
19+
dumpf(" eh_frame_ptr_enc: %S\n", eh_string_from_ptr_enc(scratch.arena, hdr.eh_frame_ptr_enc));
20+
dumpf(" table_enc: %S\n", eh_string_from_ptr_enc(scratch.arena, hdr.table_enc));
21+
dumpf(" fde_count: %llu\n", hdr.fde_count);
22+
if (hdr.eh_frame_ptr_enc != EH_PtrEnc_Omit) {
23+
dumpf(" eh_frame_ptr: 0x%I64x\n", hdr.eh_frame_ptr);
24+
}
25+
26+
dumpf(" Entries:\n");
27+
dumpf(" {\n");
28+
for (U64 cursor = 0; cursor < hdr.table.size; ) {
29+
U64 entry_off = cursor;
30+
31+
U64 pc = 0;
32+
U64 pc_size = eh_parse_ptr(hdr.table, cursor, cursor, &ptr_ctx, hdr.table_enc, &pc);
33+
if (pc_size == 0) { break; }
34+
cursor += pc_size;
35+
36+
U64 fde_addr = 0;
37+
U64 fde_addr_size = eh_parse_ptr(hdr.table, cursor, cursor, &ptr_ctx, hdr.table_enc, &fde_addr);
38+
if (fde_addr_size == 0) { break; }
39+
cursor += fde_addr_size;
40+
41+
U64 fde_offset = fde_addr - eh_frame_vaddr;
42+
dumpf(" { off=0x%04I64x, pc=0x%I64x, fde=0x%I64x }\n", entry_off, pc, fde_offset);
43+
}
44+
dumpf(" }\n");
45+
46+
dumpf("}\n");
47+
48+
}
49+
50+
if (subset_flags & EH_DumpSubsetFlag_EhFrame) {
51+
dumpf(".eh_frame:\n");
52+
dumpf("{\n");
53+
for (U64 cursor = 0; cursor < eh_frame.size; ) {
54+
DW_DescriptorEntry desc = {0};
55+
U64 desc_size = eh_parse_descriptor_entry_header(eh_frame, cursor, &desc);
56+
if (desc_size == 0) { break; }
57+
58+
switch (desc.type) {
59+
case DW_DescriptorEntryType_Null: break;
60+
case DW_DescriptorEntryType_CIE: {
61+
String8 cie_data = str8_substr(eh_frame, desc.entry_range);
62+
DW_CIE cie = {0};
63+
if (eh_parse_cie(cie_data, desc.format, arch, eh_frame_vaddr + cursor, &ptr_ctx, &cie)) {
64+
String8List init_insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, DW_Version_5, ext, cie.format, 0, &cie, eh_decode_ptr, &ptr_ctx, cie.insts);
65+
dumpf(" CIE: // entry range: %r\n", desc.entry_range);
66+
dumpf(" {\n");
67+
dumpf(" Format: %S\n", dw_string_from_format(desc.format));
68+
dumpf(" Version: %u\n", cie.version);
69+
dumpf(" Aug string: \"%S\"\n", cie.aug_string);
70+
dumpf(" Code align: %I64u\n", cie.code_align_factor);
71+
dumpf(" Data align: %I64d\n", cie.data_align_factor);
72+
dumpf(" Return addr reg: %u\n", cie.ret_addr_reg);
73+
if (cie.version > DW_Version_3) {
74+
dumpf(" Address size: %u\n", cie.address_size);
75+
dumpf(" Segment selector size: %u\n", cie.segment_selector_size);
76+
}
77+
dumpf(" Initial Insturction:\n");
78+
dumpf(" {\n");
79+
for EachNode(n, String8Node, init_insts_str_list.first) { dumpf(" %S\n", n->string); }
80+
dumpf(" }\n");
81+
dumpf(" }\n");
82+
} else {
83+
dumpf("ERROR: unable to parse CIE @ %I64x\n", desc.entry_range.min);
84+
}
85+
} break;
86+
case DW_DescriptorEntryType_FDE: {
87+
U64 cie_offset = desc.cie_pointer_off - desc.cie_pointer;
88+
89+
DW_CIE cie = {0};
90+
{
91+
DW_DescriptorEntry cie_desc = {0};
92+
eh_parse_descriptor_entry_header(eh_frame, cie_offset, &cie_desc);
93+
if (cie_desc.type == DW_DescriptorEntryType_CIE) {
94+
String8 cie_data = str8_substr(eh_frame, cie_desc.entry_range);
95+
eh_parse_cie(cie_data, cie_desc.format, arch, eh_frame_vaddr + cie_offset, &ptr_ctx, &cie);
96+
}
97+
}
98+
99+
String8 fde_raw = str8_substr(eh_frame, desc.entry_range);
100+
DW_FDE fde = {0};
101+
if (eh_parse_fde(fde_raw, desc.format, eh_frame_vaddr + cursor, &cie, &ptr_ctx, &fde)) {
102+
String8List insts_str_list = dw_string_list_from_cfi_program(scratch.arena, 0, arch, hdr.version, ext, fde.format, 0, &cie, eh_decode_ptr, &ptr_ctx, fde.insts);
103+
104+
dumpf(" FDE: // entry range: %r\n", desc.entry_range);
105+
dumpf(" {\n");
106+
{
107+
dumpf(" Format: %S\n", dw_string_from_format(fde.format));
108+
dumpf(" CIE: 0x%I64x\n", cie_offset);
109+
dumpf(" PC range: %r\n", fde.pc_range);
110+
dumpf(" Instructions:\n");
111+
dumpf(" {\n");
112+
for EachNode(n, String8Node, insts_str_list.first) { dumpf(" %S\n", n->string); }
113+
dumpf(" }\n");
114+
115+
dumpf(" Unwind:\n");
116+
dumpf(" {\n");
117+
DW_CFI_Unwind *cfi_unwind = dw_cfi_unwind_init(scratch.arena, arch, &cie, &fde, eh_decode_ptr, &ptr_ctx);
118+
do {
119+
String8 cfa_str = dw_string_from_cfa(scratch.arena, arch, cie.address_size, hdr.version, ext, fde.format, cfi_unwind->row->cfa);
120+
String8 cfi_row_str = dw_string_from_cfi_row(scratch.arena, arch, cie.address_size, hdr.version, ext, fde.format, cfi_unwind->row);
121+
dumpf(" { PC: 0x%I64x, CFA: %-7S, Rules: { %S }\n", cfi_unwind->pc, cfa_str, cfi_row_str);
122+
} while (dw_cfi_next_row(scratch.arena, cfi_unwind));
123+
dumpf(" }\n");
124+
}
125+
} else {
126+
dumpf("ERROR: unable to parse FDE @ %I64x\n", desc.entry_range.min);
127+
}
128+
dumpf(" }\n");
129+
} break;
130+
}
131+
132+
cursor += desc_size;
133+
}
134+
dumpf("}\n");
135+
}
136+
137+
#undef dumpf
138+
scratch_end(scratch);
139+
return strings;
140+
}
141+

src/dwarf/eh_dump.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Epic Games Tools
2+
// Licensed under the MIT license (https://opensource.org/license/mit/)
3+
4+
#ifndef EH_FRAME_DUMP_H
5+
#define EH_FRAME_DUMP_H
6+
7+
////////////////////////////////
8+
//~ Dump Subset Types
9+
10+
#define EH_DumpSubset_XList \
11+
X(EhFrameHdr, eh_frame_hdr, ".eh_frame_hdr") \
12+
X(EhFrame, eh_frame, ".eh_frame")
13+
14+
typedef enum EH_DumpSubset {
15+
#define X(name, name_lower, title) EH_DumpSubset_##name,
16+
EH_DumpSubset_XList
17+
#undef X
18+
} EH_DumpSubset;
19+
20+
typedef U32 EH_DumpSubsetFlags;
21+
enum {
22+
#define X(name, name_lower, title) EH_DumpSubsetFlag_##name = (1<<EH_DumpSubset_##name),
23+
EH_DumpSubset_XList
24+
#undef X
25+
EH_DumpSubsetFlag_All = 0xffffffff,
26+
};
27+
28+
read_only global String8 eh_name_lowercase_from_dump_subset_table[] =
29+
{
30+
#define X(name, name_lower, title) str8_lit_comp(#name_lower),
31+
EH_DumpSubset_XList
32+
#undef X
33+
};
34+
35+
read_only global String8 eh_name_title_from_dump_subset_table[] =
36+
{
37+
#define X(name, name_lower, title) str8_lit_comp(title),
38+
EH_DumpSubset_XList
39+
#undef X
40+
};
41+
42+
////////////////////////////////
43+
//~ Dump Entry Point
44+
45+
internal String8List eh_dump_list_from_data(Arena *arena, Arch arch, U64 eh_frame_hdr_vaddr, U64 eh_frame_vaddr, String8 eh_frame_hdr, String8 eh_frame, EH_DumpSubsetFlags subset_flags);
46+
47+
#endif // EH_FRAME_DUMP_H
48+

0 commit comments

Comments
 (0)