diff options
author | Dave Allison <dallison@google.com> | 2014-02-20 16:06:36 -0800 |
---|---|---|
committer | Dave Allison <dallison@google.com> | 2014-03-13 12:21:15 -0700 |
commit | b373e091eac39b1a79c11f2dcbd610af01e9e8a9 (patch) | |
tree | 034d820c4829e0dcf6161473cc39f7250123bfaa /runtime/fault_handler.h | |
parent | 9545a446e99b22248099fe66f5f9431530c20851 (diff) | |
download | art-b373e091eac39b1a79c11f2dcbd610af01e9e8a9.zip art-b373e091eac39b1a79c11f2dcbd610af01e9e8a9.tar.gz art-b373e091eac39b1a79c11f2dcbd610af01e9e8a9.tar.bz2 |
Implicit null/suspend checks (oat version bump)
This adds the ability to use SEGV signals
to throw NullPointerException exceptions from Java code rather
than having the compiler generate explicit comparisons and
branches. It does this by using sigaction to trap SIGSEGV and when triggered
makes sure it's in compiled code and if so, sets the return
address to the entry point to throw the exception.
It also uses this signal mechanism to determine whether to check
for thread suspension. Instead of the compiler generating calls
to a function to check for threads being suspended, the compiler
will now load indirect via an address in the TLS area. To trigger
a suspend, the contents of this address are changed from something
valid to 0. A SIGSEGV will occur and the handler will check
for a valid instruction pattern before invoking the thread
suspension check code.
If a user program taps SIGSEGV it will prevent our signal handler
working. This will cause a failure in the runtime.
There are two signal handlers at present. You can control them
individually using the flags -implicit-checks: on the runtime
command line. This takes a string parameter, a comma
separated set of strings. Each can be one of:
none switch off
null null pointer checks
suspend suspend checks
all all checks
So to switch only suspend checks on, pass:
-implicit-checks:suspend
There is also -explicit-checks to provide the reverse once
we change the default.
For dalvikvm, pass --runtime-arg -implicit-checks:foo,bar
The default is -implicit-checks:none
There is also a property 'dalvik.vm.implicit_checks' whose value is the same
string as the command option. The default is 'none'. For example to switch on
null checks using the option:
setprop dalvik.vm.implicit_checks null
It only works for ARM right now.
Bumps OAT version number due to change to Thread offsets.
Bug: 13121132
Change-Id: If743849138162f3c7c44a523247e413785677370
Diffstat (limited to 'runtime/fault_handler.h')
-rw-r--r-- | runtime/fault_handler.h | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h new file mode 100644 index 0000000..9fe6e9a --- /dev/null +++ b/runtime/fault_handler.h @@ -0,0 +1,91 @@ +/* + * 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 FaultHandler; + +class FaultManager { + public: + FaultManager(); + ~FaultManager(); + + void Init(); + + void HandleFault(int sig, siginfo_t* info, void* context); + void AddHandler(FaultHandler* handler); + void RemoveHandler(FaultHandler* handler); + + private: + bool IsInGeneratedCode(void *context) NO_THREAD_SAFETY_ANALYSIS; + void GetMethodAndReturnPC(void* context, uintptr_t& method, uintptr_t& return_pc); + + typedef std::vector<FaultHandler*> Handlers; + Handlers handlers_; + struct sigaction oldaction_; +}; + +class FaultHandler { + public: + FaultHandler() : manager_(nullptr) {} + explicit FaultHandler(FaultManager* manager) : manager_(manager) {} + virtual ~FaultHandler() {} + + virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0; + protected: + FaultManager* const manager_; +}; + +class NullPointerHandler FINAL : public FaultHandler { + public: + NullPointerHandler() {} + explicit NullPointerHandler(FaultManager* manager); + + bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE; +}; + +class SuspensionHandler FINAL : public FaultHandler { + public: + SuspensionHandler() {} + explicit SuspensionHandler(FaultManager* manager); + + bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE; +}; + +class StackOverflowHandler FINAL : public FaultHandler { + public: + StackOverflowHandler() {} + explicit StackOverflowHandler(FaultManager* manager); + + bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE; +}; + +// Statically allocated so the the signal handler can get access to it. +extern FaultManager fault_manager; + +} // namespace art +#endif // ART_RUNTIME_FAULT_HANDLER_H_ + |