ART: Add support for patching and loading OAT files compiled with PIC

* Images (.art) compiled with pic now have a new field added.
* isDexOptNeeded will now skip patch-ing for apps compiled PIC
* First-boot patching now only copies boot.art, boot.oat is linked

As a result, all system preopted dex files (with --compile-pic) no
longer take up any space in /data/dalvik-cache/<isa>.

Bug: 18035729
Change-Id: Ie1acad81a0fd8b2f24e1f3f07a06e6fdb548be62
diff --git a/compiler/image_test.cc b/compiler/image_test.cc
index d5d487f..7e2be3e 100644
--- a/compiler/image_test.cc
+++ b/compiler/image_test.cc
@@ -63,7 +63,9 @@
   ScratchFile oat_file(OS::CreateEmptyFile(oat_filename.c_str()));
 
   const uintptr_t requested_image_base = ART_BASE_ADDRESS;
-  std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_driver_, requested_image_base));
+  std::unique_ptr<ImageWriter> writer(new ImageWriter(*compiler_driver_, requested_image_base,
+                                                      /*compile_pic*/false));
+  // TODO: compile_pic should be a test argument.
   {
     {
       jobject class_loader = NULL;
@@ -212,7 +214,8 @@
                              oat_file_begin,
                              oat_data_begin,
                              oat_data_end,
-                             oat_file_end);
+                             oat_file_end,
+                             /*compile_pic*/false);
     ASSERT_TRUE(image_header.IsValid());
 
     char* magic = const_cast<char*>(image_header.GetMagic());
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 7baae6e..861a182 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -580,7 +580,8 @@
                                     PointerToLowMemUInt32(oat_file_begin),
                                     PointerToLowMemUInt32(oat_data_begin_),
                                     PointerToLowMemUInt32(oat_data_end),
-                                    PointerToLowMemUInt32(oat_file_end));
+                                    PointerToLowMemUInt32(oat_file_end),
+                                    compile_pic_);
 }
 
 
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index e6a98d1..b0cf2b2 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -24,6 +24,7 @@
 #include <set>
 #include <string>
 
+#include "base/macros.h"
 #include "driver/compiler_driver.h"
 #include "mem_map.h"
 #include "oat_file.h"
@@ -35,17 +36,18 @@
 namespace art {
 
 // Write a Space built during compilation for use during execution.
-class ImageWriter {
+class ImageWriter FINAL {
  public:
-  ImageWriter(const CompilerDriver& compiler_driver, uintptr_t image_begin)
+  ImageWriter(const CompilerDriver& compiler_driver, uintptr_t image_begin,
+              bool compile_pic)
       : compiler_driver_(compiler_driver), image_begin_(reinterpret_cast<uint8_t*>(image_begin)),
-        image_end_(0), image_roots_address_(0), oat_file_(NULL),
-        oat_data_begin_(NULL), interpreter_to_interpreter_bridge_offset_(0),
+        image_end_(0), image_roots_address_(0), oat_file_(nullptr),
+        oat_data_begin_(nullptr), interpreter_to_interpreter_bridge_offset_(0),
         interpreter_to_compiled_code_bridge_offset_(0), jni_dlsym_lookup_offset_(0),
         portable_imt_conflict_trampoline_offset_(0), portable_resolution_trampoline_offset_(0),
         portable_to_interpreter_bridge_offset_(0), quick_generic_jni_trampoline_offset_(0),
         quick_imt_conflict_trampoline_offset_(0), quick_resolution_trampoline_offset_(0),
-        quick_to_interpreter_bridge_offset_(0) {
+        quick_to_interpreter_bridge_offset_(0), compile_pic_(compile_pic) {
     CHECK_NE(image_begin, 0U);
   }
 
@@ -59,8 +61,8 @@
 
   mirror::Object* GetImageAddress(mirror::Object* object) const
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (object == NULL) {
-      return NULL;
+    if (object == nullptr) {
+      return nullptr;
     }
     return reinterpret_cast<mirror::Object*>(image_begin_ + GetImageOffset(object));
   }
@@ -111,8 +113,8 @@
     // different .o ELF objects.
     DCHECK_LT(offset, oat_file_->Size());
 #endif
-    if (offset == 0) {
-      return NULL;
+    if (offset == 0u) {
+      return nullptr;
     }
     return oat_data_begin_ + offset;
   }
@@ -217,6 +219,7 @@
   uint32_t quick_imt_conflict_trampoline_offset_;
   uint32_t quick_resolution_trampoline_offset_;
   uint32_t quick_to_interpreter_bridge_offset_;
+  const bool compile_pic_;
 
   friend class FixupVisitor;
   friend class FixupClassVisitor;
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 847fa0d..4cb7d9c 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -139,7 +139,7 @@
     compiler_driver_->CompileAll(class_loader, class_linker->GetBootClassPath(), &timings);
   }
   std::unique_ptr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), nullptr,
-                                                  false, &error_msg));
+                                                  nullptr, false, &error_msg));
   ASSERT_TRUE(oat_file.get() != nullptr) << error_msg;
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_TRUE(oat_header.IsValid());