summaryrefslogtreecommitdiff
path: root/system/libucontext/ppc64-stack-layout.patch
diff options
context:
space:
mode:
Diffstat (limited to 'system/libucontext/ppc64-stack-layout.patch')
-rw-r--r--system/libucontext/ppc64-stack-layout.patch105
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
+