1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 | // for details. All rights reserved. Use of this source code is governed by a |
3 | // BSD-style license that can be found in the LICENSE file. |
4 | |
5 | #include "vm/globals.h" |
6 | #include "vm/instructions.h" |
7 | #include "vm/signal_handler.h" |
8 | #include "vm/simulator.h" |
9 | #if defined(HOST_OS_ANDROID) |
10 | |
11 | namespace dart { |
12 | |
13 | uintptr_t SignalHandler::GetProgramCounter(const mcontext_t& mcontext) { |
14 | uintptr_t pc = 0; |
15 | |
16 | #if defined(HOST_ARCH_IA32) |
17 | pc = static_cast<uintptr_t>(mcontext.gregs[REG_EIP]); |
18 | #elif defined(HOST_ARCH_X64) |
19 | pc = static_cast<uintptr_t>(mcontext.gregs[REG_RIP]); |
20 | #elif defined(HOST_ARCH_ARM) |
21 | pc = static_cast<uintptr_t>(mcontext.arm_pc); |
22 | #elif defined(HOST_ARCH_ARM64) |
23 | pc = static_cast<uintptr_t>(mcontext.pc); |
24 | #else |
25 | #error Unsupported architecture. |
26 | #endif // HOST_ARCH_... |
27 | return pc; |
28 | } |
29 | |
30 | uintptr_t SignalHandler::GetFramePointer(const mcontext_t& mcontext) { |
31 | uintptr_t fp = 0; |
32 | |
33 | #if defined(HOST_ARCH_IA32) |
34 | fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]); |
35 | #elif defined(HOST_ARCH_X64) |
36 | fp = static_cast<uintptr_t>(mcontext.gregs[REG_RBP]); |
37 | #elif defined(HOST_ARCH_ARM) |
38 | // B1.3.3 Program Status Registers (PSRs) |
39 | if ((mcontext.arm_cpsr & (1 << 5)) != 0) { |
40 | // Thumb mode. |
41 | fp = static_cast<uintptr_t>(mcontext.arm_r7); |
42 | } else { |
43 | // ARM mode. |
44 | fp = static_cast<uintptr_t>(mcontext.arm_fp); |
45 | } |
46 | #elif defined(HOST_ARCH_ARM64) |
47 | fp = static_cast<uintptr_t>(mcontext.regs[29]); |
48 | #else |
49 | #error Unsupported architecture. |
50 | #endif // HOST_ARCH_... |
51 | |
52 | return fp; |
53 | } |
54 | |
55 | uintptr_t SignalHandler::GetCStackPointer(const mcontext_t& mcontext) { |
56 | uintptr_t sp = 0; |
57 | |
58 | #if defined(HOST_ARCH_IA32) |
59 | sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]); |
60 | #elif defined(HOST_ARCH_X64) |
61 | sp = static_cast<uintptr_t>(mcontext.gregs[REG_RSP]); |
62 | #elif defined(HOST_ARCH_ARM) |
63 | sp = static_cast<uintptr_t>(mcontext.arm_sp); |
64 | #elif defined(HOST_ARCH_ARM64) |
65 | sp = static_cast<uintptr_t>(mcontext.sp); |
66 | #else |
67 | #error Unsupported architecture. |
68 | #endif // HOST_ARCH_... |
69 | return sp; |
70 | } |
71 | |
72 | uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) { |
73 | #if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR) |
74 | return static_cast<uintptr_t>(mcontext.regs[SPREG]); |
75 | #else |
76 | return GetCStackPointer(mcontext); |
77 | #endif |
78 | } |
79 | |
80 | uintptr_t SignalHandler::GetLinkRegister(const mcontext_t& mcontext) { |
81 | uintptr_t lr = 0; |
82 | |
83 | #if defined(HOST_ARCH_IA32) |
84 | lr = 0; |
85 | #elif defined(HOST_ARCH_X64) |
86 | lr = 0; |
87 | #elif defined(HOST_ARCH_ARM) |
88 | lr = static_cast<uintptr_t>(mcontext.arm_lr); |
89 | #elif defined(HOST_ARCH_ARM64) |
90 | lr = static_cast<uintptr_t>(mcontext.regs[30]); |
91 | #else |
92 | #error Unsupported architecture. |
93 | #endif // HOST_ARCH_... |
94 | return lr; |
95 | } |
96 | |
97 | void SignalHandler::InstallImpl(SignalAction action) { |
98 | // Bionic implementation of setjmp temporary mangles SP register |
99 | // in place which breaks signal delivery on the thread stack - when |
100 | // kernel tries to deliver SIGPROF and we are in the middle of |
101 | // setjmp SP value is invalid - might be pointing to random memory |
102 | // or outside of writable space at all. In the first case we |
103 | // get memory corruption and in the second case kernel would send |
104 | // SIGSEGV to the process. See b/152210274 for details. |
105 | // To work around this issue we are using alternative signal stack |
106 | // to handle SIGPROF signals. |
107 | stack_t ss; |
108 | ss.ss_size = SIGSTKSZ; |
109 | ss.ss_sp = malloc(ss.ss_size); |
110 | ss.ss_flags = 0; |
111 | int r = sigaltstack(&ss, NULL); |
112 | ASSERT(r == 0); |
113 | |
114 | struct sigaction act = {}; |
115 | act.sa_sigaction = action; |
116 | sigemptyset(&act.sa_mask); |
117 | act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; |
118 | r = sigaction(SIGPROF, &act, NULL); |
119 | ASSERT(r == 0); |
120 | } |
121 | |
122 | void SignalHandler::Remove() { |
123 | // Ignore future SIGPROF signals because by default SIGPROF will terminate |
124 | // the process and we may have some signals in flight. |
125 | struct sigaction act = {}; |
126 | act.sa_handler = SIG_IGN; |
127 | sigemptyset(&act.sa_mask); |
128 | int r = sigaction(SIGPROF, &act, NULL); |
129 | ASSERT(r == 0); |
130 | |
131 | // Disable and delete alternative signal stack. |
132 | stack_t ss, old_ss; |
133 | ss.ss_flags = SS_DISABLE; |
134 | r = sigaltstack(&ss, &old_ss); |
135 | ASSERT(r == 0); |
136 | free(old_ss.ss_sp); |
137 | } |
138 | |
139 | } // namespace dart |
140 | |
141 | #endif // defined(HOST_OS_ANDROID) |
142 | |