Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework inline aarch64 asm for setcontext #748

Merged
merged 1 commit into from
Jun 11, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
115 changes: 61 additions & 54 deletions src/aarch64/Gos-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Copyright (C) 2008 CodeSourcery
Copyright (C) 2011-2013 Linaro Limited
Copyright (C) 2012 Tommi Rantala <tt.rantala@gmail.com>
Copyright 2024 Stephen M. Webb <swebb@blackberry.com>

This file is part of libunwind.

Expand All @@ -28,6 +29,28 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */

#ifndef UNW_REMOTE_ONLY

/* Magic constants generated from gen-offsets.c */
#define SC_R0_OFF "8"
#define SC_R2_OFF "24"
#define SC_R18_OFF "152"
#define SC_R20_OFF "168"
#define SC_R22_OFF "184"
#define SC_R24_OFF "200"
#define SC_R26_OFF "216"
#define SC_R28_OFF "232"
#define SC_R30_OFF "248"

#define FP_R08_OFF "80"
#define FP_R09_OFF "88"
#define FP_R10_OFF "96"
#define FP_R11_OFF "104"
#define FP_R12_OFF "112"
#define FP_R13_OFF "120"
#define FP_R14_OFF "128"
#define FP_R15_OFF "136"

#define SC_SP_OFF "0x100"

HIDDEN int
aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)
{
Expand All @@ -36,65 +59,49 @@ aarch64_local_resume (unw_addr_space_t as, unw_cursor_t *cursor, void *arg)

if (c->sigcontext_format == AARCH64_SCF_NONE)
{

/*
* This is effectively the old POSIX setcontext().
*
* This inline asm is broken up to use local scratch registers for the
* uc_mcontext.regs and FPCTX base addresses because newer versions of GCC
* and clang barf on too many constraints (gh-702) when the C array
* elements are used directly.
*
* Clobbers aren't required for the inline asm because they just convince
* the compiler to save those registers and they never get restored
* becauise the asm ends with a plain ol' ret.
*/
register void* uc_mcontext __asm__ ("x5") = (void*) &uc->uc_mcontext;
register void* fpctx __asm__ ("x4") = (void*) GET_FPCTX(uc);

/* Since there are no signals involved here we restore EH and non scratch
registers only. */
__asm__ __volatile__ (
"ldr x0, %[x0]\n\t"
"ldr x1, %[x1]\n\t"
"ldr x2, %[x2]\n\t"
"ldr x3, %[x3]\n\t"
"ldr x19, %[x19]\n\t"
"ldr x20, %[x20]\n\t"
"ldr x21, %[x21]\n\t"
"ldr x22, %[x22]\n\t"
"ldr x23, %[x23]\n\t"
"ldr x24, %[x24]\n\t"
"ldr x25, %[x25]\n\t"
"ldr x26, %[x26]\n\t"
"ldr x27, %[x27]\n\t"
"ldr x28, %[x28]\n\t"
"ldr x29, %[x29]\n\t"
"ldr x30, %[x30]\n\t"
"ldr d8, %[d8]\n\t"
"ldr d9, %[d9]\n\t"
"ldr d10, %[d10]\n\t"
"ldr d11, %[d11]\n\t"
"ldr d12, %[d12]\n\t"
"ldr d13, %[d13]\n\t"
"ldr d14, %[d14]\n\t"
"ldr d15, %[d15]\n\t"
"ldr x5, %[sp]\n\t"
"ldp x0, x1, [x5, " SC_R0_OFF "]\n\t"
"ldp x2, x3, [x5, " SC_R2_OFF "]\n\t"
"ldp x18, x19, [x5, " SC_R18_OFF "]\n\t"
"ldp x20, x21, [x5, " SC_R20_OFF "]\n\t"
"ldp x22, x23, [x5, " SC_R22_OFF "]\n\t"
"ldp x24, x25, [x5, " SC_R24_OFF "]\n\t"
"ldp x26, x27, [x5, " SC_R26_OFF "]\n\t"
"ldp x28, x29, [x5, " SC_R28_OFF "]\n\t"
"ldr x30, [x5, " SC_R30_OFF "]\n\t"
"ldr d8, [x4, " FP_R08_OFF "]\n\t"
"ldr d9, [x4, " FP_R09_OFF "]\n\t"
"ldr d10, [x4, " FP_R10_OFF "]\n\t"
"ldr d11, [x4, " FP_R11_OFF "]\n\t"
"ldr d12, [x4, " FP_R12_OFF "]\n\t"
"ldr d13, [x4, " FP_R13_OFF "]\n\t"
"ldr d14, [x4, " FP_R14_OFF "]\n\t"
"ldr d15, [x4, " FP_R15_OFF "]\n\t"
"ldr x5, [x5, " SC_SP_OFF "]\n\t"
"mov sp, x5\n\t"
"ret\n"
:
: [x0] "m"(uc->uc_mcontext.regs[0]),
[x1] "m"(uc->uc_mcontext.regs[1]),
[x2] "m"(uc->uc_mcontext.regs[2]),
[x3] "m"(uc->uc_mcontext.regs[3]),
[x19] "m"(uc->uc_mcontext.regs[19]),
[x20] "m"(uc->uc_mcontext.regs[20]),
[x21] "m"(uc->uc_mcontext.regs[21]),
[x22] "m"(uc->uc_mcontext.regs[22]),
[x23] "m"(uc->uc_mcontext.regs[23]),
[x24] "m"(uc->uc_mcontext.regs[24]),
[x25] "m"(uc->uc_mcontext.regs[25]),
[x26] "m"(uc->uc_mcontext.regs[26]),
[x27] "m"(uc->uc_mcontext.regs[27]),
[x28] "m"(uc->uc_mcontext.regs[28]),
[x29] "m"(uc->uc_mcontext.regs[29]), /* FP */
[x30] "m"(uc->uc_mcontext.regs[30]), /* LR */
[d8] "m"(GET_FPCTX(uc)->vregs[8]),
[d9] "m"(GET_FPCTX(uc)->vregs[9]),
[d10] "m"(GET_FPCTX(uc)->vregs[10]),
[d11] "m"(GET_FPCTX(uc)->vregs[11]),
[d12] "m"(GET_FPCTX(uc)->vregs[12]),
[d13] "m"(GET_FPCTX(uc)->vregs[13]),
[d14] "m"(GET_FPCTX(uc)->vregs[14]),
[d15] "m"(GET_FPCTX(uc)->vregs[15]),
[sp] "m"(uc->uc_mcontext.sp)
: "x0", "x1", "x2", "x3", "x19", "x20", "x21", "x22", "x23", "x24",
"x25", "x26", "x27", "x28", "x29", "x30"
);
:
: [uc_mcontext] "r"(uc_mcontext),
[fpctx] "r"(fpctx)
);
}
else
{
Expand Down