diff options
Diffstat (limited to 'system/libucontext/ppc64-stack-layout.patch')
-rw-r--r-- | system/libucontext/ppc64-stack-layout.patch | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/system/libucontext/ppc64-stack-layout.patch b/system/libucontext/ppc64-stack-layout.patch new file mode 100644 index 000000000..d030b61af --- /dev/null +++ b/system/libucontext/ppc64-stack-layout.patch @@ -0,0 +1,105 @@ +From a17b01bc9df4004a1852ba272d452b0f46f5927c Mon Sep 17 00:00:00 2001 +From: Bobby Bingham <koorogi@koorogi.info> +Date: Tue, 19 Feb 2019 06:27:28 +0000 +Subject: [PATCH 3/3] ppc64: fix stack frame layout + +--- + arch/ppc64/makecontext.c | 48 +++++++++++++++++----------------------- + 1 file changed, 20 insertions(+), 28 deletions(-) + +diff --git a/arch/ppc64/makecontext.c b/arch/ppc64/makecontext.c +index 9d6b998..6d9841c 100644 +--- a/arch/ppc64/makecontext.c ++++ b/arch/ppc64/makecontext.c +@@ -1,5 +1,6 @@ + /* + * Copyright (c) 2018 William Pitcock <nenolod@dereferenced.org> ++ * Copyright (c) 2019 Bobby Bingham <koorogi@koorogi.info> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above +@@ -11,32 +12,39 @@ + */ + + #define _GNU_SOURCE +-#include <stddef.h> + #include <stdarg.h> + #include <signal.h> +-#include <string.h> + #include <stdint.h> + +- + #include "defs.h" + + + extern void __start_context(void); + + ++#define SAVEARG(i,val) \ ++ do { \ ++ *(i < 8 ? &ucp->uc_mcontext.gp_regs[3+i] : argp) = val; \ ++ argp++; \ ++ } while (0) ++ + void + __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) + { + greg_t *sp, *argp; + va_list va; +- int i; +- unsigned int uc_link, stack_args; ++ unsigned int stack_args; ++ ++ /* We pass uc_link as an argument, so in total we have argc+1 args */ ++ stack_args = argc + 1; + +- stack_args = argc > 8 ? argc - 8 : 0; +- uc_link = stack_args + 1; ++ /* We can pass 8 args before needing the stack. If any arg is passed ++ * on the stack, then stack space must be reserved for all args, even ++ * though the first 8 don't need to be stored there */ ++ if (stack_args <= 8) stack_args = 0; + + sp = (greg_t *) ((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size); +- sp -= (uc_link + 1); ++ sp -= stack_args + 4; + sp = (greg_t *) (((uintptr_t) sp & -16L)); + + ucp->uc_mcontext.gp_regs[REG_NIP] = (uintptr_t) func; +@@ -45,29 +53,13 @@ __makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) + ucp->uc_mcontext.gp_regs[REG_ENTRY] = (uintptr_t) func; + ucp->uc_mcontext.gp_regs[REG_R31] = (uintptr_t) ucp->uc_link; + +- sp[0] = (uintptr_t) &__start_context; +- sp[uc_link] = (uintptr_t) ucp->uc_link; +- argp = &sp[2]; ++ sp[0] = 0; ++ argp = &sp[4]; + + va_start(va, argc); + +- for (i = 0; i < argc; i++) +- switch (i) +- { +- case 0: +- case 1: +- case 2: +- case 3: +- case 4: +- case 5: +- case 6: +- case 7: +- ucp->uc_mcontext.gp_regs[i + 3] = va_arg (va, greg_t); +- break; +- default: +- *argp++ = va_arg (va, greg_t); +- break; +- } ++ for (int i = 0; i < argc; i++) SAVEARG(i, va_arg(va, greg_t)); ++ SAVEARG(argc, (uintptr_t) ucp->uc_link); + + va_end(va); + } +-- +2.19.2 + |