ART: Fix CFI test wrt/ PIC

PIC boot images can't be loaded with dlopen, as their base is zero,
but we have an expectant address. Turn off in-process unwinding
in 137-cfi by checking the boot image oat file type.

Keep a non-owned referenced to the oat file in image space to simplify
access.

Change-Id: Ia2b525f9b2ecbc80b433f09e04ebece4cb6f2d2b
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index dc8a3d1..c4d978f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -808,18 +808,11 @@
 }
 
 const OatFile* ClassLinker::GetBootOatFile() {
-  // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as
-  // they were all compiled into the same oat file. So grab the first one, which is guaranteed to
-  // exist if the boot class-path isn't empty.
-  if (boot_class_path_.empty()) {
+  gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
+  if (image_space == nullptr) {
     return nullptr;
   }
-  const DexFile* boot_dex_file = boot_class_path_[0];
-  // Is it from an oat file?
-  if (boot_dex_file->GetOatDexFile() != nullptr) {
-    return boot_dex_file->GetOatDexFile()->GetOatFile();
-  }
-  return nullptr;
+  return image_space->GetOatFile();
 }
 
 const OatFile* ClassLinker::GetPrimaryOatFile() {
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index f7ceb84..1923d24 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -755,6 +755,7 @@
     DCHECK(!error_msg->empty());
     return nullptr;
   }
+  space->oat_file_non_owned_ = space->oat_file_.get();
 
   if (validate_oat_file && !space->ValidateOatFile(error_msg)) {
     DCHECK(!error_msg->empty());
@@ -838,10 +839,12 @@
   return true;
 }
 
+
 const OatFile* ImageSpace::GetOatFile() const {
-  return oat_file_.get();
+  return oat_file_non_owned_;
 }
 
+
 OatFile* ImageSpace::ReleaseOatFile() {
   CHECK(oat_file_.get() != nullptr);
   return oat_file_.release();
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 54dc7a6..93ff8aa 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -152,6 +152,10 @@
   // the ClassLinker during it's initialization.
   std::unique_ptr<OatFile> oat_file_;
 
+  // There are times when we need to find the boot image oat file. As
+  // we release ownership during startup, keep a non-owned reference.
+  const OatFile* oat_file_non_owned_;
+
   const std::string image_location_;
 
   DISALLOW_COPY_AND_ASSIGN(ImageSpace);
diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc
index 83f7711..601fbaa 100644
--- a/test/137-cfi/cfi.cc
+++ b/test/137-cfi/cfi.cc
@@ -29,6 +29,9 @@
 
 #include "base/logging.h"
 #include "base/macros.h"
+#include "gc/heap.h"
+#include "gc/space/image_space.h"
+#include "oat_file.h"
 #include "utils.h"
 
 namespace art {
@@ -84,8 +87,26 @@
 }
 #endif
 
+// Currently we have to fall back to our own loader for the boot image when it's compiled PIC
+// because its base is zero. Thus in-process unwinding through it won't work. This is a helper
+// detecting this.
+#if __linux__
+static bool IsPicImage() {
+  gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
+  CHECK(image_space != nullptr);  // We should be running with an image.
+  const OatFile* oat_file = image_space->GetOatFile();
+  CHECK(oat_file != nullptr);     // We should have an oat file to go with the image.
+  return oat_file->IsPic();
+}
+#endif
+
 extern "C" JNIEXPORT jboolean JNICALL Java_Main_unwindInProcess(JNIEnv*, jobject, jint, jboolean) {
 #if __linux__
+  if (IsPicImage()) {
+    LOG(INFO) << "Image is pic, in-process unwinding check bypassed.";
+    return JNI_TRUE;
+  }
+
   // TODO: What to do on Valgrind?
 
   std::unique_ptr<Backtrace> bt(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, GetTid()));