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
diff --git a/runtime/arch/arm/fault_handler_arm.cc b/runtime/arch/arm/fault_handler_arm.cc
new file mode 100644
index 0000000..c748ce9
--- /dev/null
+++ b/runtime/arch/arm/fault_handler_arm.cc
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+
+#include "fault_handler.h"
+#include <sys/ucontext.h>
+#include "base/macros.h"
+#include "globals.h"
+#include "base/logging.h"
+#include "base/hex_dump.h"
+#include "thread.h"
+#include "thread-inl.h"
+
+//
+// ARM specific fault handler functions.
+//
+
+namespace art {
+
+extern "C" void art_quick_throw_null_pointer_exception();
+extern "C" void art_quick_test_suspend();
+
+void FaultManager::GetMethodAndReturnPC(void* context, uintptr_t& method, uintptr_t& return_pc) {
+  struct ucontext *uc = (struct ucontext *)context;
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  uintptr_t* sp = reinterpret_cast<uint32_t*>(sc->arm_sp);
+  if (sp == nullptr) {
+    return;
+  }
+
+  // Work out the return PC.  This will be the address of the instruction
+  // following the faulting ldr/str instruction.  This is in thumb mode so
+  // the instruction might be a 16 or 32 bit one.  Also, the GC map always
+  // has the bottom bit of the PC set so we also need to set that.
+
+  // Need to work out the size of the instruction that caused the exception.
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(sc->arm_pc);
+
+  uint16_t instr = ptr[0] | ptr[1] << 8;
+  bool is_32bit = ((instr & 0xF000) == 0xF000) || ((instr & 0xF800) == 0xE800);
+  uint32_t instr_size = is_32bit ? 4 : 2;
+
+  // The method is at the top of the stack.
+  method = sp[0];
+
+  return_pc = (sc->arm_pc + instr_size) | 1;
+}
+
+bool NullPointerHandler::Action(int sig, siginfo_t* info, void* context) {
+  // The code that looks for the catch location needs to know the value of the
+  // ARM PC at the point of call.  For Null checks we insert a GC map that is immediately after
+  // the load/store instruction that might cause the fault.  However the mapping table has
+  // the low bits set for thumb mode so we need to set the bottom bit for the LR
+  // register in order to find the mapping.
+
+  // Need to work out the size of the instruction that caused the exception.
+  struct ucontext *uc = (struct ucontext *)context;
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  uint8_t* ptr = reinterpret_cast<uint8_t*>(sc->arm_pc);
+
+  uint16_t instr = ptr[0] | ptr[1] << 8;
+  bool is_32bit = ((instr & 0xF000) == 0xF000) || ((instr & 0xF800) == 0xE800);
+  uint32_t instr_size = is_32bit ? 4 : 2;
+  sc->arm_lr = (sc->arm_pc + instr_size) | 1;      // LR needs to point to gc map location
+  sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception);
+  LOG(DEBUG) << "Generating null pointer exception";
+  return true;
+}
+
+// A suspend check is done using the following instruction sequence:
+// 0xf723c0b2: f8d902c0  ldr.w   r0, [r9, #704]  ; suspend_trigger_
+// .. some intervening instruction
+// 0xf723c0b6: 6800      ldr     r0, [r0, #0]
+
+// The offset from r9 is Thread::ThreadSuspendTriggerOffset().
+// To check for a suspend check, we examine the instructions that caused
+// the fault (at PC-4 and PC).
+bool SuspensionHandler::Action(int sig, siginfo_t* info, void* context) {
+  // These are the instructions to check for.  The first one is the ldr r0,[r9,#xxx]
+  // where xxx is the offset of the suspend trigger.
+  uint32_t checkinst1 = 0xf8d90000 + Thread::ThreadSuspendTriggerOffset().Int32Value();
+  uint16_t checkinst2 = 0x6800;
+
+  struct ucontext *uc = (struct ucontext *)context;
+  struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext);
+  uint8_t* ptr2 = reinterpret_cast<uint8_t*>(sc->arm_pc);
+  uint8_t* ptr1 = ptr2 - 4;
+  LOG(DEBUG) << "checking suspend";
+
+  uint16_t inst2 = ptr2[0] | ptr2[1] << 8;
+  LOG(DEBUG) << "inst2: " << std::hex << inst2 << " checkinst2: " << checkinst2;
+  if (inst2 != checkinst2) {
+    // Second instruction is not good, not ours.
+    return false;
+  }
+
+  // The first instruction can a little bit up the stream due to load hoisting
+  // in the compiler.
+  uint8_t* limit = ptr1 - 40;   // Compiler will hoist to a max of 20 instructions.
+  bool found = false;
+  while (ptr1 > limit) {
+    uint32_t inst1 = ((ptr1[0] | ptr1[1] << 8) << 16) | (ptr1[2] | ptr1[3] << 8);
+    LOG(DEBUG) << "inst1: " << std::hex << inst1 << " checkinst1: " << checkinst1;
+    if (inst1 == checkinst1) {
+      found = true;
+      break;
+    }
+    ptr1 -= 2;      // Min instruction size is 2 bytes.
+  }
+  if (found) {
+    LOG(DEBUG) << "suspend check match";
+    // This is a suspend check.  Arrange for the signal handler to return to
+    // art_quick_test_suspend.  Also set LR so that after the suspend check it
+    // will resume the instruction (current PC + 2).  PC points to the
+    // ldr r0,[r0,#0] instruction (r0 will be 0, set by the trigger).
+
+    // NB: remember that we need to set the bottom bit of the LR register
+    // to switch to thumb mode.
+    LOG(DEBUG) << "arm lr: " << std::hex << sc->arm_lr;
+    LOG(DEBUG) << "arm pc: " << std::hex << sc->arm_pc;
+    sc->arm_lr = sc->arm_pc + 3;      // +2 + 1 (for thumb)
+    sc->arm_pc = reinterpret_cast<uintptr_t>(art_quick_test_suspend);
+
+    // Now remove the suspend trigger that caused this fault.
+    Thread::Current()->RemoveSuspendTrigger();
+    LOG(DEBUG) << "removed suspend trigger invoking test suspend";
+    return true;
+  }
+  return false;
+}
+
+bool StackOverflowHandler::Action(int sig, siginfo_t* info, void* context) {
+  return false;
+}
+}       // namespace art