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