@@ -31,6 +31,7 @@ pub enum Frame {
3131 Raw ( * mut uw:: _Unwind_Context ) ,
3232 Cloned {
3333 ip : * mut c_void ,
34+ sp : * mut c_void ,
3435 symbol_address : * mut c_void ,
3536 } ,
3637}
@@ -51,6 +52,13 @@ impl Frame {
5152 unsafe { uw:: _Unwind_GetIP ( ctx) as * mut c_void }
5253 }
5354
55+ pub fn sp ( & self ) -> * mut c_void {
56+ match * self {
57+ Frame :: Raw ( ctx) => unsafe { uw:: get_sp ( ctx) as * mut c_void } ,
58+ Frame :: Cloned { sp, .. } => sp,
59+ }
60+ }
61+
5462 pub fn symbol_address ( & self ) -> * mut c_void {
5563 if let Frame :: Cloned { symbol_address, .. } = * self {
5664 return symbol_address;
@@ -76,6 +84,7 @@ impl Clone for Frame {
7684 fn clone ( & self ) -> Frame {
7785 Frame :: Cloned {
7886 ip : self . ip ( ) ,
87+ sp : self . sp ( ) ,
7988 symbol_address : self . symbol_address ( ) ,
8089 }
8190 }
@@ -155,22 +164,46 @@ mod uw {
155164 pub fn _Unwind_GetIP ( ctx : * mut _Unwind_Context ) -> libc:: uintptr_t ;
156165
157166 #[ cfg( all(
158- not( target_os = "android" ) ,
167+ not( all ( target_os = "android" , target_arch = "arm" ) ) ,
159168 not( all( target_os = "freebsd" , target_arch = "arm" ) ) ,
160169 not( all( target_os = "linux" , target_arch = "arm" ) )
161170 ) ) ]
162171 pub fn _Unwind_FindEnclosingFunction ( pc : * mut c_void ) -> * mut c_void ;
172+
173+ #[ cfg( all(
174+ not( all( target_os = "android" , target_arch = "arm" ) ) ,
175+ not( all( target_os = "freebsd" , target_arch = "arm" ) ) ,
176+ not( all( target_os = "linux" , target_arch = "arm" ) )
177+ ) ) ]
178+ // This function is a misnomer: rather than getting this frame's
179+ // Canonical Frame Address (aka the caller frame's SP) it
180+ // returns this frame's SP.
181+ //
182+ // https://github.com/libunwind/libunwind/blob/d32956507cf29d9b1a98a8bce53c78623908f4fe/src/unwind/GetCFA.c#L28-L35
183+ #[ link_name = "_Unwind_GetCFA" ]
184+ pub fn get_sp ( ctx : * mut _Unwind_Context ) -> libc:: uintptr_t ;
163185 }
164186
165- // On android, the function _Unwind_GetIP is a macro, and this is the
166- // expansion of the macro. This is all copy/pasted directly from the
167- // header file with the definition of _Unwind_GetIP.
187+ // On android and arm, the function `_Unwind_GetIP` and a bunch of others
188+ // are macros, so we define functions containing the expansion of the
189+ // macros.
190+ //
191+ // TODO: link to the header file that defines these macros, if you can find
192+ // it. (I, fitzgen, cannot find the header file that some of these macro
193+ // expansions were originally borrowed from.)
194+ #[ cfg( any(
195+ all( target_os = "android" , target_arch = "arm" ) ,
196+ all( target_os = "freebsd" , target_arch = "arm" ) ,
197+ all( target_os = "linux" , target_arch = "arm" )
198+ ) ) ]
199+ pub use self :: arm:: * ;
168200 #[ cfg( any(
169201 all( target_os = "android" , target_arch = "arm" ) ,
170202 all( target_os = "freebsd" , target_arch = "arm" ) ,
171203 all( target_os = "linux" , target_arch = "arm" )
172204 ) ) ]
173- pub unsafe fn _Unwind_GetIP ( ctx : * mut _Unwind_Context ) -> libc:: uintptr_t {
205+ mod arm {
206+ pub use super :: * ;
174207 #[ repr( C ) ]
175208 enum _Unwind_VRS_Result {
176209 _UVRSR_OK = 0 ,
@@ -206,26 +239,39 @@ mod uw {
206239 ) -> _Unwind_VRS_Result ;
207240 }
208241
209- let mut val: _Unwind_Word = 0 ;
210- let ptr = & mut val as * mut _Unwind_Word ;
211- let _ = _Unwind_VRS_Get (
212- ctx,
213- _Unwind_VRS_RegClass:: _UVRSC_CORE,
214- 15 ,
215- _Unwind_VRS_DataRepresentation:: _UVRSD_UINT32,
216- ptr as * mut c_void ,
217- ) ;
218- ( val & !1 ) as libc:: uintptr_t
219- }
242+ pub unsafe fn _Unwind_GetIP ( ctx : * mut _Unwind_Context ) -> libc:: uintptr_t {
243+ let mut val: _Unwind_Word = 0 ;
244+ let ptr = & mut val as * mut _Unwind_Word ;
245+ let _ = _Unwind_VRS_Get (
246+ ctx,
247+ _Unwind_VRS_RegClass:: _UVRSC_CORE,
248+ 15 ,
249+ _Unwind_VRS_DataRepresentation:: _UVRSD_UINT32,
250+ ptr as * mut c_void ,
251+ ) ;
252+ ( val & !1 ) as libc:: uintptr_t
253+ }
220254
221- // This function also doesn't exist on Android or ARM/Linux, so make it
222- // a no-op
223- #[ cfg( any(
224- target_os = "android" ,
225- all( target_os = "freebsd" , target_arch = "arm" ) ,
226- all( target_os = "linux" , target_arch = "arm" )
227- ) ) ]
228- pub unsafe fn _Unwind_FindEnclosingFunction ( pc : * mut c_void ) -> * mut c_void {
229- pc
255+ // R13 is the stack pointer on arm.
256+ const SP : _Unwind_Word = 13 ;
257+
258+ pub unsafe fn get_sp ( ctx : * mut _Unwind_Context ) -> libc:: uintptr_t {
259+ let mut val: _Unwind_Word = 0 ;
260+ let ptr = & mut val as * mut _Unwind_Word ;
261+ let _ = _Unwind_VRS_Get (
262+ ctx,
263+ _Unwind_VRS_RegClass:: _UVRSC_CORE,
264+ SP ,
265+ _Unwind_VRS_DataRepresentation:: _UVRSD_UINT32,
266+ ptr as * mut c_void ,
267+ ) ;
268+ val as libc:: uintptr_t
269+ }
270+
271+ // This function also doesn't exist on Android or ARM/Linux, so make it
272+ // a no-op.
273+ pub unsafe fn _Unwind_FindEnclosingFunction ( pc : * mut c_void ) -> * mut c_void {
274+ pc
275+ }
230276 }
231277}
0 commit comments