1472758f3SLionel Sambuc //===--------------------------- libuwind.cpp -----------------------------===//
2472758f3SLionel Sambuc //
3472758f3SLionel Sambuc // The LLVM Compiler Infrastructure
4472758f3SLionel Sambuc //
5472758f3SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
6472758f3SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
7472758f3SLionel Sambuc //
8472758f3SLionel Sambuc //
9472758f3SLionel Sambuc // Implements C++ ABI Exception Handling Level 1 as documented at:
10472758f3SLionel Sambuc // http://mentorembedded.github.io/cxx-abi/abi-eh.html
11472758f3SLionel Sambuc //
12472758f3SLionel Sambuc //===----------------------------------------------------------------------===//
13472758f3SLionel Sambuc
14*0a6a1f1dSLionel Sambuc #define _UNWIND_GCC_EXTENSIONS
15*0a6a1f1dSLionel Sambuc
16472758f3SLionel Sambuc #include <unwind.h>
17472758f3SLionel Sambuc
18472758f3SLionel Sambuc #include "UnwindCursor.hpp"
19472758f3SLionel Sambuc
20472758f3SLionel Sambuc using namespace _Unwind;
21472758f3SLionel Sambuc
22b029fb59SBen Gras typedef CFI_Parser<LocalAddressSpace, NativeUnwindRegisters> MyCFIParser;
23472758f3SLionel Sambuc
24472758f3SLionel Sambuc // Internal object representing the address space of this process.
25472758f3SLionel Sambuc static LocalAddressSpace sThisAddressSpace(MyCFIParser::findPCRange);
26472758f3SLionel Sambuc
27b029fb59SBen Gras typedef UnwindCursor<LocalAddressSpace, NativeUnwindRegisters> ThisUnwindCursor;
28472758f3SLionel Sambuc
unwind_phase1(ThisUnwindCursor & cursor,struct _Unwind_Exception * exc)29472758f3SLionel Sambuc static _Unwind_Reason_Code unwind_phase1(ThisUnwindCursor &cursor,
30472758f3SLionel Sambuc struct _Unwind_Exception *exc) {
31472758f3SLionel Sambuc cursor.setInfoBasedOnIPRegister();
32472758f3SLionel Sambuc
33472758f3SLionel Sambuc // Walk frames looking for a place to stop.
34472758f3SLionel Sambuc for (;;) {
35472758f3SLionel Sambuc // Get next frame.
36472758f3SLionel Sambuc // First frame is _Unwind_RaiseException and skipped.
37472758f3SLionel Sambuc switch (cursor.step()) {
38472758f3SLionel Sambuc case UNW_STEP_END:
39472758f3SLionel Sambuc return _URC_END_OF_STACK;
40472758f3SLionel Sambuc case UNW_STEP_FAILED:
41472758f3SLionel Sambuc return _URC_FATAL_PHASE1_ERROR;
42472758f3SLionel Sambuc case UNW_STEP_SUCCESS:
43472758f3SLionel Sambuc break;
44472758f3SLionel Sambuc }
45472758f3SLionel Sambuc
46472758f3SLionel Sambuc // Check if there is a personality routine for this frame.
47472758f3SLionel Sambuc unw_proc_info_t frameInfo;
48472758f3SLionel Sambuc cursor.getInfo(&frameInfo);
49472758f3SLionel Sambuc if (frameInfo.end_ip == 0)
50472758f3SLionel Sambuc return _URC_FATAL_PHASE1_ERROR;
51472758f3SLionel Sambuc
52472758f3SLionel Sambuc if (frameInfo.handler == 0)
53472758f3SLionel Sambuc continue; // No personality routine, so try next frame.
54472758f3SLionel Sambuc
55472758f3SLionel Sambuc __personality_routine p = (__personality_routine)(frameInfo.handler);
56472758f3SLionel Sambuc _Unwind_Reason_Code result = (*p)(1, _UA_SEARCH_PHASE, exc->exception_class,
57472758f3SLionel Sambuc exc, (struct _Unwind_Context *)(&cursor));
58472758f3SLionel Sambuc
59472758f3SLionel Sambuc switch (result) {
60472758f3SLionel Sambuc case _URC_HANDLER_FOUND:
61472758f3SLionel Sambuc // This is either a catch clause or a local variable
62472758f3SLionel Sambuc // with destructor.
63472758f3SLionel Sambuc // Stop search and remember the frame for phase 2.
64472758f3SLionel Sambuc exc->private_2 = cursor.getSP();
65472758f3SLionel Sambuc return _URC_NO_REASON;
66472758f3SLionel Sambuc
67472758f3SLionel Sambuc case _URC_CONTINUE_UNWIND:
68472758f3SLionel Sambuc // Continue unwinding
69472758f3SLionel Sambuc break;
70472758f3SLionel Sambuc
71472758f3SLionel Sambuc default:
72472758f3SLionel Sambuc // Bad personality routine.
73472758f3SLionel Sambuc return _URC_FATAL_PHASE1_ERROR;
74472758f3SLionel Sambuc }
75472758f3SLionel Sambuc }
76472758f3SLionel Sambuc }
77472758f3SLionel Sambuc
unwind_phase2(ThisUnwindCursor & cursor,struct _Unwind_Exception * exc)78472758f3SLionel Sambuc static _Unwind_Reason_Code unwind_phase2(ThisUnwindCursor &cursor,
79472758f3SLionel Sambuc struct _Unwind_Exception *exc) {
80472758f3SLionel Sambuc cursor.setInfoBasedOnIPRegister();
81472758f3SLionel Sambuc
82472758f3SLionel Sambuc // Walk frames until the frame selected in phase 1 is reached.
83472758f3SLionel Sambuc for (;;) {
84472758f3SLionel Sambuc // Get next frame.
85472758f3SLionel Sambuc // First frame is _Unwind_RaiseException and skipped.
86472758f3SLionel Sambuc switch (cursor.step()) {
87472758f3SLionel Sambuc case UNW_STEP_END:
88472758f3SLionel Sambuc return _URC_END_OF_STACK;
89472758f3SLionel Sambuc case UNW_STEP_FAILED:
90472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
91472758f3SLionel Sambuc case UNW_STEP_SUCCESS:
92472758f3SLionel Sambuc break;
93472758f3SLionel Sambuc }
94472758f3SLionel Sambuc
95472758f3SLionel Sambuc unw_proc_info_t frameInfo;
96472758f3SLionel Sambuc cursor.getInfo(&frameInfo);
97472758f3SLionel Sambuc if (frameInfo.end_ip == 0)
98472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
99472758f3SLionel Sambuc
100472758f3SLionel Sambuc if (frameInfo.handler == 0)
101472758f3SLionel Sambuc continue; // No personality routine, continue.
102472758f3SLionel Sambuc
103472758f3SLionel Sambuc uintptr_t sp = cursor.getSP();
104472758f3SLionel Sambuc
105472758f3SLionel Sambuc _Unwind_Action action = _UA_CLEANUP_PHASE;
106472758f3SLionel Sambuc // If this frame was selected in phase 1,
107472758f3SLionel Sambuc // inform the personality routine.
108472758f3SLionel Sambuc if (sp == exc->private_2)
109472758f3SLionel Sambuc action = (_Unwind_Action)(action | _UA_HANDLER_FRAME);
110472758f3SLionel Sambuc __personality_routine p = (__personality_routine)(frameInfo.handler);
111472758f3SLionel Sambuc _Unwind_Reason_Code result = (*p)(1, action, exc->exception_class, exc,
112472758f3SLionel Sambuc (struct _Unwind_Context *)(&cursor));
113472758f3SLionel Sambuc switch (result) {
114472758f3SLionel Sambuc case _URC_CONTINUE_UNWIND:
115472758f3SLionel Sambuc // Continue unwinding unless the selected frame passed.
116472758f3SLionel Sambuc if (sp == exc->private_2)
117472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
118472758f3SLionel Sambuc break;
119472758f3SLionel Sambuc case _URC_INSTALL_CONTEXT:
120472758f3SLionel Sambuc // Transfer control to landing pad.
121472758f3SLionel Sambuc cursor.jumpto();
122472758f3SLionel Sambuc default:
123472758f3SLionel Sambuc // Bad personality routine.
124472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
125472758f3SLionel Sambuc }
126472758f3SLionel Sambuc }
127472758f3SLionel Sambuc }
128472758f3SLionel Sambuc
unwind_phase2_forced(ThisUnwindCursor & cursor,struct _Unwind_Exception * exc,_Unwind_Stop_Fn stop,void * stop_arg)129472758f3SLionel Sambuc static _Unwind_Reason_Code unwind_phase2_forced(ThisUnwindCursor &cursor,
130472758f3SLionel Sambuc struct _Unwind_Exception *exc,
131472758f3SLionel Sambuc _Unwind_Stop_Fn stop,
132472758f3SLionel Sambuc void *stop_arg) {
133472758f3SLionel Sambuc _Unwind_Action action;
134472758f3SLionel Sambuc cursor.setInfoBasedOnIPRegister();
135472758f3SLionel Sambuc
136472758f3SLionel Sambuc // Walk frames until the frame selected in phase 1 is reached.
137472758f3SLionel Sambuc for (;;) {
138472758f3SLionel Sambuc // Get next frame.
139472758f3SLionel Sambuc // First frame is _Unwind_RaiseException and skipped.
140472758f3SLionel Sambuc switch (cursor.step()) {
141472758f3SLionel Sambuc case UNW_STEP_END:
142472758f3SLionel Sambuc case UNW_STEP_FAILED:
143472758f3SLionel Sambuc // End of stack or error condition.
144472758f3SLionel Sambuc // Call the stop function one last time.
145472758f3SLionel Sambuc action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE |
146472758f3SLionel Sambuc _UA_END_OF_STACK);
147472758f3SLionel Sambuc (*stop)(1, action, exc->exception_class, exc,
148472758f3SLionel Sambuc (struct _Unwind_Context *)(&cursor), stop_arg);
149472758f3SLionel Sambuc
150472758f3SLionel Sambuc // Didn't stop at the expected frame, so return error.
151472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
152472758f3SLionel Sambuc
153472758f3SLionel Sambuc case UNW_STEP_SUCCESS:
154472758f3SLionel Sambuc break;
155472758f3SLionel Sambuc }
156472758f3SLionel Sambuc
157472758f3SLionel Sambuc unw_proc_info_t frameInfo;
158472758f3SLionel Sambuc cursor.getInfo(&frameInfo);
159472758f3SLionel Sambuc if (frameInfo.end_ip == 0)
160472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
161472758f3SLionel Sambuc
162472758f3SLionel Sambuc // Call stop function for each frame
163472758f3SLionel Sambuc action = (_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
164472758f3SLionel Sambuc _Unwind_Reason_Code result =
165472758f3SLionel Sambuc (*stop)(1, action, exc->exception_class, exc,
166472758f3SLionel Sambuc (struct _Unwind_Context *)(&cursor), stop_arg);
167472758f3SLionel Sambuc if (result != _URC_NO_REASON)
168472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
169472758f3SLionel Sambuc
170472758f3SLionel Sambuc if (frameInfo.handler == 0)
171472758f3SLionel Sambuc continue; // No personality routine, continue.
172472758f3SLionel Sambuc
173472758f3SLionel Sambuc __personality_routine p = (__personality_routine)(frameInfo.handler);
174472758f3SLionel Sambuc result = (*p)(1, action, exc->exception_class, exc,
175472758f3SLionel Sambuc (struct _Unwind_Context *)(&cursor));
176472758f3SLionel Sambuc
177472758f3SLionel Sambuc switch (result) {
178472758f3SLionel Sambuc case _URC_CONTINUE_UNWIND:
179472758f3SLionel Sambuc // Destructors called, continue.
180472758f3SLionel Sambuc break;
181472758f3SLionel Sambuc case _URC_INSTALL_CONTEXT:
182472758f3SLionel Sambuc // Transfer control to landing pad.
183472758f3SLionel Sambuc cursor.jumpto();
184472758f3SLionel Sambuc default:
185472758f3SLionel Sambuc // Bad personality routine.
186472758f3SLionel Sambuc return _URC_FATAL_PHASE2_ERROR;
187472758f3SLionel Sambuc }
188472758f3SLionel Sambuc }
189472758f3SLionel Sambuc }
190472758f3SLionel Sambuc
_Unwind_RaiseException(struct _Unwind_Exception * exc)191472758f3SLionel Sambuc _Unwind_Reason_Code _Unwind_RaiseException(struct _Unwind_Exception *exc) {
192b029fb59SBen Gras NativeUnwindRegisters registers;
193472758f3SLionel Sambuc ThisUnwindCursor cursor1(registers, sThisAddressSpace);
194472758f3SLionel Sambuc ThisUnwindCursor cursor2(registers, sThisAddressSpace);
195472758f3SLionel Sambuc
196472758f3SLionel Sambuc // Mark this as a non-forced unwind for _Unwind_Resume().
197472758f3SLionel Sambuc exc->private_1 = 0;
198472758f3SLionel Sambuc exc->private_2 = 0;
199472758f3SLionel Sambuc
200472758f3SLionel Sambuc // Phase 1: searching.
201472758f3SLionel Sambuc _Unwind_Reason_Code phase1 = unwind_phase1(cursor1, exc);
202472758f3SLionel Sambuc if (phase1 != _URC_NO_REASON)
203472758f3SLionel Sambuc return phase1;
204472758f3SLionel Sambuc
205472758f3SLionel Sambuc // Phase 2: cleaning up.
206472758f3SLionel Sambuc return unwind_phase2(cursor2, exc);
207472758f3SLionel Sambuc }
208472758f3SLionel Sambuc
_Unwind_ForcedUnwind(struct _Unwind_Exception * exc,_Unwind_Stop_Fn stop,void * stop_arg)209472758f3SLionel Sambuc _Unwind_Reason_Code _Unwind_ForcedUnwind(struct _Unwind_Exception *exc,
210472758f3SLionel Sambuc _Unwind_Stop_Fn stop, void *stop_arg) {
211b029fb59SBen Gras NativeUnwindRegisters registers;
212472758f3SLionel Sambuc ThisUnwindCursor cursor(registers, sThisAddressSpace);
213472758f3SLionel Sambuc
214472758f3SLionel Sambuc // Mark this as forced unwind for _Unwind_Resume().
215472758f3SLionel Sambuc exc->private_1 = (uintptr_t)stop;
216472758f3SLionel Sambuc exc->private_2 = (uintptr_t)stop_arg;
217472758f3SLionel Sambuc
218472758f3SLionel Sambuc return unwind_phase2_forced(cursor, exc, stop, stop_arg);
219472758f3SLionel Sambuc }
220472758f3SLionel Sambuc
_Unwind_Resume(struct _Unwind_Exception * exc)221472758f3SLionel Sambuc void _Unwind_Resume(struct _Unwind_Exception *exc) {
222b029fb59SBen Gras NativeUnwindRegisters registers;
223472758f3SLionel Sambuc ThisUnwindCursor cursor(registers, sThisAddressSpace);
224472758f3SLionel Sambuc
225472758f3SLionel Sambuc if (exc->private_1 != 0)
226472758f3SLionel Sambuc unwind_phase2_forced(cursor, exc, (_Unwind_Stop_Fn)exc->private_1,
227472758f3SLionel Sambuc (void *)exc->private_2);
228472758f3SLionel Sambuc else
229472758f3SLionel Sambuc unwind_phase2(cursor, exc);
230472758f3SLionel Sambuc abort();
231472758f3SLionel Sambuc }
232472758f3SLionel Sambuc
_Unwind_Resume_or_Rethrow(struct _Unwind_Exception * exc)233472758f3SLionel Sambuc _Unwind_Reason_Code _Unwind_Resume_or_Rethrow(struct _Unwind_Exception *exc) {
234472758f3SLionel Sambuc // This is a re-throw, if this is a non-forced unwind
235472758f3SLionel Sambuc // and the stopping place was found.
236472758f3SLionel Sambuc // In that case, call _Unwind_RaiseException() as if
237472758f3SLionel Sambuc // it was a new exception.
238472758f3SLionel Sambuc
239472758f3SLionel Sambuc if (exc->private_1 != 0)
240472758f3SLionel Sambuc _Unwind_Resume(exc);
241472758f3SLionel Sambuc
242472758f3SLionel Sambuc // This can return if there is no catch clause.
243472758f3SLionel Sambuc // In that case, __cxa_rethrow is expected to call std::terminate().
244472758f3SLionel Sambuc return _Unwind_RaiseException(exc);
245472758f3SLionel Sambuc }
246472758f3SLionel Sambuc
_Unwind_DeleteException(struct _Unwind_Exception * exc)247472758f3SLionel Sambuc void _Unwind_DeleteException(struct _Unwind_Exception *exc) {
248472758f3SLionel Sambuc if (exc->exception_cleanup != NULL)
249472758f3SLionel Sambuc (*exc->exception_cleanup)(_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
250472758f3SLionel Sambuc }
251472758f3SLionel Sambuc
_Unwind_GetGR(struct _Unwind_Context * context,int index)252472758f3SLionel Sambuc uintptr_t _Unwind_GetGR(struct _Unwind_Context *context, int index) {
253472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
254472758f3SLionel Sambuc return cursor->getReg(index);
255472758f3SLionel Sambuc }
256472758f3SLionel Sambuc
_Unwind_SetGR(struct _Unwind_Context * context,int index,uintptr_t new_value)257472758f3SLionel Sambuc void _Unwind_SetGR(struct _Unwind_Context *context, int index,
258472758f3SLionel Sambuc uintptr_t new_value) {
259472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
260472758f3SLionel Sambuc cursor->setReg(index, new_value);
261472758f3SLionel Sambuc }
262472758f3SLionel Sambuc
_Unwind_GetIP(struct _Unwind_Context * context)263472758f3SLionel Sambuc uintptr_t _Unwind_GetIP(struct _Unwind_Context *context) {
264472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
265472758f3SLionel Sambuc return cursor->getIP();
266472758f3SLionel Sambuc }
267472758f3SLionel Sambuc
_Unwind_GetIPInfo(struct _Unwind_Context * context,int * isSignalFrame)268b029fb59SBen Gras uintptr_t _Unwind_GetIPInfo(struct _Unwind_Context *context, int *isSignalFrame) {
269b029fb59SBen Gras ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
270b029fb59SBen Gras *isSignalFrame = cursor->isSignalFrame() ? 1 : 0;
271b029fb59SBen Gras return cursor->getIP();
272b029fb59SBen Gras }
273b029fb59SBen Gras
_Unwind_SetIP(struct _Unwind_Context * context,uintptr_t new_value)274472758f3SLionel Sambuc void _Unwind_SetIP(struct _Unwind_Context *context, uintptr_t new_value) {
275472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
276472758f3SLionel Sambuc cursor->setIP(new_value);
277472758f3SLionel Sambuc unw_proc_info_t info;
278472758f3SLionel Sambuc cursor->getInfo(&info);
279472758f3SLionel Sambuc cursor->setInfoBasedOnIPRegister(false);
280472758f3SLionel Sambuc }
281472758f3SLionel Sambuc
_Unwind_GetRegionStart(struct _Unwind_Context * context)282472758f3SLionel Sambuc uintptr_t _Unwind_GetRegionStart(struct _Unwind_Context *context) {
283472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
284472758f3SLionel Sambuc unw_proc_info_t frameInfo;
285472758f3SLionel Sambuc cursor->getInfo(&frameInfo);
286472758f3SLionel Sambuc return frameInfo.end_ip ? frameInfo.start_ip : 0;
287472758f3SLionel Sambuc }
288472758f3SLionel Sambuc
_Unwind_GetLanguageSpecificData(struct _Unwind_Context * context)289472758f3SLionel Sambuc uintptr_t _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context) {
290472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
291472758f3SLionel Sambuc unw_proc_info_t frameInfo;
292472758f3SLionel Sambuc cursor->getInfo(&frameInfo);
293472758f3SLionel Sambuc return frameInfo.end_ip ? frameInfo.lsda : 0;
294472758f3SLionel Sambuc }
295472758f3SLionel Sambuc
_Unwind_Backtrace(_Unwind_Trace_Fn callback,void * ref)296472758f3SLionel Sambuc _Unwind_Reason_Code _Unwind_Backtrace(_Unwind_Trace_Fn callback, void *ref) {
297b029fb59SBen Gras NativeUnwindRegisters registers;
298472758f3SLionel Sambuc ThisUnwindCursor cursor(registers, sThisAddressSpace);
299472758f3SLionel Sambuc cursor.setInfoBasedOnIPRegister();
300472758f3SLionel Sambuc
301472758f3SLionel Sambuc // Walk each frame.
302472758f3SLionel Sambuc while (true) {
303472758f3SLionel Sambuc
304472758f3SLionel Sambuc // Ask libuwind to get next frame (skip over first frame which is
305472758f3SLionel Sambuc // _Unwind_Backtrace()).
306472758f3SLionel Sambuc if (cursor.step() != UNW_STEP_SUCCESS)
307472758f3SLionel Sambuc return _URC_END_OF_STACK;
308472758f3SLionel Sambuc
309472758f3SLionel Sambuc // Call trace function with this frame.
310472758f3SLionel Sambuc _Unwind_Reason_Code result =
311472758f3SLionel Sambuc (*callback)((struct _Unwind_Context *)(&cursor), ref);
312472758f3SLionel Sambuc if (result != _URC_NO_REASON)
313472758f3SLionel Sambuc return result;
314472758f3SLionel Sambuc }
315472758f3SLionel Sambuc }
316472758f3SLionel Sambuc
_Unwind_GetCFA(struct _Unwind_Context * context)317472758f3SLionel Sambuc uintptr_t _Unwind_GetCFA(struct _Unwind_Context *context) {
318472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
319472758f3SLionel Sambuc return cursor->getSP();
320472758f3SLionel Sambuc }
321472758f3SLionel Sambuc
_Unwind_FindEnclosingFunction(void * pc)322472758f3SLionel Sambuc void *_Unwind_FindEnclosingFunction(void *pc) {
323b029fb59SBen Gras NativeUnwindRegisters registers;
324472758f3SLionel Sambuc ThisUnwindCursor cursor(registers, sThisAddressSpace);
325472758f3SLionel Sambuc
326472758f3SLionel Sambuc unw_proc_info_t info;
327472758f3SLionel Sambuc cursor.setIP((uintptr_t)pc);
328472758f3SLionel Sambuc cursor.setInfoBasedOnIPRegister();
329472758f3SLionel Sambuc
330472758f3SLionel Sambuc cursor.getInfo(&info);
331472758f3SLionel Sambuc return info.end_ip ? (void *)info.start_ip : NULL;
332472758f3SLionel Sambuc }
333472758f3SLionel Sambuc
_Unwind_Find_FDE(void * pc,struct dwarf_eh_bases * bases)334*0a6a1f1dSLionel Sambuc void *_Unwind_Find_FDE(void *pc, struct dwarf_eh_bases *bases) {
335*0a6a1f1dSLionel Sambuc NativeUnwindRegisters registers;
336*0a6a1f1dSLionel Sambuc ThisUnwindCursor cursor(registers, sThisAddressSpace);
337*0a6a1f1dSLionel Sambuc
338*0a6a1f1dSLionel Sambuc unw_proc_info_t info;
339*0a6a1f1dSLionel Sambuc cursor.setIP((uintptr_t)pc);
340*0a6a1f1dSLionel Sambuc cursor.setInfoBasedOnIPRegister();
341*0a6a1f1dSLionel Sambuc
342*0a6a1f1dSLionel Sambuc cursor.getInfo(&info);
343*0a6a1f1dSLionel Sambuc if (info.end_ip == 0)
344*0a6a1f1dSLionel Sambuc return NULL;
345*0a6a1f1dSLionel Sambuc bases->tbase = 0; /* Not supported */
346*0a6a1f1dSLionel Sambuc bases->dbase = (void *)info.data_base;
347*0a6a1f1dSLionel Sambuc bases->func = (void *)info.start_ip;
348*0a6a1f1dSLionel Sambuc return (void *)info.unwind_info;
349*0a6a1f1dSLionel Sambuc }
350*0a6a1f1dSLionel Sambuc
_Unwind_GetDataRelBase(struct _Unwind_Context * context)351472758f3SLionel Sambuc uintptr_t _Unwind_GetDataRelBase(struct _Unwind_Context *context) {
352472758f3SLionel Sambuc ThisUnwindCursor *cursor = (ThisUnwindCursor *)context;
353472758f3SLionel Sambuc unw_proc_info_t frameInfo;
354472758f3SLionel Sambuc cursor->getInfo(&frameInfo);
355472758f3SLionel Sambuc return frameInfo.data_base;
356472758f3SLionel Sambuc }
357472758f3SLionel Sambuc
_Unwind_GetTextRelBase(struct _Unwind_Context * context)358472758f3SLionel Sambuc uintptr_t _Unwind_GetTextRelBase(struct _Unwind_Context *context) { return 0; }
359472758f3SLionel Sambuc
__register_frame(const void * fde)360472758f3SLionel Sambuc void __register_frame(const void *fde) {
361472758f3SLionel Sambuc MyCFIParser::pint_t pcStart, pcEnd;
362472758f3SLionel Sambuc
363472758f3SLionel Sambuc MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
364472758f3SLionel Sambuc if (pcEnd == 0)
365472758f3SLionel Sambuc return; // Bad FDE.
366472758f3SLionel Sambuc
367472758f3SLionel Sambuc sThisAddressSpace.addFDE(pcStart, pcEnd, (uintptr_t)fde);
368472758f3SLionel Sambuc }
369472758f3SLionel Sambuc
__register_frame_info(const void * ehframe,void * storage)370472758f3SLionel Sambuc void __register_frame_info(const void *ehframe, void *storage) {
371472758f3SLionel Sambuc sThisAddressSpace.setLazyReload();
372472758f3SLionel Sambuc }
373472758f3SLionel Sambuc
__deregister_frame(const void * fde)374472758f3SLionel Sambuc void __deregister_frame(const void *fde) {
375472758f3SLionel Sambuc MyCFIParser::pint_t pcStart, pcEnd;
376472758f3SLionel Sambuc
377472758f3SLionel Sambuc MyCFIParser::findPCRange(sThisAddressSpace, (uintptr_t)fde, pcStart, pcEnd);
378472758f3SLionel Sambuc if (pcEnd == 0)
379472758f3SLionel Sambuc return; // Bad FDE.
380472758f3SLionel Sambuc
381472758f3SLionel Sambuc sThisAddressSpace.removeFDE(pcStart, pcEnd, (uintptr_t)fde);
382472758f3SLionel Sambuc }
383472758f3SLionel Sambuc
__deregister_frame_info(const void * ehFrameStart)384472758f3SLionel Sambuc void *__deregister_frame_info(const void *ehFrameStart) {
385472758f3SLionel Sambuc sThisAddressSpace.removeDSO((LocalAddressSpace::pint_t)ehFrameStart);
386472758f3SLionel Sambuc return NULL;
387472758f3SLionel Sambuc }
388