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
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#else
25#error Unsupported architecture.
26#endif // HOST_ARCH_...
27 return pc;
28}
29
30uintptr_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
55uintptr_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
72uintptr_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
80uintptr_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
97void 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
122void 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