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