1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
|