Setup AbstractMethodError and dlsym stub when loading from oat

Change-Id: Ie97fa6eb3cfb7d0c6224aa6914f28a7b137ae056
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);