1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ART_RUNTIME_FAULT_HANDLER_H_
#define ART_RUNTIME_FAULT_HANDLER_H_
#include <signal.h>
#include <vector>
#include <setjmp.h>
#include <stdint.h>
#include "base/mutex.h" // For annotalysis.
namespace art {
class ArtMethod;
class FaultHandler;
class FaultManager {
public:
FaultManager();
~FaultManager();
void Init();
// Unclaim signals.
void Release();
// Unclaim signals and delete registered handlers.
void Shutdown();
// Try to handle a fault, returns true if successful.
bool HandleFault(int sig, siginfo_t* info, void* context);
// Added handlers are owned by the fault handler and will be freed on Shutdown().
void AddHandler(FaultHandler* handler, bool generated_code);
void RemoveHandler(FaultHandler* handler);
// Note that the following two functions are called in the context of a signal handler.
// The IsInGeneratedCode() function checks that the mutator lock is held before it
// calls GetMethodAndReturnPCAndSP().
// TODO: think about adding lock assertions and fake lock and unlock functions.
void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, ArtMethod** out_method,
uintptr_t* out_return_pc, uintptr_t* out_sp)
NO_THREAD_SAFETY_ANALYSIS;
bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc)
NO_THREAD_SAFETY_ANALYSIS;
private:
// The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code.
bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context)
NO_THREAD_SAFETY_ANALYSIS;
std::vector<FaultHandler*> generated_code_handlers_;
std::vector<FaultHandler*> other_handlers_;
struct sigaction oldaction_;
bool initialized_;
DISALLOW_COPY_AND_ASSIGN(FaultManager);
};
class FaultHandler {
public:
explicit FaultHandler(FaultManager* manager);
virtual ~FaultHandler() {}
FaultManager* GetFaultManager() {
return manager_;
}
virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0;
protected:
FaultManager* const manager_;
private:
DISALLOW_COPY_AND_ASSIGN(FaultHandler);
};
class NullPointerHandler FINAL : public FaultHandler {
public:
explicit NullPointerHandler(FaultManager* manager);
bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;
static bool IsValidImplicitCheck(siginfo_t* siginfo) {
// Our implicit NPE checks always limit the range to a page.
// Note that the runtime will do more exhaustive checks (that we cannot
// reasonably do in signal processing code) based on the dex instruction
// faulting.
return CanDoImplicitNullCheckOn(reinterpret_cast<uintptr_t>(siginfo->si_addr));
}
private:
DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);
};
class SuspensionHandler FINAL : public FaultHandler {
public:
explicit SuspensionHandler(FaultManager* manager);
bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(SuspensionHandler);
};
class StackOverflowHandler FINAL : public FaultHandler {
public:
explicit StackOverflowHandler(FaultManager* manager);
bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);
};
class JavaStackTraceHandler FINAL : public FaultHandler {
public:
explicit JavaStackTraceHandler(FaultManager* manager);
bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE NO_THREAD_SAFETY_ANALYSIS;
private:
DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler);
};
// Statically allocated so the the signal handler can Get access to it.
extern FaultManager fault_manager;
} // namespace art
#endif // ART_RUNTIME_FAULT_HANDLER_H_
|