NetBurner 3.5.6
PDF Version
exidx_unwind.h
1#ifndef __EXIDX_UNWIND_H
2#define __EXIDX_UNWIND_H
3/*NB_REVISION*/
4
5/*NB_COPYRIGHT*/
6
7#include <predef.h>
8#include <stdint.h>
9#include <stddef.h>
10
11#define COMP_ENTRY_IDX_MASK (0xF << 24)
12#define ARM_EXIDX_CMD_FINISH 0xB0
13#define ARM_EXIDX_CMD_REFUSED 0x80
14#define ARM_EXIDX_CMD_REG_POP 0xB1
15#define ARM_EXIDX_CMD_DATA_POP 0xB2
16#define ARM_EXIDX_CMD_VFP_POP 0xB3
17#define ARM_EXIDX_CMD_WCGR_POP 0xC7
18#define ARM_EXIDX_PRS_CANT_UNWIND 0x00000001
19
20typedef enum
21{
22 ARM_RET_HND_FP = 0xFFFFFFE1,
23 ARM_RET_MSP_FP = 0xFFFFFFE9,
24 ARM_RET_PSP_FP = 0xFFFFFFED,
25 ARM_RET_HND_NOFP = 0xFFFFFFF1,
26 ARM_RET_MSP_NOFP = 0xFFFFFFF9,
27 ARM_RET_PSP_NOFP = 0xFFFFFFFD,
28} ExceptRet_LR_t;
29
30struct insn_t
31{
32 const uint32_t *prs32; // pointer to table entry holding the instructions
33 int rem; // Remaining instruction count to unwind frame
34 int idx; // index of next instruction in entry word
35
36 int getNext();
37 int peek();
38 uint32_t get_uleb128();
39 void init(const uint32_t *tab_entry);
40};
41
42/*
43 * To convert the index table entry into an exception address, we must first
44 * sign extend the offset value (since only 31 bits are stored).
45 * We then add this offset to the address of the entry to get the handling
46 * table entry. I think...
47 */
48inline uint32_t prel31Addr(const uint32_t *prel31)
49{
50 int32_t s_ext_offset = (*((int32_t *)prel31) << 1) >> 1;
51 return (((uint32_t)prel31) + s_ext_offset) & 0x7FffFFff;
52}
53
54struct exidx_t
55{
56 uint32_t offset;
57 uint32_t xtab_insn;
58
59 inline uint32_t asAddr() const { return prel31Addr(&offset); }
60 const int getInsn(insn_t *insn) const;
61};
62
63extern const exidx_t __exidx_start[];
64extern const exidx_t __exidx_end[];
65
66// Virtual Register set for stack unwinding
67struct vrs_t
68{
69 union
70 {
71 uint32_t r[16];
72 struct
73 {
74 uint32_t _r[12];
75 uint32_t ip;
76 uint32_t *sp;
77 uint32_t lr;
78 uint32_t pc;
79 };
80 };
81 uint32_t xpsr;
82 uint64_t fpr[16];
83 uint32_t fpscr;
84 bool bVPSP; // is our virtual stack pointer currently the Process Stack Pointer
85};
86
87typedef void *unwind_trace_dat_t;
88typedef int (*unwind_trace_fn)(const vrs_t &vrs, unwind_trace_dat_t trace_dat);
89
90struct unwind_ctx
91{
92 vrs_t vrs;
93 insn_t insn;
94 uint32_t maxRecurse;
95 uint32_t flags;
96
97 int step();
98 int unwind_frame();
99 inline void init() volatile
100 {
101 // Do not modify without verifying dissassembly...
102 uint32_t offset;
103 offset = offsetof(unwind_ctx, vrs) + offsetof(vrs_t, r) + 4 * sizeof(vrs.r[0]);
104 asm volatile(
105 "add %%r1, %0, %1\n\t"
106 "str %%r4, [%%r1], #4\n\t"
107 "str %%r5, [%%r1], #4\n\t"
108 "str %%r6, [%%r1], #4\n\t"
109 "str %%r7, [%%r1], #4\n\t"
110 "str %%r8, [%%r1], #4\n\t"
111 "str %%r9, [%%r1], #4\n\t"
112 "str %%r10, [%%r1], #4\n\t"
113 "str %%r11, [%%r1], #4\n\t"
114 :
115 : "r"(this), "r"(offset)
116 : "r1", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "memory");
117 }
118 inline void initFpr() volatile
119 {
120#if ((__SOFTFP__ != 1) || (defined __ARM_FP))
121 // Do not modify without verifying dissassembly...
122 uint32_t offset;
123 offset = offsetof(unwind_ctx, vrs) + offsetof(vrs_t, fpr);
124 asm volatile(
125 "add %%r1, %0, %1\n\t"
126 "vstm.64 %%r1!, {%%d0-%%d15}\n\t"
127 "vmrs %%r2, FPSCR\n\t"
128 "str %%r2, [%%r1]\n\t"
129 :
130 : "r"(this), "r"(offset)
131 : "r1", "r2", "memory");
132#endif
133 }
134 inline void initForRunning() volatile
135 {
136 // Do not modify without verifying dissassembly...
137 uint32_t offset;
138 offset = offsetof(unwind_ctx, vrs) + offsetof(vrs_t, r) + 2 * sizeof(vrs.r[0]);
139 asm volatile(
140 "add %%r1, %0, %1\n\t"
141 "stm r1!, {r2-r12}\n\t"
142 "str sp, [r1], #4\n\t"
143 "str lr, [r1], #4\n\t"
144 :
145 : "r"(this), "r"(offset)
146 : "r1", "memory");
147 }
148 void init(volatile cpu_tcb *ptcb);
149 void init(uint32_t sp, uint32_t lr, uint32_t pc);
150 void unwind_eframe();
151 int unwind_stack(unwind_trace_fn trace_cb, unwind_trace_dat_t trace_dat);
152};
153
154// Exception Frame for no FPU or FPU disabled.
155typedef struct
156{
157 union
158 {
159 struct
160 {
161 uint32_t r0;
162 uint32_t r1;
163 uint32_t r2;
164 uint32_t r3;
165 uint32_t r12;
166 uint32_t lr;
167 uint32_t pc;
168 uint32_t xprs;
169 };
170 uint32_t r[16];
171 };
172} eframe_t;
173
174// Exception Frame with FPU
175typedef struct
176{
177 union
178 {
179 struct
180 {
181 uint32_t r0;
182 uint32_t r1;
183 uint32_t r2;
184 uint32_t r3;
185 uint32_t r12;
186 uint32_t lr;
187 uint32_t pc;
188 uint32_t xprs;
189 };
190 uint32_t r[16];
191 };
192 union
193 {
194 uint32_t fp[32];
195 uint64_t dfp[16];
196 };
197 uint32_t fpscr;
198} eframe_fp_t;
199
200// Minimal state context for stack unwind
201typedef struct
202{
203 uint32_t pc;
204 uint32_t lr;
205 uint32_t sp;
206} uwctx;
207
208// extab exception table entry
209typedef struct
210{
211 uint32_t prs_fn_offset;
212 uint32_t prs_data;
213} extab_entry_gen;
214
215struct extab_insn_tbl
216{
217 inline uint8_t operator[](int i);
218};
219
220struct extab_insn_ctx
221{
222};
223
224struct extab_entry_comp
225{
226 uint32_t idx_prs;
227 uint32_t prs_data[];
228 uint8_t operator[](int i);
229};
230
231exidx_t *find_insn(uint32_t *start, uint32_t *end, uint32_t pc);
232
233#endif /* ----- #ifndef __EXIDX_UNWIND_H ----- */
void init()
System initialization. Ideally called at the beginning of all applications, since the easiest Recover...