• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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