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 <vector>
25 
26 #include "base/locks.h"  // For annotalysis.
27 #include "runtime_globals.h"  // For CanDoImplicitNullCheckOn.
28 
29 namespace art {
30 
31 class ArtMethod;
32 class FaultHandler;
33 
34 class FaultManager {
35  public:
36   FaultManager();
37   ~FaultManager();
38 
39   void Init();
40 
41   // Unclaim signals.
42   void Release();
43 
44   // Unclaim signals and delete registered handlers.
45   void Shutdown();
46 
47   // Try to handle a fault, returns true if successful.
48   bool HandleFault(int sig, siginfo_t* info, void* context);
49 
50   // Added handlers are owned by the fault handler and will be freed on Shutdown().
51   void AddHandler(FaultHandler* handler, bool generated_code);
52   void RemoveHandler(FaultHandler* handler);
53 
54   // Note that the following two functions are called in the context of a signal handler.
55   // The IsInGeneratedCode() function checks that the mutator lock is held before it
56   // calls GetMethodAndReturnPCAndSP().
57   // TODO: think about adding lock assertions and fake lock and unlock functions.
58   void GetMethodAndReturnPcAndSp(siginfo_t* siginfo,
59                                  void* context,
60                                  ArtMethod** out_method,
61                                  uintptr_t* out_return_pc,
62                                  uintptr_t* out_sp,
63                                  bool* out_is_stack_overflow)
64                                  NO_THREAD_SAFETY_ANALYSIS;
65   bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc)
66                          NO_THREAD_SAFETY_ANALYSIS;
67 
68  private:
69   // The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code.
70   bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context)
71                                   NO_THREAD_SAFETY_ANALYSIS;
72 
73   std::vector<FaultHandler*> generated_code_handlers_;
74   std::vector<FaultHandler*> other_handlers_;
75   struct sigaction oldaction_;
76   bool initialized_;
77   DISALLOW_COPY_AND_ASSIGN(FaultManager);
78 };
79 
80 class FaultHandler {
81  public:
82   explicit FaultHandler(FaultManager* manager);
~FaultHandler()83   virtual ~FaultHandler() {}
GetFaultManager()84   FaultManager* GetFaultManager() {
85     return manager_;
86   }
87 
88   virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0;
89 
90  protected:
91   FaultManager* const manager_;
92 
93  private:
94   DISALLOW_COPY_AND_ASSIGN(FaultHandler);
95 };
96 
97 class NullPointerHandler final : public FaultHandler {
98  public:
99   explicit NullPointerHandler(FaultManager* manager);
100 
101   bool Action(int sig, siginfo_t* siginfo, void* context) override;
102 
IsValidImplicitCheck(siginfo_t * siginfo)103   static bool IsValidImplicitCheck(siginfo_t* siginfo) {
104     // Our implicit NPE checks always limit the range to a page.
105     // Note that the runtime will do more exhaustive checks (that we cannot
106     // reasonably do in signal processing code) based on the dex instruction
107     // faulting.
108     return CanDoImplicitNullCheckOn(reinterpret_cast<uintptr_t>(siginfo->si_addr));
109   }
110 
111  private:
112   DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);
113 };
114 
115 class SuspensionHandler final : public FaultHandler {
116  public:
117   explicit SuspensionHandler(FaultManager* manager);
118 
119   bool Action(int sig, siginfo_t* siginfo, void* context) override;
120 
121  private:
122   DISALLOW_COPY_AND_ASSIGN(SuspensionHandler);
123 };
124 
125 class StackOverflowHandler final : public FaultHandler {
126  public:
127   explicit StackOverflowHandler(FaultManager* manager);
128 
129   bool Action(int sig, siginfo_t* siginfo, void* context) override;
130 
131  private:
132   DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);
133 };
134 
135 class JavaStackTraceHandler final : public FaultHandler {
136  public:
137   explicit JavaStackTraceHandler(FaultManager* manager);
138 
139   bool Action(int sig, siginfo_t* siginfo, void* context) override NO_THREAD_SAFETY_ANALYSIS;
140 
141  private:
142   DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler);
143 };
144 
145 // Statically allocated so the the signal handler can Get access to it.
146 extern FaultManager fault_manager;
147 
148 }       // namespace art
149 #endif  // ART_RUNTIME_FAULT_HANDLER_H_
150 
151