Skip to content

Commit 3405dc6

Browse files
authored
Fix get_sp implementation for s390x (#389)
On s390x we use a biased CFA: the CFA of a function equal the SP at function entry plus a constant of 160. Therefore, the current implementation of get_sp, which uses _Unwind_GetCFA, is not an appropriate way to retrieve the current SP value on this platform. Instead, use _Unwind_GetGR to explicitly retrieve the value of the stack pointer register %r15.
1 parent 28531b6 commit 3405dc6

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

src/backtrace/libunwind.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ mod uw {
168168
#[cfg(all(
169169
not(all(target_os = "android", target_arch = "arm")),
170170
not(all(target_os = "freebsd", target_arch = "arm")),
171-
not(all(target_os = "linux", target_arch = "arm"))
171+
not(all(target_os = "linux", target_arch = "arm")),
172+
not(all(target_os = "linux", target_arch = "s390x"))
172173
))]
173174
// This function is a misnomer: rather than getting this frame's
174175
// Canonical Frame Address (aka the caller frame's SP) it
@@ -179,6 +180,17 @@ mod uw {
179180
pub fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t;
180181
}
181182

183+
// s390x uses a biased CFA value, therefore we need to use
184+
// _Unwind_GetGR to get the stack pointer register (%r15)
185+
// instead of relying on _Unwind_GetCFA.
186+
#[cfg(all(target_os = "linux", target_arch = "s390x"))]
187+
pub unsafe fn get_sp(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
188+
extern "C" {
189+
pub fn _Unwind_GetGR(ctx: *mut _Unwind_Context, index: libc::c_int) -> libc::uintptr_t;
190+
}
191+
_Unwind_GetGR(ctx, 15)
192+
}
193+
182194
// On android and arm, the function `_Unwind_GetIP` and a bunch of others
183195
// are macros, so we define functions containing the expansion of the
184196
// macros.

0 commit comments

Comments
 (0)