• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_RUNTIME_SIGNAL_HANDLER_H
17 #define PANDA_RUNTIME_SIGNAL_HANDLER_H
18 
19 #include <csignal>
20 #include <cstdint>
21 #include <iostream>
22 #include <vector>
23 #include <libpandabase/macros.h>
24 #include "runtime/include/mem/panda_containers.h"
25 #include "libpandabase/os/sighook.h"
26 
27 namespace ark {
28 
29 class Method;
30 class SignalHandler;
31 
32 bool IsInvalidPointer(uintptr_t addr);
33 bool InAllocatedCodeRange(uintptr_t pc);
34 
35 #ifdef PANDA_TARGET_ARM32
36 #define CONTEXT_PC uc_->uc_mcontext.arm_pc  // NOLINT(cppcoreguidelines-macro-usage)
37 #define CONTEXT_SP uc_->uc_mcontext.arm_sp  // NOLINT(cppcoreguidelines-macro-usage)
38 #define CONTEXT_FP uc_->uc_mcontext.arm_fp  // NOLINT(cppcoreguidelines-macro-usage)
39 #define CONTEXT_LR uc_->uc_mcontext.arm_lr  // NOLINT(cppcoreguidelines-macro-usage)
40 #elif defined(PANDA_TARGET_ARM64)
41 #ifdef __APPLE__
42 #define CONTEXT_PC uc_->uc_mcontext->__ss.__pc  // NOLINT(cppcoreguidelines-macro-usage)
43 #define CONTEXT_FP uc_->uc_mcontext->__ss.__fp  // NOLINT(cppcoreguidelines-macro-usage)
44 #define CONTEXT_LR uc_->uc_mcontext->__ss.__lr  // NOLINT(cppcoreguidelines-macro-usage)
45 #else
46 #define CONTEXT_PC uc_->uc_mcontext.pc        // NOLINT(cppcoreguidelines-macro-usage)
47 #define CONTEXT_FP uc_->uc_mcontext.regs[29]  // NOLINT(cppcoreguidelines-macro-usage)
48 #define CONTEXT_LR uc_->uc_mcontext.regs[30]  // NOLINT(cppcoreguidelines-macro-usage)
49 #endif
50 #elif defined(PANDA_TARGET_AMD64)
51 #ifdef __APPLE__
52 #define CONTEXT_PC uc_->uc_mcontext->__ss.__rip  // NOLINT(cppcoreguidelines-macro-usage)
53 #define CONTEXT_SP uc_->uc_mcontext->__ss.__rsp  // NOLINT(cppcoreguidelines-macro-usage)
54 #define CONTEXT_FP uc_->uc_mcontext->__ss.__rbp  // NOLINT(cppcoreguidelines-macro-usage)
55 #else
56 #define CONTEXT_PC uc_->uc_mcontext.gregs[REG_RIP]  // NOLINT(cppcoreguidelines-macro-usage)
57 #define CONTEXT_SP uc_->uc_mcontext.gregs[REG_RSP]  // NOLINT(cppcoreguidelines-macro-usage)
58 #define CONTEXT_FP uc_->uc_mcontext.gregs[REG_RBP]  // NOLINT(cppcoreguidelines-macro-usage)
59 #endif
60 #elif defined(PANDA_TARGET_X86)
61 #define CONTEXT_PC uc_->uc_mcontext.gregs[REG_EIP]  // NOLINT(cppcoreguidelines-macro-usage)
62 #define CONTEXT_SP uc_->uc_mcontext.gregs[REG_ESP]  // NOLINT(cppcoreguidelines-macro-usage)
63 #define CONTEXT_FP uc_->uc_mcontext.gregs[REG_EBP]  // NOLINT(cppcoreguidelines-macro-usage)
64 #endif
65 
66 class SignalContext {
67 public:
SignalContext(void * ucontextRaw)68     explicit SignalContext(void *ucontextRaw)
69     {
70         uc_ = reinterpret_cast<ucontext_t *>(ucontextRaw);
71     }
GetPC()72     uintptr_t GetPC()
73     {
74         return CONTEXT_PC;
75     }
SetPC(uintptr_t pc)76     void SetPC(uintptr_t pc)
77     {
78         CONTEXT_PC = pc;
79     }
GetSP()80     uintptr_t GetSP()
81     {
82 #if defined(PANDA_TARGET_ARM64)
83 #ifdef __APPLE__
84         return uc_->uc_mcontext->__ss.__sp;
85 #else
86         auto sc = reinterpret_cast<struct sigcontext *>(&uc_->uc_mcontext);
87         return sc->sp;
88 #endif
89 #else
90         return CONTEXT_SP;
91 #endif
92     }
GetFP()93     uintptr_t *GetFP()
94     {
95         return reinterpret_cast<uintptr_t *>(CONTEXT_FP);
96     }
97 #if (defined(PANDA_TARGET_ARM64) || defined(PANDA_TARGET_ARM32))
GetLR()98     uintptr_t GetLR()
99     {
100         return CONTEXT_LR;
101     }
SetLR(uintptr_t lr)102     void SetLR(uintptr_t lr)
103     {
104         CONTEXT_LR = lr;
105     }
106 #elif defined(PANDA_TARGET_AMD64)
SetSP(uintptr_t sp)107     void SetSP(uintptr_t sp)
108     {
109         CONTEXT_SP = sp;
110     }
111 
112 #endif
113 
114 private:
115     ucontext_t *uc_;
116 };
117 
118 class SignalManager {
119 public:
120     void InitSignals();
121 
IsInitialized()122     bool IsInitialized()
123     {
124         return isInit_;
125     }
126 
127     bool SignalActionHandler(int sig, siginfo_t *info, void *context);
128     bool InCompiledCode(const siginfo_t *siginfo, const void *context, bool checkBytecodePc) const;
129     void AddHandler(SignalHandler *handler, bool oatCode);
130 
131     void RemoveHandler(SignalHandler *handler);
132     void GetMethodAndReturnPcAndSp(const siginfo_t *siginfo, const void *context, const Method **outMethod,
133                                    const uintptr_t *outReturnPc, const uintptr_t *outSp);
134 
GetAllocator()135     mem::InternalAllocatorPtr GetAllocator()
136     {
137         return allocator_;
138     }
139 
140     void DeleteHandlersArray();
141 
SignalManager(mem::InternalAllocatorPtr allocator)142     explicit SignalManager(mem::InternalAllocatorPtr allocator) : allocator_(allocator) {}
143     SignalManager(SignalManager &&) = delete;
144     SignalManager &operator=(SignalManager &&) = delete;
145     virtual ~SignalManager() = default;
146 
147 private:
148     bool isInit_ {false};
149     mem::InternalAllocatorPtr allocator_;
150     PandaVector<SignalHandler *> compiledCodeHandler_;
151     PandaVector<SignalHandler *> otherHandlers_;
152     NO_COPY_SEMANTIC(SignalManager);
153 };
154 
155 class SignalHandler {
156 public:
157     SignalHandler() = default;
158 
159     virtual bool Action(int sig, siginfo_t *siginfo, void *context) = 0;
160 
161     SignalHandler(SignalHandler &&) = delete;
162     SignalHandler &operator=(SignalHandler &&) = delete;
163     virtual ~SignalHandler() = default;
164 
165 private:
166     NO_COPY_SEMANTIC(SignalHandler);
167 };
168 
169 class NullPointerHandler final : public SignalHandler {
170 public:
171     NullPointerHandler() = default;
172 
173     bool Action(int sig, siginfo_t *siginfo, void *context) override;
174 
175     NullPointerHandler(NullPointerHandler &&) = delete;
176     NullPointerHandler &operator=(NullPointerHandler &&) = delete;
177     ~NullPointerHandler() override;
178 
179 private:
180     NO_COPY_SEMANTIC(NullPointerHandler);
181 };
182 
183 class StackOverflowHandler final : public SignalHandler {
184 public:
185     StackOverflowHandler() = default;
186     ~StackOverflowHandler() override = default;
187 
188     NO_COPY_SEMANTIC(StackOverflowHandler);
189     NO_MOVE_SEMANTIC(StackOverflowHandler);
190 
191     bool Action(int sig, siginfo_t *siginfo, void *context) override;
192 };
193 
194 class SamplingProfilerHandler final : public SignalHandler {
195 public:
196     SamplingProfilerHandler() = default;
197     ~SamplingProfilerHandler() override = default;
198 
199     NO_COPY_SEMANTIC(SamplingProfilerHandler);
200     NO_MOVE_SEMANTIC(SamplingProfilerHandler);
201 
202     bool Action(int sig, siginfo_t *siginfo, void *context) override;
203 };
204 
205 class CrashFallbackDumpHandler final : public SignalHandler {
206 public:
207     CrashFallbackDumpHandler() = default;
208     ~CrashFallbackDumpHandler() override = default;
209 
210     NO_COPY_SEMANTIC(CrashFallbackDumpHandler);
211     NO_MOVE_SEMANTIC(CrashFallbackDumpHandler);
212 
213     bool Action(int sig, siginfo_t *siginfo, void *context) override;
214 };
215 
216 }  // namespace ark
217 
218 #endif  // PANDA_RUNTIME_SIGNAL_HANDLER_H
219