1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 #ifndef ART_RUNTIME_FAULT_HANDLER_H_ 19 #define ART_RUNTIME_FAULT_HANDLER_H_ 20 21 #include <signal.h> 22 #include <stdint.h> 23 24 #include <atomic> 25 #include <vector> 26 27 #include "base/locks.h" // For annotalysis. 28 #include "base/mutex.h" 29 #include "runtime_globals.h" // For CanDoImplicitNullCheckOn. 30 31 namespace art { 32 33 class ArtMethod; 34 class FaultHandler; 35 36 class FaultManager { 37 public: 38 FaultManager(); 39 ~FaultManager(); 40 41 // Use libsigchain if use_sig_chain is true. Otherwise, setup SIGBUS directly 42 // using sigaction(). 43 void Init(bool use_sig_chain); 44 45 // Unclaim signals. 46 void Release(); 47 48 // Unclaim signals and delete registered handlers. 49 void Shutdown(); 50 51 // Try to handle a SIGSEGV fault, returns true if successful. 52 bool HandleSigsegvFault(int sig, siginfo_t* info, void* context); 53 54 // Try to handle a SIGBUS fault, returns true if successful. 55 bool HandleSigbusFault(int sig, siginfo_t* info, void* context); 56 57 // Added handlers are owned by the fault handler and will be freed on Shutdown(). 58 void AddHandler(FaultHandler* handler, bool generated_code); 59 void RemoveHandler(FaultHandler* handler); 60 61 void AddGeneratedCodeRange(const void* start, size_t size); 62 void RemoveGeneratedCodeRange(const void* start, size_t size) 63 REQUIRES_SHARED(Locks::mutator_lock_); 64 65 // Retrieves fault PC from architecture-dependent `context`, returns 0 on failure. 66 // Called in the context of a signal handler. 67 static uintptr_t GetFaultPc(siginfo_t* siginfo, void* context); 68 69 // Retrieves SP from architecture-dependent `context`. 70 // Called in the context of a signal handler. 71 static uintptr_t GetFaultSp(void* context); 72 73 // Checks if the fault happened while running generated code. 74 // Called in the context of a signal handler. 75 bool IsInGeneratedCode(siginfo_t* siginfo, void *context) NO_THREAD_SAFETY_ANALYSIS; 76 77 private: 78 struct GeneratedCodeRange { 79 std::atomic<GeneratedCodeRange*> next; 80 const void* start; 81 size_t size; 82 }; 83 84 GeneratedCodeRange* CreateGeneratedCodeRange(const void* start, size_t size) 85 REQUIRES(generated_code_ranges_lock_); 86 void FreeGeneratedCodeRange(GeneratedCodeRange* range) REQUIRES(!generated_code_ranges_lock_); 87 88 // The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code. 89 bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context) 90 NO_THREAD_SAFETY_ANALYSIS; 91 92 // Note: The lock guards modifications of the ranges but the function `IsInGeneratedCode()` 93 // walks the list in the context of a signal handler without holding the lock. 94 Mutex generated_code_ranges_lock_; 95 std::atomic<GeneratedCodeRange*> generated_code_ranges_ GUARDED_BY(generated_code_ranges_lock_); 96 97 std::vector<FaultHandler*> generated_code_handlers_; 98 std::vector<FaultHandler*> other_handlers_; 99 bool initialized_; 100 101 // We keep a certain number of generated code ranges locally to avoid too many 102 // cache misses while traversing the singly-linked list `generated_code_ranges_`. 103 // 16 should be enough for the boot image (assuming `--multi-image`; there is 104 // only one entry for `--single-image`), nterp, JIT code cache and a few other 105 // entries for the app or system server. 106 static constexpr size_t kNumLocalGeneratedCodeRanges = 16; 107 GeneratedCodeRange generated_code_ranges_storage_[kNumLocalGeneratedCodeRanges]; 108 GeneratedCodeRange* free_generated_code_ranges_ 109 GUARDED_BY(generated_code_ranges_lock_); 110 111 DISALLOW_COPY_AND_ASSIGN(FaultManager); 112 }; 113 114 class FaultHandler { 115 public: 116 explicit FaultHandler(FaultManager* manager); ~FaultHandler()117 virtual ~FaultHandler() {} GetFaultManager()118 FaultManager* GetFaultManager() { 119 return manager_; 120 } 121 122 virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0; 123 124 protected: 125 FaultManager* const manager_; 126 127 private: 128 DISALLOW_COPY_AND_ASSIGN(FaultHandler); 129 }; 130 131 class NullPointerHandler final : public FaultHandler { 132 public: 133 explicit NullPointerHandler(FaultManager* manager); 134 135 // NO_THREAD_SAFETY_ANALYSIS: Called after the fault manager determined that 136 // the thread is `Runnable` and holds the mutator lock (shared) but without 137 // telling annotalysis that we actually hold the lock. 138 bool Action(int sig, siginfo_t* siginfo, void* context) override 139 NO_THREAD_SAFETY_ANALYSIS; 140 141 private: 142 // Helper functions for checking whether the signal can be interpreted 143 // as implicit NPE check. Note that the runtime will do more exhaustive 144 // checks (that we cannot reasonably do in signal processing code) based 145 // on the dex instruction faulting. 146 IsValidFaultAddress(uintptr_t fault_address)147 static bool IsValidFaultAddress(uintptr_t fault_address) { 148 // Our implicit NPE checks always limit the range to a page. 149 return CanDoImplicitNullCheckOn(fault_address); 150 } 151 152 static bool IsValidMethod(ArtMethod* method) 153 REQUIRES_SHARED(Locks::mutator_lock_); 154 155 static bool IsValidReturnPc(ArtMethod** sp, uintptr_t return_pc) 156 REQUIRES_SHARED(Locks::mutator_lock_); 157 158 DISALLOW_COPY_AND_ASSIGN(NullPointerHandler); 159 }; 160 161 class SuspensionHandler final : public FaultHandler { 162 public: 163 explicit SuspensionHandler(FaultManager* manager); 164 165 bool Action(int sig, siginfo_t* siginfo, void* context) override; 166 167 private: 168 DISALLOW_COPY_AND_ASSIGN(SuspensionHandler); 169 }; 170 171 class StackOverflowHandler final : public FaultHandler { 172 public: 173 explicit StackOverflowHandler(FaultManager* manager); 174 175 bool Action(int sig, siginfo_t* siginfo, void* context) override; 176 177 private: 178 DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler); 179 }; 180 181 class JavaStackTraceHandler final : public FaultHandler { 182 public: 183 explicit JavaStackTraceHandler(FaultManager* manager); 184 185 bool Action(int sig, siginfo_t* siginfo, void* context) override NO_THREAD_SAFETY_ANALYSIS; 186 187 private: 188 DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler); 189 }; 190 191 // Statically allocated so the the signal handler can Get access to it. 192 extern FaultManager fault_manager; 193 194 } // namespace art 195 #endif // ART_RUNTIME_FAULT_HANDLER_H_ 196 197