Setup AbstractMethodError and dlsym stub when loading from oat

Change-Id: Ie97fa6eb3cfb7d0c6224aa6914f28a7b137ae056
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 6dfbf99..8e23112 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -77,10 +77,10 @@
 $(eval $(call declare-test-test-target,Invoke,))
 $(eval $(call declare-test-test-target,ExceptionTest,))
 $(eval $(call declare-test-test-target,SystemMethods,))
-# TODO: Re-enable the test when System.LoadLibrary is working.
+$(eval $(call declare-test-test-target,MemUsage,))
+
+# TODO: Enable when the StackWalk tests are passing
 # $(eval $(call declare-test-test-target,StackWalk,))
 # $(eval $(call declare-test-test-target,StackWalk2,))
 
- $(eval $(call declare-test-test-target,MemUsage,))
-
 ########################################################################
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3f30b9e..f6cf291 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -982,6 +982,23 @@
   return size;
 }
 
+void LinkCode(Method* method, const OatFile::OatClass* oat_class, uint32_t method_index) {
+  // Every kind of method should at least get an invoke stub from the oat_method.
+  // non-abstract methods also get their code pointers.
+  const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
+  oat_method.LinkMethod(method);
+
+  if (method->IsAbstract()) {
+    method->SetCode(Runtime::Current()->GetAbstractMethodErrorStubArray()->GetData());
+    return;
+  }
+  if (method->IsNative()) {
+    // unregistering restores the dlsym lookup stub
+    method->UnregisterNative();
+    return;
+  }
+}
+
 void ClassLinker::LoadClass(const DexFile& dex_file,
                             const DexFile::ClassDef& dex_class_def,
                             Class* klass,
@@ -1060,6 +1077,7 @@
         bool found = dex_file.FindClassDefIndex(descriptor, class_def_index);
         CHECK(found) << descriptor;
         oat_class.reset(oat_dex_file->GetOatClass(class_def_index));
+        CHECK(oat_class.get() != NULL) << descriptor;
       }
     }
   }
@@ -1073,12 +1091,11 @@
     for (size_t i = 0; i < num_direct_methods; ++i, ++method_index) {
       DexFile::Method dex_method;
       dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-      Method* meth = AllocMethod();
-      klass->SetDirectMethod(i, meth);
-      LoadMethod(dex_file, dex_method, klass, meth);
+      Method* method = AllocMethod();
+      klass->SetDirectMethod(i, method);
+      LoadMethod(dex_file, dex_method, klass, method);
       if (oat_class.get() != NULL) {
-        const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-        oat_method.LinkMethod(meth);
+        LinkCode(method, oat_class.get(), method_index);
       }
     }
   }
@@ -1091,12 +1108,11 @@
     for (size_t i = 0; i < num_virtual_methods; ++i, ++method_index) {
       DexFile::Method dex_method;
       dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-      Method* meth = AllocMethod();
-      klass->SetVirtualMethod(i, meth);
-      LoadMethod(dex_file, dex_method, klass, meth);
+      Method* method = AllocMethod();
+      klass->SetVirtualMethod(i, method);
+      LoadMethod(dex_file, dex_method, klass, method);
       if (oat_class.get() != NULL) {
-        const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index);
-        oat_method.LinkMethod(meth);
+        LinkCode(method, oat_class.get(), method_index);
       }
     }
   }
@@ -2116,14 +2132,12 @@
     int new_vtable_count = old_vtable_count + miranda_list.size();
     vtable = vtable->CopyOf(new_vtable_count);
     for (size_t i = 0; i < miranda_list.size(); ++i) {
-      Method* meth = miranda_list[i]; //AllocMethod();
-      // TODO: this shouldn't be a memcpy
-      //memcpy(meth, miranda_list[i], sizeof(Method));
-      meth->SetDeclaringClass(klass);
-      meth->SetAccessFlags(meth->GetAccessFlags() | kAccMiranda);
-      meth->SetMethodIndex(0xFFFF & (old_vtable_count + i));
-      klass->SetVirtualMethod(old_method_count + i, meth);
-      vtable->Set(old_vtable_count + i, meth);
+      Method* method = miranda_list[i];
+      method->SetDeclaringClass(klass);
+      method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
+      method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
+      klass->SetVirtualMethod(old_method_count + i, method);
+      vtable->Set(old_vtable_count + i, method);
     }
     // TODO: do not assign to the vtable field until it is fully constructed.
     klass->SetVTable(vtable);
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 277284a..21b5918 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -576,6 +576,7 @@
     }
     detail += "No implementation found for ";
     detail += PrettyMethod(m);
+    detail += " (tried " + jni_short_name + " and " + jni_long_name + ")";
     LOG(ERROR) << detail;
     return NULL;
   }
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 6ebe36e..65b89a3 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -39,6 +39,8 @@
 // Return value helper for jobject return types
 extern Object* DecodeJObjectInThread(Thread* thread, jobject obj) {
   if (thread->IsExceptionPending()) {
+    // clear any result if an exception is pending to avoid making a
+    // local reference out of garbage.
     return NULL;
   }
   return thread->DecodeJObject(obj);
diff --git a/src/stack_walk.cc b/src/stack_walk.cc
index b2feee3..25b2270 100644
--- a/src/stack_walk.cc
+++ b/src/stack_walk.cc
@@ -100,7 +100,7 @@
 }
 
 extern "C"
-JNIEXPORT jint JNICALL Java_StackWalk_refmap2(JNIEnv* env, jobject thisObj, jint count) {
+JNIEXPORT jint JNICALL Java_StackWalk2_refmap2(JNIEnv* env, jobject thisObj, jint count) {
   gJava_StackWalk_refmap_calls++;
 
   // Visitor
diff --git a/test/StackWalk2/StackWalk2.java b/test/StackWalk2/StackWalk2.java
index 7d8c177..b4ea2d7 100644
--- a/test/StackWalk2/StackWalk2.java
+++ b/test/StackWalk2/StackWalk2.java
@@ -1,7 +1,5 @@
 // Copyright 2011 Google Inc. All Rights Reserved.
 
-package com.example.StackWalk2;
-
 public class StackWalk2 {
   // use v1 for this