OSDN Git Service

Check that we don't accidentally invoke compiled code when -Xint.
authorHiroshi Yamauchi <yamauchi@google.com>
Sat, 16 Aug 2014 00:11:12 +0000 (17:11 -0700)
committerHiroshi Yamauchi <yamauchi@google.com>
Mon, 18 Aug 2014 18:25:13 +0000 (11:25 -0700)
The heap poisoning breakge (b/17018234) would have been detected with
this check.

Bug: 17018234
Change-Id: If4827ea1b02396d41012f0955e55c887387a0565

runtime/class_linker.cc
runtime/class_linker.h
runtime/mirror/art_method.cc
runtime/mirror/art_method.h

index 3ab4ef8..f31e273 100644 (file)
@@ -2167,6 +2167,24 @@ const void* ClassLinker::GetPortableOatCodeFor(mirror::ArtMethod* method,
   return result;
 }
 
+const void* ClassLinker::GetOatMethodQuickCodeFor(mirror::ArtMethod* method) {
+  if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) {
+    return nullptr;
+  }
+  bool found;
+  OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
+  return found ? oat_method.GetQuickCode() : nullptr;
+}
+
+const void* ClassLinker::GetOatMethodPortableCodeFor(mirror::ArtMethod* method) {
+  if (method->IsNative() || method->IsAbstract() || method->IsProxyMethod()) {
+    return nullptr;
+  }
+  bool found;
+  OatFile::OatMethod oat_method = FindOatMethodFor(method, &found);
+  return found ? oat_method.GetPortableCode() : nullptr;
+}
+
 const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx,
                                             uint32_t method_idx) {
   bool found;
index d2c9b40..9ae3862 100644 (file)
@@ -344,6 +344,14 @@ class ClassLinker {
   const void* GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Get compiled code for a method, return null if no code
+  // exists. This is unlike Get..OatCodeFor which will return a bridge
+  // or interpreter entrypoint.
+  const void* GetOatMethodQuickCodeFor(mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  const void* GetOatMethodPortableCodeFor(mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   pid_t GetClassesLockOwner();  // For SignalCatcher.
   pid_t GetDexLockOwner();  // For SignalCatcher.
 
index 370bfb9..131f5d6 100644 (file)
@@ -281,6 +281,19 @@ uint32_t ArtMethod::FindCatchBlock(Handle<ArtMethod> h_this, Handle<Class> excep
   return found_dex_pc;
 }
 
+bool ArtMethod::IsEntrypointInterpreter() {
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const void* oat_quick_code = class_linker->GetOatMethodQuickCodeFor(this);
+  const void* oat_portable_code = class_linker->GetOatMethodPortableCodeFor(this);
+  if (!IsPortableCompiled()) {  // Quick.
+    return oat_quick_code == nullptr ||
+        oat_quick_code != GetEntryPointFromQuickCompiledCode();
+  } else {  // Portable.
+    return oat_portable_code == nullptr ||
+        oat_portable_code != GetEntryPointFromPortableCompiledCode();
+  }
+}
+
 void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result,
                        const char* shorty) {
   if (UNLIKELY(__builtin_frame_address(0) < self->GetStackEnd())) {
@@ -318,6 +331,13 @@ void ArtMethod::Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue*
                                   have_quick_code ? GetEntryPointFromQuickCompiledCode()
                                                   : GetEntryPointFromPortableCompiledCode());
       }
+
+      // Ensure that we won't be accidentally calling quick/portable compiled code when -Xint.
+      if (kIsDebugBuild && Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly()) {
+        CHECK(IsEntrypointInterpreter())
+            << "Don't call compiled code when -Xint " << PrettyMethod(this);
+      }
+
       if (!IsPortableCompiled()) {
 #ifdef __LP64__
         if (!IsStatic()) {
index fa592c2..ebd5bd5 100644 (file)
@@ -309,6 +309,11 @@ class MANAGED ArtMethod FINAL : public Object {
 
   void AssertPcIsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // Returns true if the entrypoint points to the interpreter, as
+  // opposed to the compiled code, that is, this method will be
+  // interpretered on invocation.
+  bool IsEntrypointInterpreter() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   uint32_t GetQuickOatCodeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   uint32_t GetPortableOatCodeOffset() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   void SetQuickOatCodeOffset(uint32_t code_offset) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);