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
105void SignalHandler::Install(SignalAction action) {
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 are using alternative signal stack
114 // to handle SIGPROF signals.
115 stack_t ss;
116 ss.ss_size = SIGSTKSZ;
117 ss.ss_sp = malloc(ss.ss_size);
118 ss.ss_flags = 0;
119 int r = sigaltstack(&ss, nullptr);
120 ASSERT(r == 0);
121
122 struct sigaction act = {};
123 act.sa_sigaction = action;
124 sigemptyset(&act.sa_mask);
125 sigaddset(&act.sa_mask, SIGPROF); // Prevent nested signals.
126 act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
127 r = sigaction(SIGPROF, &act, nullptr);
128 ASSERT(r == 0);
129}
130
131void SignalHandler::Remove() {
132 // Ignore future SIGPROF signals because by default SIGPROF will terminate
133 // the process and we may have some signals in flight.
134 struct sigaction act = {};
135 act.sa_handler = SIG_IGN;
136 sigemptyset(&act.sa_mask);
137 int r = sigaction(SIGPROF, &act, nullptr);
138 ASSERT(r == 0);
139
140 // Disable and delete alternative signal stack.
141 stack_t ss, old_ss;
142 ss.ss_flags = SS_DISABLE;
143 r = sigaltstack(&ss, &old_ss);
144 ASSERT(r == 0);
145 free(old_ss.ss_sp);
146}
147
148} // namespace dart
149
150#endif // defined(DART_HOST_OS_ANDROID)
151

source code of dart_sdk/runtime/vm/signal_handler_android.cc