Flutter Engine
The Flutter Engine
signal_handler_android.cc
Go to the documentation of this file.
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(DART_HOST_OS_ANDROID)
10
11namespace dart {
12
13uintptr_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#elif defined(HOST_ARCH_RISCV64)
25 pc = static_cast<uintptr_t>(mcontext.__gregs[REG_PC]);
26#else
27#error Unsupported architecture.
28#endif // HOST_ARCH_...
29 return pc;
30}
31
32uintptr_t SignalHandler::GetFramePointer(const mcontext_t& mcontext) {
33 uintptr_t fp = 0;
34
35#if defined(HOST_ARCH_IA32)
36 fp = static_cast<uintptr_t>(mcontext.gregs[REG_EBP]);
37#elif defined(HOST_ARCH_X64)
38 fp = static_cast<uintptr_t>(mcontext.gregs[REG_RBP]);
39#elif defined(HOST_ARCH_ARM)
40 // B1.3.3 Program Status Registers (PSRs)
41 if ((mcontext.arm_cpsr & (1 << 5)) != 0) {
42 // Thumb mode.
43 fp = static_cast<uintptr_t>(mcontext.arm_r7);
44 } else {
45 // ARM mode.
46 fp = static_cast<uintptr_t>(mcontext.arm_fp);
47 }
48#elif defined(HOST_ARCH_ARM64)
49 fp = static_cast<uintptr_t>(mcontext.regs[29]);
50#elif defined(HOST_ARCH_RISCV64)
51 fp = static_cast<uintptr_t>(mcontext.__gregs[REG_S0]);
52#else
53#error Unsupported architecture.
54#endif // HOST_ARCH_...
55
56 return fp;
57}
58
59uintptr_t SignalHandler::GetCStackPointer(const mcontext_t& mcontext) {
60 uintptr_t sp = 0;
61
62#if defined(HOST_ARCH_IA32)
63 sp = static_cast<uintptr_t>(mcontext.gregs[REG_ESP]);
64#elif defined(HOST_ARCH_X64)
65 sp = static_cast<uintptr_t>(mcontext.gregs[REG_RSP]);
66#elif defined(HOST_ARCH_ARM)
67 sp = static_cast<uintptr_t>(mcontext.arm_sp);
68#elif defined(HOST_ARCH_ARM64)
69 sp = static_cast<uintptr_t>(mcontext.sp);
70#elif defined(HOST_ARCH_RISCV64)
71 sp = static_cast<uintptr_t>(mcontext.__gregs[REG_SP]);
72#else
73#error Unsupported architecture.
74#endif // HOST_ARCH_...
75 return sp;
76}
77
78uintptr_t SignalHandler::GetDartStackPointer(const mcontext_t& mcontext) {
79#if defined(TARGET_ARCH_ARM64) && !defined(USING_SIMULATOR)
80 return static_cast<uintptr_t>(mcontext.regs[SPREG]);
81#else
82 return GetCStackPointer(mcontext);
83#endif
84}
85
86uintptr_t SignalHandler::GetLinkRegister(const mcontext_t& mcontext) {
87 uintptr_t lr = 0;
88
89#if defined(HOST_ARCH_IA32)
90 lr = 0;
91#elif defined(HOST_ARCH_X64)
92 lr = 0;
93#elif defined(HOST_ARCH_ARM)
94 lr = static_cast<uintptr_t>(mcontext.arm_lr);
95#elif defined(HOST_ARCH_ARM64)
96 lr = static_cast<uintptr_t>(mcontext.regs[30]);
97#elif defined(HOST_ARCH_RISCV64)
98 lr = static_cast<uintptr_t>(mcontext.__gregs[REG_RA]);
99#else
100#error Unsupported architecture.
101#endif // HOST_ARCH_...
102 return lr;
103}
104
106 // Bionic implementation of setjmp temporary mangles SP register
107 // in place which breaks signal delivery on the thread stack - when
108 // kernel tries to deliver SIGPROF and we are in the middle of
109 // setjmp SP value is invalid - might be pointing to random memory
110 // or outside of writable space at all. In the first case we
111 // get memory corruption and in the second case kernel would send
112 // SIGSEGV to the process. See b/152210274 for details.
113 // To work around this issue we request SIGPROF signals to be delivered
114 // on the alternative signal stack by setting SA_ONSTACK. The stack itself
115 // is configured when interrupts are enabled for a particular thread.
116 // In reality Bionic's |pthread_create| eagerly creates and assigns an
117 // alternative signal stack for each thread. However older versions of Bionic
118 // (L and below) make the size of alternative stack too small which causes
119 // stack overflows and crashes.
120 struct sigaction act = {};
121 act.sa_sigaction = action;
122 sigemptyset(&act.sa_mask);
123 sigaddset(&act.sa_mask, SIGPROF); // Prevent nested signals.
124 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
125 int r = sigaction(SIGPROF, &act, nullptr);
126 ASSERT(r == 0);
127}
128
130 // Ignore future SIGPROF signals because by default SIGPROF will terminate
131 // the process and we may have some signals in flight.
132 struct sigaction act = {};
133 act.sa_handler = SIG_IGN;
134 sigemptyset(&act.sa_mask);
135 int r = sigaction(SIGPROF, &act, nullptr);
136 RELEASE_ASSERT(r == 0);
137}
138
139void* SignalHandler::PrepareCurrentThread() {
140 // These constants are selected to prevent allocating alternative signal
141 // stack if Bionic has already allocated large enough one for us. They
142 // match current values used in Bionic[1].
143 //
144 // [1]: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/pthread_internal.h;drc=3649db34a154cedb8ef53a5adbaa349970159b58;l=243
145 const intptr_t kGuardPageSize = 4 * KB;
146#if defined(TARGET_ARCH_IS_64_BIT)
147 const intptr_t kSigAltStackSize = 32 * KB;
148#else
149 const intptr_t kSigAltStackSize = 16 * KB;
150#endif
151
152 // First check if the alternative signal stack is already installed and
153 // large enough.
154 int r;
155 stack_t ss;
156 memset(&ss, 0, sizeof(ss));
157 r = sigaltstack(nullptr, &ss);
158 ASSERT(r == 0);
159 if (ss.ss_flags == 0 && ss.ss_size >= (kSigAltStackSize - kGuardPageSize)) {
160 // Bionic has created a large enough stack already.
161 return nullptr;
162 }
163
164 // We are running on an older version of Android, where Bionic creates
165 // stacks which are too small.
166 ss.ss_sp = malloc(kSigAltStackSize);
167 ss.ss_size = kSigAltStackSize;
168 ss.ss_flags = 0;
169 r = sigaltstack(&ss, nullptr);
170 ASSERT(r == 0);
171
172 return ss.ss_sp;
173}
174
175void SignalHandler::CleanupCurrentThreadState(void* stack) {
176 if (stack != nullptr) {
177 // Disable alternative stack then free allocated memory.
178 stack_t ss, old_ss;
179 memset(&ss, 0, sizeof(ss));
180 ss.ss_flags = SS_DISABLE;
181 int r = sigaltstack(&ss, &old_ss);
182 ASSERT(r == 0);
183 ASSERT(old_ss.ss_sp == stack);
184 free(stack);
185 }
186}
187
188} // namespace dart
189
190#endif // defined(DART_HOST_OS_ANDROID)
#define RELEASE_ASSERT(cond)
Definition: assert.h:327
static void Remove()
static uintptr_t GetDartStackPointer(const mcontext_t &mcontext)
static uintptr_t GetCStackPointer(const mcontext_t &mcontext)
static uintptr_t GetFramePointer(const mcontext_t &mcontext)
static uintptr_t GetProgramCounter(const mcontext_t &mcontext)
static void Install(SignalAction action)
static uintptr_t GetLinkRegister(const mcontext_t &mcontext)
#define ASSERT(E)
Definition: dart_vm.cc:33
void * malloc(size_t size)
Definition: allocation.cc:19
constexpr intptr_t KB
Definition: globals.h:528
void(* SignalAction)(int signal, siginfo_t *info, void *context)
const uint32_t fp
const Register SPREG