-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathada-x86-android.patch
63 lines (59 loc) · 2.83 KB
/
ada-x86-android.patch
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
diff -rup gcc-6.4.0/gcc/ada/init.c gcc-6.4.0-new/gcc/ada/init.c
--- gcc-6.4.0/gcc/ada/init.c 2015-11-25 07:16:44.605929000 -0800
+++ gcc-6.4.0-new/gcc/ada/init.c 2018-10-28 21:43:17.804437431 -0700
@@ -2510,8 +2510,45 @@ __gnat_adjust_context_for_raise (int sig
{
mcontext_t *mcontext = &((ucontext_t *) ucontext)->uc_mcontext;
+ /* On the i386 and x86-64 architectures, stack checking is performed by
+ means of probes with moving stack pointer, that is to say the probed
+ address is always the value of the stack pointer. Upon hitting the
+ guard page, the stack pointer therefore points to an inaccessible
+ address and an alternate signal stack is needed to run the handler.
+ But there is an additional twist: on these architectures, the EH
+ return code writes the address of the handler at the target CFA's
+ value on the stack before doing the jump. As a consequence, if
+ there is an active handler in the frame whose stack has overflowed,
+ the stack pointer must nevertheless point to an accessible address
+ by the time the EH return is executed.
+
+ We therefore adjust the saved value of the stack pointer by the size
+ of one page + a small dope of 4 words, in order to make sure that it
+ points to an accessible address in case it's used as the target CFA.
+ The stack checking code guarantees that this address is unused by the
+ time this happens. */
+
+#if defined (__i386__)
+ unsigned long *pc = (unsigned long *)mcontext->gregs[REG_EIP];
+ /* The pattern is "orl $0x0,(%esp)" for a probe in 32-bit mode. */
+ if (signo == SIGSEGV && pc && *pc == 0x00240c83)
+ mcontext->gregs[REG_ESP] += 4096 + 4 * sizeof (unsigned long);
+#elif defined (__x86_64__)
+ unsigned long long *pc = (unsigned long long *)mcontext->gregs[REG_RIP];
+ if (signo == SIGSEGV && pc
+ /* The pattern is "orq $0x0,(%rsp)" for a probe in 64-bit mode. */
+ && ((*pc & 0xffffffffffLL) == 0x00240c8348LL
+ /* The pattern may also be "orl $0x0,(%esp)" for a probe in
+ x32 mode. */
+ || (*pc & 0xffffffffLL) == 0x00240c83LL))
+ mcontext->gregs[REG_RSP] += 4096 + 4 * sizeof (unsigned long);
+#elif defined (__ia64__)
+ /* ??? The IA-64 unwinder doesn't compensate for signals. */
+ mcontext->sc_ip++;
+#elif defined (__ARMEL__)
/* ARM Bump has to be an even number because of odd/even architecture. */
- ((mcontext_t *) mcontext)->arm_pc += 2;
+ mcontext->arm_pc+=2;
+#endif
}
static void
@@ -2552,8 +2589,12 @@ __gnat_error_handler (int sig, siginfo_t
{
__gnat_adjust_context_for_raise (sig, ucontext);
+ #if defined (__ARMEL__)
__gnat_sigtramp (sig, (void *) si, (void *) ucontext,
(__sigtramphandler_t *)&__gnat_map_signal);
+ #else
+ __gnat_map_signal (sig, si, ucontext);
+ #endif
}
/* This must be in keeping with System.OS_Interface.Alternate_Stack_Size. */