Add ELF loader to OatFile.

Change-Id: I062c3cc78ff9a35d0efcbc9451e7e7ccb055667b
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 344f844..e755cbd 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -645,7 +645,9 @@
   std::string oat_filename;
   oat_filename += runtime->GetHostPrefix();
   oat_filename += oat_location->ToModifiedUtf8();
-  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, image_header.GetOatBegin());
+  OatFile* oat_file = OatFile::Open(oat_filename, oat_filename,
+                                    image_header.GetOatBegin(),
+                                    OatFile::kRelocNone);
   VLOG(startup) << "ClassLinker::OpenOat entering oat_filename=" << oat_filename;
   if (oat_file == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image.";
@@ -729,7 +731,8 @@
 static const DexFile* FindDexFileInOatLocation(const std::string& dex_location,
                                                uint32_t dex_location_checksum,
                                                const std::string& oat_location) {
-  UniquePtr<OatFile> oat_file(OatFile::Open(oat_location, oat_location, NULL));
+  UniquePtr<OatFile> oat_file(
+      OatFile::Open(oat_location, oat_location, NULL, OatFile::kRelocAll));
   if (oat_file.get() == NULL) {
     return NULL;
   }
@@ -781,7 +784,8 @@
     LOG(ERROR) << "Failed to seek to start of generated oat file: " << oat_location;
     return NULL;
   }
-  const OatFile* oat_file = OatFile::Open(*file.get(), oat_location, NULL);
+  const OatFile* oat_file =
+      OatFile::Open(*file.get(), oat_location, NULL, OatFile::kRelocAll);
   if (oat_file == NULL) {
     LOG(ERROR) << "Failed to open generated oat file: " << oat_location;
     return NULL;
@@ -877,7 +881,8 @@
     return oat_file;
   }
 
-  oat_file = OatFile::Open(oat_location, oat_location, NULL);
+  oat_file = OatFile::Open(oat_location, oat_location, NULL,
+                           OatFile::kRelocAll);
   if (oat_file == NULL) {
     return NULL;
   }
@@ -3513,4 +3518,10 @@
   class_roots_->Set(class_root, klass);
 }
 
+void ClassLinker::RelocateExecutable() {
+  for (size_t i = 0; i < oat_files_.size(); ++i) {
+    const_cast<OatFile*>(oat_files_[i])->RelocateExecutable();
+  }
+}
+
 }  // namespace art
diff --git a/src/class_linker.h b/src/class_linker.h
index 3226a6f..b6727d9 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -290,6 +290,9 @@
   // Get the oat code for a method when its class isn't yet initialized
   const void* GetOatCodeFor(const Method* method);
 
+  // Relocate the OatFiles (ELF images)
+  void RelocateExecutable();
+
   pid_t GetClassesLockOwner(); // For SignalCatcher.
   pid_t GetDexLockOwner(); // For SignalCatcher.
 
diff --git a/src/common_test.h b/src/common_test.h
index 3d5b53b..a323831 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -204,7 +204,13 @@
                                 reinterpret_cast<uint32_t>(mapping_table),
                                 reinterpret_cast<uint32_t>(vmap_table),
                                 reinterpret_cast<uint32_t>(gc_map),
-                                reinterpret_cast<uint32_t>(invoke_stub));
+                                reinterpret_cast<uint32_t>(invoke_stub)
+#if defined(ART_USE_LLVM_COMPILER)
+                              , NULL,
+                                -1u,
+                                -1u
+#endif
+                                );
   }
 
   void MakeExecutable(Method* method) {
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 75ced8b..2b18903 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -27,6 +27,7 @@
 #include "jni_compiler.h"
 #include "method_compiler.h"
 #include "oat_compilation_unit.h"
+#include "oat_file.h"
 #include "stl_util.h"
 #include "upcall_compiler.h"
 
@@ -203,7 +204,9 @@
   compiler_lock_.AssertHeld();
   DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
 
-  if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(), cunit->GetElfImage())) {
+  if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
+                              cunit->GetElfImage(),
+                              OatFile::kRelocAll)) {
     LOG(ERROR) << "Failed to load ELF from compilation unit "
                << cunit->GetElfIndex();
   }
diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc
index 60fce0b..adea85d 100644
--- a/src/compiler_llvm/elf_loader.cc
+++ b/src/compiler_llvm/elf_loader.cc
@@ -19,6 +19,7 @@
 #include "compiled_method.h"
 #include "elf_image.h"
 #include "logging.h"
+#include "oat_file.h"
 #include "object.h"
 #include "runtime_support_llvm.h"
 #include "utils_llvm.h"
@@ -37,7 +38,9 @@
 }
 
 
-bool ElfLoader::LoadElfAt(size_t elf_idx, const ElfImage& elf_image) {
+bool ElfLoader::LoadElfAt(size_t elf_idx,
+                          const ElfImage& elf_image,
+                          OatFile::RelocationBehavior reloc) {
   if (elf_idx < executables_.size() && executables_[elf_idx] != NULL) {
     return false;
   }
@@ -46,9 +49,8 @@
     executables_.resize(elf_idx + 1);
   }
 
-  RSExecRef executable =
-    rsloaderCreateExec(elf_image.begin(), elf_image.size(),
-                       art_find_runtime_support_func, NULL);
+  RSExecRef executable = rsloaderLoadExecutable(elf_image.begin(),
+                                                elf_image.size());
 
   if (executable == NULL) {
     LOG(WARNING) << "Failed to load ELF"
@@ -57,11 +59,31 @@
     return false;
   }
 
+  if (reloc == OatFile::kRelocAll) {
+    if (!rsloaderRelocateExecutable(executable,
+                                    art_find_runtime_support_func, NULL)) {
+      LOG(ERROR) << "Failed to relocate the ELF image";
+      rsloaderDisposeExec(executable);
+      return false;
+    }
+  }
+
   executables_[elf_idx] = executable;
   return true;
 }
 
 
+void ElfLoader::RelocateExecutable() {
+  for (size_t i = 0; i < executables_.size(); ++i) {
+    if (executables_[i] != NULL &&
+        !rsloaderRelocateExecutable(executables_[i],
+                                    art_find_runtime_support_func, NULL)) {
+      LOG(FATAL) << "Failed to relocate ELF image " << i;
+    }
+  }
+}
+
+
 const void* ElfLoader::GetMethodCodeAddr(size_t elf_idx,
                                          const Method* method) const {
   CHECK_LT(elf_idx, executables_.size());
diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h
index 5c8063a..9e8137f 100644
--- a/src/compiler_llvm/elf_loader.h
+++ b/src/compiler_llvm/elf_loader.h
@@ -19,6 +19,7 @@
 
 #include "elf_image.h"
 #include "globals.h"
+#include "oat_file.h"
 #include "object.h"
 
 #include <android/librsloader.h>
@@ -35,7 +36,10 @@
  public:
   ~ElfLoader();
 
-  bool LoadElfAt(size_t elf_idx, const ElfImage& elf_image);
+  bool LoadElfAt(size_t elf_idx, const ElfImage& elf_image,
+                 OatFile::RelocationBehavior reloc);
+
+  void RelocateExecutable();
 
   const void* GetMethodCodeAddr(size_t elf_idx, const Method* method) const;
 
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index a4b270d..3ada9f4 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -197,7 +197,8 @@
   // A user build looks like this, and it will have no classes.dex in
   // the input for checksum validation.
   std::string oat_filename(OatFile::DexFilenameToOatFilename(filename.c_str()));
-  UniquePtr<const OatFile> oat_file(OatFile::Open(oat_filename, oat_filename, NULL));
+  UniquePtr<const OatFile> oat_file(
+      OatFile::Open(oat_filename, oat_filename, NULL, OatFile::kRelocNone));
   if (oat_file.get() != NULL && oat_file->GetOatDexFile(filename.c_str()) != NULL) {
     if (debug_logging) {
       LOG(INFO) << "DexFile_isDexOptNeeded ignoring precompiled file: " << filename.c_str();
@@ -207,7 +208,8 @@
 
   // Check if we have an oat file in the cache
   std::string cache_location(GetArtCacheFilenameOrDie(oat_filename));
-  oat_file.reset(OatFile::Open(cache_location, oat_filename, NULL));
+  oat_file.reset(
+      OatFile::Open(cache_location, oat_filename, NULL, OatFile::kRelocNone));
   if (oat_file.get() == NULL) {
     LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
               << " does not exist for " << filename.c_str();
diff --git a/src/image_writer.cc b/src/image_writer.cc
index adaeebc..9e01d01 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -32,6 +32,7 @@
 #include "image.h"
 #include "intern_table.h"
 #include "logging.h"
+#include "oat_file.h"
 #include "object.h"
 #include "object_utils.h"
 #include "runtime.h"
@@ -62,7 +63,8 @@
     }
   }
 
-  oat_file_ = OatFile::Open(oat_filename, oat_location, NULL, true);
+  oat_file_ = OatFile::Open(oat_filename, oat_location, NULL,
+                            OatFile::kRelocNone, true);
   if (oat_file_ == NULL) {
     LOG(ERROR) << "Failed to open oat file " << oat_filename;
     return false;
diff --git a/src/oat_file.cc b/src/oat_file.cc
index a8b89a9..97d8f64 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -22,6 +22,10 @@
 #include "os.h"
 #include "stl_util.h"
 
+#if defined(ART_USE_LLVM_COMPILER)
+#include "compiler_llvm/elf_loader.h"
+#endif
+
 namespace art {
 
 std::string OatFile::DexFilenameToOatFilename(const std::string& location) {
@@ -34,41 +38,57 @@
 OatFile* OatFile::Open(const std::string& filename,
                        const std::string& location,
                        byte* requested_base,
+                       RelocationBehavior reloc,
                        bool writable) {
   CHECK(!filename.empty()) << location;
   UniquePtr<File> file(OS::OpenFile(filename.c_str(), writable, false));
   if (file.get() == NULL) {
     return NULL;
   }
-  return Open(*file.get(), location, requested_base, writable);
+  return Open(*file.get(), location, requested_base, reloc, writable);
 }
 
 OatFile* OatFile::Open(File& file,
                        const std::string& location,
                        byte* requested_base,
+                       RelocationBehavior reloc,
                        bool writable) {
   CHECK(!location.empty());
   if (!IsValidOatFilename(location)) {
     LOG(WARNING) << "Attempting to open dex file with unknown extension '" << location << "'";
   }
   UniquePtr<OatFile> oat_file(new OatFile(location));
-  bool success = oat_file->Map(file, requested_base, writable);
+  bool success = oat_file->Map(file, requested_base, reloc, writable);
   if (!success) {
     return NULL;
   }
   return oat_file.release();
 }
 
-OatFile::OatFile(const std::string& location) : location_(location) {
+OatFile::OatFile(const std::string& location)
+    : location_(location)
+#if defined(ART_USE_LLVM_COMPILER)
+    , elf_loader_(new compiler_llvm::ElfLoader())
+#endif
+{
   CHECK(!location_.empty());
 }
 
 OatFile::~OatFile() {
   STLDeleteValues(&oat_dex_files_);
+#if defined(ART_USE_LLVM_COMPILER)
   STLDeleteElements(&oat_elf_images_);
+#endif
 }
 
-bool OatFile::Map(File& file, byte* requested_base, bool writable) {
+bool OatFile::Map(File& file,
+                  byte* requested_base,
+#if defined(ART_USE_LLVM_COMPILER)
+                  RelocationBehavior reloc,
+#else
+                  RelocationBehavior /*UNUSED*/,
+#endif
+                  bool writable) {
   OatHeader oat_header;
   bool success = file.ReadFully(&oat_header, sizeof(oat_header));
   if (!success || !oat_header.IsValid()) {
@@ -164,6 +184,11 @@
                                                        methods_offsets_pointer);
   }
 
+#if !defined(ART_USE_LLVM_COMPILER)
+  CHECK_EQ(oat_header.GetElfImageTableOffset(), 0u);
+  CHECK_EQ(oat_header.GetElfImageCount(), 0u);
+
+#else
   oat = map->Begin() + oat_header.GetElfImageTableOffset();
   CHECK((reinterpret_cast<uintptr_t>(oat) & 0x3) == 0);
 
@@ -174,9 +199,15 @@
     uint32_t elf_size = *reinterpret_cast<const uint32_t*>(oat);
     oat += sizeof(uint32_t);
 
-    oat_elf_images_.push_back(
-        new OatElfImage(this, map->Begin() + elf_offset, elf_size));
+    const byte* elf_begin = map->Begin() + elf_offset;
+
+    oat_elf_images_.push_back(new OatElfImage(this, elf_begin, elf_size));
+
+    if (!elf_loader_->LoadElfAt(i, ElfImage(elf_begin, elf_size), reloc)) {
+      LOG(ERROR) << "Failed to load ELF image.  index: " << i;
+    }
   }
+#endif
 
   mem_map_.reset(map.release());
   return true;
@@ -216,6 +247,12 @@
   return result;
 }
 
+void OatFile::RelocateExecutable() {
+#if defined(ART_USE_LLVM_COMPILER)
+  elf_loader_->RelocateExecutable();
+#endif
+}
+
 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
                                 const std::string& dex_file_location,
                                 uint32_t dex_file_location_checksum,
@@ -271,7 +308,13 @@
       oat_method_offsets.mapping_table_offset_,
       oat_method_offsets.vmap_table_offset_,
       oat_method_offsets.gc_map_offset_,
-      oat_method_offsets.invoke_stub_offset_);
+      oat_method_offsets.invoke_stub_offset_
+#if defined(ART_USE_LLVM_COMPILER)
+    , oat_file_->elf_loader_.get(),
+      oat_method_offsets.code_elf_idx_,
+      oat_method_offsets.invoke_stub_elf_idx_
+#endif
+      );
 }
 
 OatFile::OatMethod::OatMethod(const byte* base,
@@ -282,7 +325,13 @@
                               const uint32_t mapping_table_offset,
                               const uint32_t vmap_table_offset,
                               const uint32_t gc_map_offset,
-                              const uint32_t invoke_stub_offset)
+                              const uint32_t invoke_stub_offset
+#if defined(ART_USE_LLVM_COMPILER)
+                            , const compiler_llvm::ElfLoader* elf_loader,
+                              const uint32_t code_elf_idx,
+                              const uint32_t invoke_stub_elf_idx
+#endif
+                              )
   : begin_(base),
     code_offset_(code_offset),
     frame_size_in_bytes_(frame_size_in_bytes),
@@ -291,7 +340,13 @@
     mapping_table_offset_(mapping_table_offset),
     vmap_table_offset_(vmap_table_offset),
     gc_map_offset_(gc_map_offset),
-    invoke_stub_offset_(invoke_stub_offset) {
+    invoke_stub_offset_(invoke_stub_offset)
+#if defined(ART_USE_LLVM_COMPILER)
+  , elf_loader_(elf_loader),
+    code_elf_idx_(code_elf_idx),
+    invoke_stub_elf_idx_(invoke_stub_elf_idx)
+#endif
+{
 #ifndef NDEBUG
   if (mapping_table_offset_ != 0) {  // implies non-native, non-stub code
     if (vmap_table_offset_ == 0) {
@@ -308,6 +363,68 @@
 
 OatFile::OatMethod::~OatMethod() {}
 
+
+const void* OatFile::OatMethod::GetCode() const {
+  if (!IsCodeInElf()) {
+    return GetOatPointer<const void*>(code_offset_);
+  } else {
+#if !defined(ART_USE_LLVM_COMPILER)
+    UNIMPLEMENTED(FATAL);
+    return NULL;
+#else
+    CHECK(elf_loader_ != NULL);
+    const void* code = elf_loader_->GetMethodCodeAddr(code_elf_idx_, method);
+    CHECK(code != NULL);
+    return code;
+#endif
+  }
+}
+
+uint32_t OatFile::OatMethod::GetCodeSize() const {
+  if (!IsCodeInElf()) {
+    uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
+
+    if (code == 0) {
+      return 0;
+    }
+    // TODO: make this Thumb2 specific
+    code &= ~0x1;
+    return reinterpret_cast<uint32_t*>(code)[-1];
+  } else {
+    UNIMPLEMENTED(ERROR);
+    return 0;
+  }
+}
+
+const Method::InvokeStub* OatFile::OatMethod::GetInvokeStub() const {
+  if (!IsInvokeStubInElf()) {
+    return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_);
+  } else {
+#if !defined(ART_USE_LLVM_COMPILER)
+    UNIMPLEMENTED(FATAL);
+    return NULL;
+#else
+    CHECK(elf_loader_ != NULL);
+    const Method::InvokeStub* stub = elf_loader_->GetMethodInvokeStubAddr(invoke_stub_elf_idx_, method);
+    CHECK(stub != NULL);
+    return stub;
+#endif
+  }
+}
+
+uint32_t OatFile::OatMethod::GetInvokeStubSize() const {
+  if (!IsInvokeStubInElf()) {
+    uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub());
+    if (code == 0) {
+      return 0;
+    }
+    return reinterpret_cast<uint32_t*>(code)[-1];
+  } else {
+    UNIMPLEMENTED(ERROR);
+    return 0;
+  }
+}
+
 void OatFile::OatMethod::LinkMethodPointers(Method* method) const {
   CHECK(method != NULL);
   method->SetCode(GetCode());
diff --git a/src/oat_file.h b/src/oat_file.h
index 281ef78..07d7f63 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -20,14 +20,27 @@
 #include <vector>
 
 #include "dex_file.h"
+#include "invoke_type.h"
 #include "mem_map.h"
 #include "oat.h"
 #include "object.h"
 
+#if defined(ART_USE_LLVM_COMPILER)
+namespace art {
+  namespace compiler_llvm {
+    class ElfLoader;
+  }
+}
+#endif
+
 namespace art {
 
 class OatFile {
  public:
+  enum RelocationBehavior {
+    kRelocNone,
+    kRelocAll,
+  };
 
   // Returns an OatFile name based on a DexFile location
   static std::string DexFilenameToOatFilename(const std::string& location);
@@ -37,12 +50,14 @@
   static OatFile* Open(const std::string& filename,
                        const std::string& location,
                        byte* requested_base,
+                       RelocationBehavior reloc,
                        bool writable = false);
 
   // Open an oat file from an already opened File with the given location.
   static OatFile* Open(File& file,
                        const std::string& location,
                        byte* requested_base,
+                       RelocationBehavior reloc,
                        bool writable = false);
 
   ~OatFile();
@@ -88,18 +103,34 @@
       return invoke_stub_offset_;
     }
 
-    const void* GetCode() const {
-      return GetOatPointer<const void*>(code_offset_);
+#if defined(ART_USE_LLVM_COMPILER)
+    uint32_t GetCodeElfIndex() const {
+      return code_elf_idx_;
     }
-    uint32_t GetCodeSize() const {
-      uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
-      if (code == 0) {
-        return 0;
-      }
-      // TODO: make this Thumb2 specific
-      code &= ~0x1;
-      return reinterpret_cast<uint32_t*>(code)[-1];
+    uint32_t GetInvokeStubElfIndex() const {
+      return invoke_stub_elf_idx_;
     }
+#endif
+
+    bool IsCodeInElf() const {
+#if defined(ART_USE_LLVM_COMPILER)
+      return (code_elf_idx_ != -1u);
+#else
+      return false;
+#endif
+    }
+
+    bool IsInvokeStubInElf() const {
+#if defined(ART_USE_LLVM_COMPILER)
+      return (invoke_stub_elf_idx_ != -1u);
+#else
+      return false;
+#endif
+    }
+
+    const void* GetCode() const;
+    uint32_t GetCodeSize() const;
+
     const uint32_t* GetMappingTable() const {
       return GetOatPointer<const uint32_t*>(mapping_table_offset_);
     }
@@ -109,16 +140,9 @@
     const uint8_t* GetGcMap() const {
       return GetOatPointer<const uint8_t*>(gc_map_offset_);
     }
-    const Method::InvokeStub* GetInvokeStub() const {
-      return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_);
-    }
-    uint32_t GetInvokeStubSize() const {
-      uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub());
-      if (code == 0) {
-        return 0;
-      }
-      return reinterpret_cast<uint32_t*>(code)[-1];
-    }
+
+    const Method::InvokeStub* GetInvokeStub() const;
+    uint32_t GetInvokeStubSize() const;
 
     ~OatMethod();
 
@@ -131,7 +155,13 @@
               const uint32_t mapping_table_offset,
               const uint32_t vmap_table_offset,
               const uint32_t gc_map_offset,
-              const uint32_t invoke_stub_offset);
+              const uint32_t invoke_stub_offset
+#if defined(ART_USE_LLVM_COMPILER)
+            , const compiler_llvm::ElfLoader* elf_loader,
+              const uint32_t code_elf_idx,
+              const uint32_t invoke_stub_elf_idx
+#endif
+              );
 
    private:
     template<class T>
@@ -153,6 +183,13 @@
     uint32_t gc_map_offset_;
     uint32_t invoke_stub_offset_;
 
+#if defined(ART_USE_LLVM_COMPILER)
+    const compiler_llvm::ElfLoader* elf_loader_;
+
+    uint32_t code_elf_idx_;
+    uint32_t invoke_stub_elf_idx_;
+#endif
+
     friend class OatClass;
   };
 
@@ -239,17 +276,21 @@
                                   bool warn_if_not_found = true) const;
   std::vector<const OatDexFile*> GetOatDexFiles() const;
 
+#if defined(ART_USE_LLVM_COMPILER)
   const OatElfImage* GetOatElfImage(size_t i) const {
     return oat_elf_images_[i];
   }
+#endif
 
   size_t Size() const {
     return End() - Begin();
   }
 
+  void RelocateExecutable();
+
  private:
   explicit OatFile(const std::string& filename);
-  bool Map(File& file, byte* requested_base, bool writable);
+  bool Map(File& file, byte* requested_base, RelocationBehavior reloc, bool writable);
 
   const byte* Begin() const;
   const byte* End() const;
@@ -265,7 +306,10 @@
   typedef std::map<std::string, const OatDexFile*> Table;
   Table oat_dex_files_;
 
+#if defined(ART_USE_LLVM_COMPILER)
   std::vector<OatElfImage*> oat_elf_images_;
+  UniquePtr<compiler_llvm::ElfLoader> elf_loader_;
+#endif
 
   friend class OatClass;
   friend class OatDexFile;
diff --git a/src/oat_test.cc b/src/oat_test.cc
index d50183c..3e92a15 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -80,7 +80,10 @@
   if (compile) {  // OatWriter strips the code, regenerate to compare
     compiler_->CompileAll(class_loader.get(), class_linker->GetBootClassPath());
   }
-  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(), tmp.GetFilename(), NULL));
+  UniquePtr<OatFile> oat_file(OatFile::Open(tmp.GetFilename(),
+                                            tmp.GetFilename(),
+                                            NULL,
+                                            OatFile::kRelocNone));
   ASSERT_TRUE(oat_file.get() != NULL);
   const OatHeader& oat_header = oat_file->GetOatHeader();
   ASSERT_EQ(1U, oat_header.GetDexFileCount());
diff --git a/src/oatdump.cc b/src/oatdump.cc
index aa63ef5..978060d 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -1257,7 +1257,8 @@
   }
 
   if (oat_filename != NULL) {
-    OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL);
+    OatFile* oat_file =
+        OatFile::Open(oat_filename, oat_filename, NULL, OatFile::kRelocNone);
     if (oat_file == NULL) {
       fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
       return EXIT_FAILURE;
@@ -1265,6 +1266,7 @@
     OatDumper oat_dumper(*host_prefix.get(), *oat_file);
     oat_dumper.Dump(*os);
 
+#if defined(ART_USE_LLVM_COMPILER)
     if (!elf_filename_prefix.empty()) {
       uint32_t elf_image_count = oat_file->GetOatHeader().GetElfImageCount();
       for (uint32_t i = 0; i < elf_image_count; ++i) {
@@ -1281,6 +1283,7 @@
         }
       }
     }
+#endif
     return EXIT_SUCCESS;
   }
 
diff --git a/src/runtime.cc b/src/runtime.cc
index c013726..1d0ab8f 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -529,6 +529,9 @@
 
   CHECK(host_prefix_.empty()) << host_prefix_;
 
+  // Relocate the OatFiles (ELF images)
+  class_linker_->RelocateExecutable();
+
   // Restore main thread state to kNative as expected by native code
   Thread::Current()->SetState(Thread::kNative);