Compile method one-by-one.

Change-Id: Ic56fb397f3bd6dee32372eb875261a3383eaf30c
diff --git a/build/Android.common.mk b/build/Android.common.mk
index c4f04be..74bc4a9 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -233,7 +233,6 @@
 
 ifeq ($(ART_USE_LLVM_COMPILER),true)
 LIBART_COMMON_SRC_FILES += \
-	src/compiler_llvm/elf_loader.cc \
 	src/compiler_llvm/inferred_reg_category_map.cc \
 	src/compiler_llvm/procedure_linkage_table.cc \
 	src/compiler_llvm/runtime_support_llvm.cc
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index 9f75115..d090395 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -63,11 +63,6 @@
     LOCAL_SHARED_LIBRARIES += libdynamic_annotations-host
   endif
 
-  ifeq ($(ART_USE_LLVM_COMPILER),true)
-    LOCAL_C_INCLUDES += frameworks/compile/linkloader
-    LOCAL_STATIC_LIBRARIES += librsloader
-  endif
-
   # Mac OS linker doesn't understand --export-dynamic.
   ifneq ($(HOST_OS)-$$(art_target_or_host),darwin-host)
     # Allow jni_compiler_test to find Java_MyClassNatives_bar within itself using dlopen(NULL, ...).
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index e2c66e4..9ec356a 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -74,7 +74,7 @@
   endif
 
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
-  LOCAL_C_INCLUDES += frameworks/compile/linkloader
+
   libart_compiler_llvm_arm_STATIC_LIBRARIES := \
     libLLVMARMInfo \
     libLLVMARMDisassembler \
@@ -111,6 +111,7 @@
   endif
 
   LOCAL_STATIC_LIBRARIES += \
+    libLLVMObject \
     libLLVMLinker \
     libLLVMipo \
     libLLVMBitWriter \
@@ -129,8 +130,8 @@
     libLLVMMC \
     libLLVMMCParser \
     libLLVMCore \
-    libLLVMSupport \
-    librsloader
+    libLLVMSupport
+
   LOCAL_SHARED_LIBRARIES := liblog libnativehelper
   LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
   ifeq ($$(art_target_or_host),target)
diff --git a/build/Android.libart.mk b/build/Android.libart.mk
index 01fa42b..9ccbe3f 100644
--- a/build/Android.libart.mk
+++ b/build/Android.libart.mk
@@ -98,13 +98,6 @@
     endif
   endif
   LOCAL_C_INCLUDES += $(ART_C_INCLUDES)
-  ifeq ($(ART_USE_LLVM_COMPILER),true)
-    LOCAL_C_INCLUDES += frameworks/compile/linkloader
-    LOCAL_STATIC_LIBRARIES += librsloader
-  endif
-  ifeq ($(ART_REQUIRE_LLVM),true)
-    LOCAL_STATIC_LIBRARIES += libLLVMSupport
-  endif
   LOCAL_SHARED_LIBRARIES := liblog libnativehelper
   LOCAL_SHARED_LIBRARIES += libcorkscrew # native stack trace support
   ifeq ($$(art_target_or_host),target)
diff --git a/src/common_test.h b/src/common_test.h
index cdcac24..58d0219 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -177,14 +177,10 @@
     MakeExecutable(code_array->GetData(), code_array->GetLength());
   }
 
-#if !defined(ART_USE_LLVM_COMPILER)  // LLVM compilation uses ELF instead
   static void MakeExecutable(const std::vector<uint8_t>& code) {
     CHECK_NE(code.size(), 0U);
     MakeExecutable(&code[0], code.size());
   }
-#else
-  static void MakeExecutable(const std::vector<uint8_t>&) {}
-#endif
 
   // Create an OatMethod based on pointers (for unit tests)
   OatFile::OatMethod CreateOatMethod(const void* code,
@@ -205,13 +201,7 @@
                                 reinterpret_cast<uint32_t>(gc_map),
                                 reinterpret_cast<uint32_t>(invoke_stub)
 #if defined(ART_USE_LLVM_COMPILER)
-                              , NULL,
-                                static_cast<uint16_t>(-1u),
-                                static_cast<uint16_t>(-1u),
-                                static_cast<uint16_t>(-1u),
-                                static_cast<uint16_t>(-1u),
-                                static_cast<uint16_t>(-1u),
-                                static_cast<uint16_t>(-1u)
+                              , 0
 #endif
                                 );
   }
@@ -224,17 +214,12 @@
         compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty());
     CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method);
 
-    const Method::InvokeStub* method_invoke_stub = NULL;
-    if (compiled_invoke_stub->IsExecutableInElf()) {
-      method_invoke_stub =
-          compiler_->GetMethodInvokeStubAddr(compiled_invoke_stub, method);
-    } else {
-      const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
-      MakeExecutable(invoke_stub);
-      method_invoke_stub = reinterpret_cast<const Method::InvokeStub*>(
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
+    MakeExecutable(invoke_stub);
+    const Method::InvokeStub* method_invoke_stub =
+        reinterpret_cast<const Method::InvokeStub*>(
           CompiledCode::CodePointer(&invoke_stub[0],
                                     compiled_invoke_stub->GetInstructionSet()));
-    }
 
     LOG(INFO) << "MakeExecutable " << PrettyMethod(method)
               << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub);
@@ -247,14 +232,10 @@
                                                                  method->GetDexMethodIndex()));
       CHECK(compiled_method != NULL) << PrettyMethod(method);
 
-      const void* method_code = NULL;
-      if (compiled_method->IsExecutableInElf()) {
-        method_code = compiler_->GetMethodCodeAddr(compiled_method, method);
-      } else {
-        const std::vector<uint8_t>& code = compiled_method->GetCode();
-        MakeExecutable(code);
-        method_code = CompiledMethod::CodePointer(&code[0], compiled_method->GetInstructionSet());
-      }
+      const std::vector<uint8_t>& code = compiled_method->GetCode();
+      MakeExecutable(code);
+      const void* method_code = CompiledMethod::CodePointer(&code[0],
+                                                            compiled_method->GetInstructionSet());
 
       LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
 
@@ -380,9 +361,6 @@
     image_classes_.reset(new std::set<std::string>);
     compiler_.reset(new Compiler(instruction_set, true, 2, false, image_classes_.get(),
                                  true, true));
-#if defined(ART_USE_LLVM_COMPILER)
-    compiler_->EnableAutoElfLoading();
-#endif
 
     Runtime::Current()->GetHeap()->VerifyHeap();  // Check for heap corruption before the test
   }
diff --git a/src/compiled_method.h b/src/compiled_method.h
index 7ddde0c..ca3a597 100644
--- a/src/compiled_method.h
+++ b/src/compiled_method.h
@@ -32,22 +32,14 @@
 class CompiledCode {
  public:
   CompiledCode(InstructionSet instruction_set)
-      : instruction_set_(instruction_set), elf_idx_(-1), elf_func_idx_(-1) {
+      : instruction_set_(instruction_set) {
   }
 
   CompiledCode(InstructionSet instruction_set, const std::vector<uint8_t>& code)
-      : instruction_set_(instruction_set), code_(code), elf_idx_(-1),
-        elf_func_idx_(-1) {
+      : instruction_set_(instruction_set), code_(code) {
     CHECK_NE(code.size(), 0U);
   }
 
-  CompiledCode(InstructionSet instruction_set,
-               uint16_t elf_idx,
-               uint16_t elf_func_idx)
-      : instruction_set_(instruction_set), elf_idx_(elf_idx),
-        elf_func_idx_(elf_func_idx) {
-  }
-
   InstructionSet GetInstructionSet() const {
     return instruction_set_;
   }
@@ -57,6 +49,7 @@
   }
 
   void SetCode(const std::vector<uint8_t>& code) {
+    CHECK_NE(code.size(), 0U);
     code_ = code;
   }
 
@@ -64,18 +57,6 @@
     return (code_ == rhs.code_);
   }
 
-  bool IsExecutableInElf() const {
-    return (elf_idx_ != static_cast<uint16_t>(-1u));
-  }
-
-  uint16_t GetElfIndex() const {
-    return elf_idx_;
-  }
-
-  uint16_t GetElfFuncIndex() const {
-    return elf_func_idx_;
-  }
-
   // To align an offset from a page-aligned value to make it suitable
   // for code storage. For example on ARM, to ensure that PC relative
   // valu computations work out as expected.
@@ -95,10 +76,6 @@
  private:
   const InstructionSet instruction_set_;
   std::vector<uint8_t> code_;
-
-  // LLVM-specific fields
-  uint16_t elf_idx_;
-  uint16_t elf_func_idx_;
 };
 
 class CompiledMethod : public CompiledCode {
@@ -124,9 +101,8 @@
 
   // Constructs a CompiledMethod for the LLVM compiler.
   CompiledMethod(InstructionSet instruction_set,
-                 uint16_t elf_idx,
-                 uint16_t elf_func_idx)
-      : CompiledCode(instruction_set, elf_idx, elf_func_idx),
+                 const std::vector<uint8_t>& code)
+      : CompiledCode(instruction_set, code),
         frame_size_in_bytes_(kStackAlignment), core_spill_mask_(0),
         fp_spill_mask_(0) {
   }
@@ -162,12 +138,6 @@
   explicit CompiledInvokeStub(InstructionSet instruction_set,
                               const std::vector<uint8_t>& code);
 
-  explicit CompiledInvokeStub(InstructionSet instruction_set,
-                              uint16_t elf_idx,
-                              uint16_t elf_func_idx)
-      : CompiledCode(instruction_set, elf_idx, elf_func_idx) {
-  }
-
   ~CompiledInvokeStub();
 };
 
diff --git a/src/compiler.cc b/src/compiler.cc
index a726606..272ba9e 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -319,14 +319,8 @@
       compiler_(NULL),
       compiler_context_(NULL),
       jni_compiler_(NULL),
-#if !defined(ART_USE_LLVM_COMPILER)
-      create_invoke_stub_(NULL) {
-#else
-      create_invoke_stub_(NULL),
-      compiler_enable_auto_elf_loading_(NULL),
-      compiler_get_method_code_addr_(NULL),
-      compiler_get_method_invoke_stub_addr_(NULL) {
-#endif
+      create_invoke_stub_(NULL)
+{
   std::string compiler_so_name(MakeCompilerSoName(instruction_set_));
   compiler_library_ = dlopen(compiler_so_name.c_str(), RTLD_LAZY);
   if (compiler_library_ == NULL) {
@@ -353,12 +347,6 @@
 #if defined(ART_USE_LLVM_COMPILER)
   create_proxy_stub_ = FindFunction<CreateProxyStubFn>(
       compiler_so_name, compiler_library_, "ArtCreateProxyStub");
-  compiler_enable_auto_elf_loading_ = FindFunction<CompilerEnableAutoElfLoadingFn>(
-      compiler_so_name, compiler_library_, "compilerLLVMEnableAutoElfLoading");
-  compiler_get_method_code_addr_ = FindFunction<CompilerGetMethodCodeAddrFn>(
-      compiler_so_name, compiler_library_, "compilerLLVMGetMethodCodeAddr");
-  compiler_get_method_invoke_stub_addr_ = FindFunction<CompilerGetMethodInvokeStubAddrFn>(
-      compiler_so_name, compiler_library_, "compilerLLVMGetMethodInvokeStubAddr");
 #endif
 
   CHECK(!Runtime::Current()->IsStarted());
@@ -395,10 +383,17 @@
     STLDeleteElements(&methods_to_patch_);
   }
 #if defined(ART_USE_LLVM_COMPILER)
-  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
-                                                          compiler_library_,
-                                                          "compilerLLVMDispose");
-  (*f)(*this);
+  // Uninitialize compiler_context_
+  typedef void (*UninitCompilerContextFn)(Compiler&);
+
+  std::string compiler_so_name(MakeCompilerSoName(instruction_set_));
+
+  UninitCompilerContextFn uninit_compiler_context =
+    FindFunction<void (*)(Compiler&)>(compiler_so_name,
+                                      compiler_library_,
+                                      "ArtUnInitCompilerContext");
+
+  uninit_compiler_context(*this);
 #endif
   if (compiler_library_ != NULL) {
     VLOG(compiler) << "dlclose(" << compiler_library_ << ")";
@@ -511,12 +506,6 @@
 void Compiler::PostCompile(ClassLoader* class_loader,
                            const std::vector<const DexFile*>& dex_files) {
   SetGcMaps(class_loader, dex_files);
-#if defined(ART_USE_LLVM_COMPILER)
-  CompilerCallbackFn f = FindFunction<CompilerCallbackFn>(MakeCompilerSoName(instruction_set_),
-                                                          compiler_library_,
-                                                          "compilerLLVMMaterializeRemainder");
-  (*f)(*this);
-#endif
 }
 
 bool Compiler::IsImageClass(const std::string& descriptor) const {
@@ -1683,31 +1672,4 @@
 }
 #endif
 
-#if defined(ART_USE_LLVM_COMPILER)
-void Compiler::EnableAutoElfLoading() {
-  compiler_enable_auto_elf_loading_(*this);
-}
-
-const void* Compiler::GetMethodCodeAddr(const CompiledMethod* cm,
-                                        const Method* method) const {
-  return compiler_get_method_code_addr_(*this, cm, method);
-}
-
-const Method::InvokeStub* Compiler::GetMethodInvokeStubAddr(const CompiledInvokeStub* cm,
-                                                            const Method* method) const {
-  return compiler_get_method_invoke_stub_addr_(*this, cm, method);
-}
-
-std::vector<ElfImage> Compiler::GetElfImages() const {
-  typedef std::vector<ElfImage> (*GetElfImagesFn)(const Compiler&);
-
-  GetElfImagesFn get_elf_images =
-    FindFunction<GetElfImagesFn>(MakeCompilerSoName(instruction_set_),
-                                 compiler_library_,
-                                 "compilerLLVMGetElfImages");
-
-  return get_elf_images(*this);
-}
-#endif
-
 }  // namespace art
diff --git a/src/compiler.h b/src/compiler.h
index 5202967..46d3647 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -25,7 +25,6 @@
 #include "compiled_method.h"
 #include "dex_cache.h"
 #include "dex_file.h"
-#include "elf_image.h"
 #include "instruction_set.h"
 #include "invoke_type.h"
 #include "oat_file.h"
@@ -146,34 +145,6 @@
   void SetBitcodeFileName(std::string const& filename);
 #endif
 
-#if defined(ART_USE_LLVM_COMPILER)
-  void EnableAutoElfLoading();
-
-  const void* GetMethodCodeAddr(const CompiledMethod* cm,
-                                const Method* method) const;
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(const CompiledInvokeStub* cm,
-                                                    const Method* method) const;
-
-  std::vector<ElfImage> GetElfImages() const;
-#else
-  void EnableAutoElfLoader() { }
-
-  const void* GetMethodCodeAddr(const CompiledMethod*,
-                                const Method*) const {
-    return NULL;
-  }
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(const CompiledInvokeStub*,
-                                                    const Method*) const {
-    return NULL;
-  }
-
-  std::vector<ElfImage> GetElfImages() const {
-    return std::vector<ElfImage>();
-  }
-#endif
-
   void SetCompilerContext(void* compiler_context) {
     compiler_context_ = compiler_context;
   }
diff --git a/src/compiler_llvm/compilation_unit.cc b/src/compiler_llvm/compilation_unit.cc
index 38faf61..fdbf575 100644
--- a/src/compiler_llvm/compilation_unit.cc
+++ b/src/compiler_llvm/compilation_unit.cc
@@ -17,6 +17,7 @@
 #include "compilation_unit.h"
 
 #include "compiled_method.h"
+#include "compiler_llvm.h"
 #include "file.h"
 #include "instruction_set.h"
 #include "ir_builder.h"
@@ -47,8 +48,10 @@
 #include <llvm/DerivedTypes.h>
 #include <llvm/LLVMContext.h>
 #include <llvm/Module.h>
+#include <llvm/Object/ObjectFile.h>
 #include <llvm/PassManager.h>
 #include <llvm/Support/Debug.h>
+#include <llvm/Support/ELF.h>
 #include <llvm/Support/FormattedStream.h>
 #include <llvm/Support/ManagedStatic.h>
 #include <llvm/Support/MemoryBuffer.h>
@@ -77,37 +80,6 @@
 
 namespace {
 
-class UpdateFrameSizePass : public llvm::MachineFunctionPass {
- public:
-  static char ID;
-
-  UpdateFrameSizePass() : llvm::MachineFunctionPass(ID), cunit_(NULL) {
-    LOG(FATAL) << "Unexpected instantiation of UpdateFrameSizePass";
-    // NOTE: We have to declare this constructor for llvm::RegisterPass, but
-    // this constructor won't work because we have no information on
-    // CompilationUnit.  Thus, we should place a LOG(FATAL) here.
-  }
-
-  UpdateFrameSizePass(art::compiler_llvm::CompilationUnit* cunit)
-    : llvm::MachineFunctionPass(ID), cunit_(cunit) {
-  }
-
-  virtual bool runOnMachineFunction(llvm::MachineFunction &MF) {
-    cunit_->UpdateFrameSizeInBytes(MF.getFunction(),
-                                   MF.getFrameInfo()->getStackSize());
-    return false;
-  }
-
- private:
-  art::compiler_llvm::CompilationUnit* cunit_;
-};
-
-char UpdateFrameSizePass::ID = 0;
-
-llvm::RegisterPass<UpdateFrameSizePass> reg_update_frame_size_pass_(
-  "update-frame-size", "Update frame size pass", false, false);
-
-
 // TODO: We may need something to manage these passes.
 // TODO: We need high-level IR to analysis and do this at the IRBuilder level.
 class AddSuspendCheckToLoopLatchPass : public llvm::LoopPass {
@@ -167,10 +139,10 @@
 llvm::Module* makeLLVMModuleContents(llvm::Module* module);
 
 
-CompilationUnit::CompilationUnit(InstructionSet insn_set, size_t elf_idx)
-: cunit_lock_("compilation_unit_lock"), insn_set_(insn_set), elf_idx_(elf_idx),
-  context_(new llvm::LLVMContext()), compiled_methods_map_(new CompiledMethodMap()),
-  mem_usage_(0), num_elf_funcs_(0) {
+CompilationUnit::CompilationUnit(const CompilerLLVM* compiler_llvm,
+                                 size_t cunit_idx)
+: compiler_llvm_(compiler_llvm), cunit_idx_(cunit_idx),
+  context_(new llvm::LLVMContext()) {
 
   // Create the module and include the runtime function declaration
   module_ = new llvm::Module("art", *context_);
@@ -180,7 +152,7 @@
   irb_.reset(new IRBuilder(*context_, *module_));
 
   // We always need a switch case, so just use a normal function.
-  switch(insn_set_) {
+  switch(GetInstructionSet()) {
   default:
     runtime_support_.reset(new RuntimeSupportBuilder(*context_, *module_, *irb_));
     break;
@@ -205,57 +177,56 @@
 }
 
 
-bool CompilationUnit::Materialize(size_t thread_count) {
-  MutexLock GUARD(cunit_lock_);
-
-  // Materialize the bitcode to elf_image_
-  llvm::raw_string_ostream str_os(elf_image_);
-  bool success = MaterializeToFile(str_os);
-  LOG(INFO) << "Compilation Unit: " << elf_idx_ << (success ? " (done)" : " (failed)");
-
-  // Free the resources
-  context_.reset(NULL);
-  irb_.reset(NULL);
-  module_ = NULL;
-  runtime_support_.reset(NULL);
-  compiled_methods_map_.reset(NULL);
-
-  return success;
+InstructionSet CompilationUnit::GetInstructionSet() const {
+  return compiler_llvm_->GetInstructionSet();
 }
 
 
-void CompilationUnit::RegisterCompiledMethod(const llvm::Function* func,
-                                             CompiledMethod* compiled_method) {
-  MutexLock GUARD(cunit_lock_);
-  compiled_methods_map_->Put(func, compiled_method);
-}
+bool CompilationUnit::Materialize() {
+  std::string elf_image;
 
-
-void CompilationUnit::UpdateFrameSizeInBytes(const llvm::Function* func,
-                                             size_t frame_size_in_bytes) {
-  MutexLock GUARD(cunit_lock_);
-  SafeMap<const llvm::Function*, CompiledMethod*>::iterator iter =
-    compiled_methods_map_->find(func);
-
-  if (iter != compiled_methods_map_->end()) {
-    CompiledMethod* compiled_method = iter->second;
-    compiled_method->SetFrameSizeInBytes(frame_size_in_bytes);
-
-    if (frame_size_in_bytes > 1728u) {
-      LOG(WARNING) << "Huge frame size: " << frame_size_in_bytes
-                   << " elf_idx=" << compiled_method->GetElfIndex()
-                   << " elf_func_idx=" << compiled_method->GetElfFuncIndex();
-    }
+  // Compile and prelink llvm::Module
+  if (!MaterializeToString(elf_image)) {
+    LOG(ERROR) << "Failed to materialize compilation unit " << cunit_idx_;
+    DeleteResources();
+    return false;
   }
+
+#if 0
+  // Dump the ELF image for debugging
+  std::string filename(StringPrintf("%s/Art%zu.elf",
+                                    GetArtCacheOrDie(GetAndroidData()).c_str(),
+                                    cunit_idx_));
+  UniquePtr<File> output(OS::OpenFile(filename.c_str(), true));
+  output->WriteFully(elf_image.data(), elf_image.size());
+#endif
+
+  // Extract the .text section and prelink the code
+  if (!ExtractCodeAndPrelink(elf_image)) {
+    LOG(ERROR) << "Failed to extract code from compilation unit " << cunit_idx_;
+    DeleteResources();
+    return false;
+  }
+
+  DeleteResources();
+  return true;
 }
 
-bool CompilationUnit::MaterializeToFile(llvm::raw_ostream& out_stream) {
+
+bool CompilationUnit::MaterializeToString(std::string& str_buffer) {
+  llvm::raw_string_ostream str_os(str_buffer);
+  return MaterializeToRawOStream(str_os);
+}
+
+
+bool CompilationUnit::MaterializeToRawOStream(llvm::raw_ostream& out_stream) {
   // Lookup the LLVM target
   char const* target_triple = NULL;
   char const* target_cpu = "";
   char const* target_attr = NULL;
 
-  switch (insn_set_) {
+  InstructionSet insn_set = GetInstructionSet();
+  switch (insn_set) {
   case kThumb2:
     target_triple = "thumb-none-linux-gnueabi";
     target_cpu = "cortex-a9";
@@ -281,7 +252,7 @@
     break;
 
   default:
-    LOG(FATAL) << "Unknown instruction set: " << insn_set_;
+    LOG(FATAL) << "Unknown instruction set: " << insn_set;
   }
 
   std::string errmsg;
@@ -375,11 +346,6 @@
       return false;
     }
 
-    // FIXME: Unable to run the UpdateFrameSizePass pass since it tries to
-    //        update the value reside in the different address space.
-    // Add pass to update the frame_size_in_bytes_
-    //pm.add(new ::UpdateFrameSizePass(this));
-
     // Run the per-function optimization
     fpm.doInitialization();
     for (llvm::Module::iterator F = module_->begin(), E = module_->end();
@@ -395,5 +361,130 @@
   return true;
 }
 
+
+bool CompilationUnit::ExtractCodeAndPrelink(const std::string& elf_image) {
+  llvm::OwningPtr<llvm::MemoryBuffer> elf_image_buff(
+    llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(elf_image.data(),
+                                                     elf_image.size())));
+
+  llvm::OwningPtr<llvm::object::ObjectFile> elf_file(
+    llvm::object::ObjectFile::createELFObjectFile(elf_image_buff.take()));
+
+  llvm::error_code ec;
+
+  const ProcedureLinkageTable& plt = compiler_llvm_->GetProcedureLinkageTable();
+
+  for (llvm::object::section_iterator
+       sec_iter = elf_file->begin_sections(),
+       sec_end = elf_file->end_sections();
+       sec_iter != sec_end; sec_iter.increment(ec)) {
+
+    CHECK(ec == 0) << "Failed to read section because " << ec.message();
+
+    // Read the section information
+    llvm::StringRef name;
+    uint64_t alignment = 0u;
+    uint64_t size = 0u;
+
+    CHECK(sec_iter->getName(name) == 0);
+    CHECK(sec_iter->getSize(size) == 0);
+    CHECK(sec_iter->getAlignment(alignment) == 0);
+
+    if (name == ".data" || name == ".bss" || name == ".rodata") {
+      if (size > 0) {
+        LOG(FATAL) << "Compilation unit " << cunit_idx_ << " has non-empty "
+                   << name.str() << " section";
+      }
+
+    } else if (name == "" || name == ".rel.text" ||
+               name == ".ARM.attributes" || name == ".symtab" ||
+               name == ".strtab" || name == ".shstrtab") {
+      // We can ignore these sections.  We don't have to copy them into
+      // the result Oat file.
+
+    } else if (name == ".text") {
+      // Ensure the alignment requirement is less than or equal to
+      // kArchAlignment
+      CheckCodeAlign(alignment);
+
+      // Copy the compiled code
+      llvm::StringRef contents;
+      CHECK(sec_iter->getContents(contents) == 0);
+
+      copy(contents.data(),
+           contents.data() + contents.size(),
+           back_inserter(compiled_code_));
+
+      // Prelink the compiled code
+      for (llvm::object::relocation_iterator
+           rel_iter = sec_iter->begin_relocations(),
+           rel_end = sec_iter->end_relocations(); rel_iter != rel_end;
+           rel_iter.increment(ec)) {
+
+        CHECK(ec == 0) << "Failed to read relocation because " << ec.message();
+
+        // Read the relocation information
+        llvm::object::SymbolRef sym_ref;
+        uint64_t rel_offset = 0;
+        uint64_t rel_type = 0;
+        int64_t rel_addend = 0;
+
+        CHECK(rel_iter->getSymbol(sym_ref) == 0);
+        CHECK(rel_iter->getOffset(rel_offset) == 0);
+        CHECK(rel_iter->getType(rel_type) == 0);
+        CHECK(rel_iter->getAdditionalInfo(rel_addend) == 0);
+
+        // Read the symbol related to this relocation fixup
+        llvm::StringRef sym_name;
+        CHECK(sym_ref.getName(sym_name) == 0);
+
+        // Relocate the fixup.
+        // TODO: Support more relocation type.
+        CHECK(rel_type == llvm::ELF::R_ARM_ABS32);
+        CHECK_LE(rel_offset + 4, compiled_code_.size());
+
+        uintptr_t dest_addr = plt.GetEntryAddress(sym_name.str().c_str());
+        uintptr_t final_addr = dest_addr + rel_addend;
+        compiled_code_[rel_offset] = final_addr & 0xff;
+        compiled_code_[rel_offset + 1] = (final_addr >> 8) & 0xff;
+        compiled_code_[rel_offset + 2] = (final_addr >> 16) & 0xff;
+        compiled_code_[rel_offset + 3] = (final_addr >> 24) & 0xff;
+      }
+
+    } else {
+      LOG(WARNING) << "Unexpected section: " << name.str();
+    }
+  }
+
+  return true;
+}
+
+
+// Check whether the align is less than or equal to the code alignment of
+// that architecture.  Since the Oat writer only guarantee that the compiled
+// method being aligned to kArchAlignment, we have no way to align the ELf
+// section if the section alignment is greater than kArchAlignment.
+void CompilationUnit::CheckCodeAlign(uint32_t align) const {
+  InstructionSet insn_set = GetInstructionSet();
+  switch (insn_set) {
+  case kThumb2:
+  case kArm:
+    CHECK_LE(align, static_cast<uint32_t>(kArmAlignment));
+    break;
+
+  case kX86:
+    CHECK_LE(align, static_cast<uint32_t>(kX86Alignment));
+    break;
+
+  case kMips:
+    CHECK_LE(align, static_cast<uint32_t>(kMipsAlignment));
+    break;
+
+  default:
+    LOG(FATAL) << "Unknown instruction set: " << insn_set;
+  }
+}
+
+
 } // namespace compiler_llvm
 } // namespace art
diff --git a/src/compiler_llvm/compilation_unit.h b/src/compiler_llvm/compilation_unit.h
index d391620..576b65f 100644
--- a/src/compiler_llvm/compilation_unit.h
+++ b/src/compiler_llvm/compilation_unit.h
@@ -18,7 +18,6 @@
 #define ART_SRC_COMPILER_LLVM_COMPILATION_UNIT_H_
 
 #include "../mutex.h"
-#include "elf_image.h"
 #include "globals.h"
 #include "instruction_set.h"
 #include "logging.h"
@@ -44,81 +43,52 @@
 namespace art {
 namespace compiler_llvm {
 
+class CompilerLLVM;
 class IRBuilder;
 
 class CompilationUnit {
  public:
-  CompilationUnit(InstructionSet insn_set, size_t elf_idx);
+  CompilationUnit(const CompilerLLVM* compiler_llvm,
+                  size_t cunit_idx);
 
   ~CompilationUnit();
 
-  size_t GetElfIndex() const {
-    return elf_idx_;
+  size_t GetIndex() const {
+    return cunit_idx_;
   }
 
-  InstructionSet GetInstructionSet() const {
-    cunit_lock_.AssertHeld();
-    return insn_set_;
-  }
+  InstructionSet GetInstructionSet() const;
 
   llvm::LLVMContext* GetLLVMContext() const {
-    cunit_lock_.AssertHeld();
     return context_.get();
   }
 
   llvm::Module* GetModule() const {
-    cunit_lock_.AssertHeld();
     return module_;
   }
 
   IRBuilder* GetIRBuilder() const {
-    cunit_lock_.AssertHeld();
     return irb_.get();
   }
 
-  ElfImage GetElfImage() const {
-    MutexLock GUARD(cunit_lock_);
-    CHECK_GT(elf_image_.size(), 0u);
-    return ElfImage(elf_image_);
-  }
-
-  uint16_t AcquireUniqueElfFuncIndex() {
-    cunit_lock_.AssertHeld();
-    CHECK(num_elf_funcs_ < UINT16_MAX);
-    return num_elf_funcs_++;
-  }
-
   void SetBitcodeFileName(const std::string& bitcode_filename) {
-    MutexLock GUARD(cunit_lock_);
     bitcode_filename_ = bitcode_filename;
   }
 
-  bool Materialize(size_t thread_count);
+  bool Materialize();
 
   bool IsMaterialized() const {
-    MutexLock GUARD(cunit_lock_);
     return (context_.get() == NULL);
   }
 
-  bool IsMaterializeThresholdReached() const {
-    MutexLock GUARD(cunit_lock_);
-    return (mem_usage_ > 1000000u); // (threshold: 1 MB)
+  const std::vector<uint8_t>& GetCompiledCode() const {
+    DCHECK(IsMaterialized());
+    return compiled_code_;
   }
 
-  void AddMemUsageApproximation(size_t usage) {
-    MutexLock GUARD(cunit_lock_);
-    mem_usage_ += usage;
-  }
-
-  void RegisterCompiledMethod(const llvm::Function* func, CompiledMethod* cm);
-
-  void UpdateFrameSizeInBytes(const llvm::Function* func, size_t frame_size_in_bytes);
-
-  mutable Mutex cunit_lock_;
-
  private:
-  InstructionSet insn_set_;
-  const size_t elf_idx_;
+  const CompilerLLVM* compiler_llvm_;
+  const size_t cunit_idx_;
 
   UniquePtr<llvm::LLVMContext> context_;
   UniquePtr<IRBuilder> irb_;
@@ -126,15 +96,24 @@
   llvm::Module* module_;
 
   std::string bitcode_filename_;
-  std::string elf_image_;
 
-  typedef SafeMap<const llvm::Function*, CompiledMethod*> CompiledMethodMap;
-  UniquePtr<CompiledMethodMap> compiled_methods_map_;
+  std::vector<uint8_t> compiled_code_;
 
-  size_t mem_usage_;
-  uint16_t num_elf_funcs_;
+  SafeMap<const llvm::Function*, CompiledMethod*> compiled_methods_map_;
 
-  bool MaterializeToFile(llvm::raw_ostream& out_stream);
+  void CheckCodeAlign(uint32_t offset) const;
+
+  void DeleteResources() {
+    module_ = NULL; // Managed by context_
+    context_.reset(NULL);
+    irb_.reset(NULL);
+    runtime_support_.reset(NULL);
+  }
+
+  bool MaterializeToString(std::string& str_buffer);
+  bool MaterializeToRawOStream(llvm::raw_ostream& out_stream);
+
+  bool ExtractCodeAndPrelink(const std::string& elf_image);
 };
 
 } // namespace compiler_llvm
diff --git a/src/compiler_llvm/compiler_llvm.cc b/src/compiler_llvm/compiler_llvm.cc
index 6c8188e..b793fbd 100644
--- a/src/compiler_llvm/compiler_llvm.cc
+++ b/src/compiler_llvm/compiler_llvm.cc
@@ -22,8 +22,6 @@
 #include "compiled_method.h"
 #include "compiler.h"
 #include "dex_cache.h"
-#include "elf_image.h"
-#include "elf_loader.h"
 #include "ir_builder.h"
 #include "jni_compiler.h"
 #include "method_compiler.h"
@@ -95,9 +93,9 @@
 
 
 CompilerLLVM::CompilerLLVM(Compiler* compiler, InstructionSet insn_set)
-    : compiler_(compiler), compiler_lock_("llvm_compiler_lock"),
-      insn_set_(insn_set), curr_cunit_(NULL) {
-
+    : compiler_(compiler), insn_set_(insn_set),
+      num_cunits_lock_("compilation unit counter lock"), num_cunits_(0),
+      plt_(insn_set) {
 
   // Initialize LLVM libraries
   pthread_once(&llvm_initialized, InitializeLLVM);
@@ -105,152 +103,21 @@
 
 
 CompilerLLVM::~CompilerLLVM() {
-  STLDeleteElements(&cunits_);
 }
 
 
-void CompilerLLVM::EnsureCompilationUnit() {
-  compiler_lock_.AssertHeld();
-
-  if (curr_cunit_ != NULL) {
-    return;
-  }
-
-  // Allocate compilation unit
-  size_t cunit_idx = cunits_.size();
-  curr_cunit_ = new CompilationUnit(insn_set_, cunit_idx);
-
-  // Register compilation unit
-  cunits_.push_back(curr_cunit_);
-}
-
-
-void CompilerLLVM::MaterializeRemainder() {
-  compiler_lock_.Lock();
-  // Localize
-  CompilationUnit* cunit = curr_cunit_;
-  // Reset the curr_cuit_
-  curr_cunit_ = NULL;
-  compiler_lock_.Unlock();
-
-  if (cunit != NULL) {
-    Materialize(cunit);
-  }
-}
-
-
-void CompilerLLVM::MaterializeIfThresholdReached() {
-  compiler_lock_.Lock();
-  // Localize
-  CompilationUnit* cunit = curr_cunit_;
-
-  if (curr_cunit_ != NULL && curr_cunit_->IsMaterializeThresholdReached()) {
-    // Delete the compilation unit
-    curr_cunit_ = NULL;
-  } else {
-    // Reset cunit such that Materialize() won't be invoked
-    cunit = NULL;
-  }
-
-  compiler_lock_.Unlock();
-
-  if (cunit != NULL) {
-    Materialize(cunit);
-  }
-}
-
-
-void CompilerLLVM::Materialize(CompilationUnit* cunit) {
-  DCHECK(cunit != NULL);
-  DCHECK(!cunit->IsMaterialized());
-
-  // Write bitcode to file when filename is set
-  if (IsBitcodeFileNameAvailable()) {
-    const size_t cunit_idx = cunits_.size();
-    cunit->SetBitcodeFileName(
-      StringPrintf("%s-%zu", bitcode_filename_.c_str(), cunit_idx));
-  }
-
-  // Materialize the llvm::Module into ELF object file
-  cunit->Materialize(compiler_->GetThreadCount());
-
-  // Load ELF image when automatic ELF loading is enabled
-  if (IsAutoElfLoadingEnabled()) {
-    LoadElfFromCompilationUnit(cunit);
-  }
-}
-
-
-void CompilerLLVM::EnableAutoElfLoading() {
-  MutexLock GUARD(compiler_lock_);
-
-  if (IsAutoElfLoadingEnabled()) {
-    // If there is an existing ELF loader, then do nothing.
-    // Because the existing ELF loader may have returned some code address
-    // already.  If we replace the existing ELF loader with
-    // elf_loader_.reset(...), then it is possible to have some dangling
-    // pointer.
-    return;
-  }
-
-  // Create ELF loader and load the materialized CompilationUnit
-  elf_loader_.reset(new ElfLoader());
-
-  for (size_t i = 0; i < cunits_.size(); ++i) {
-    if (cunits_[i]->IsMaterialized()) {
-      LoadElfFromCompilationUnit(cunits_[i]);
-    }
-  }
-}
-
-
-void CompilerLLVM::LoadElfFromCompilationUnit(const CompilationUnit* cunit) {
-  MutexLock GUARD(compiler_lock_);
-  DCHECK(cunit->IsMaterialized()) << cunit->GetElfIndex();
-
-  if (!elf_loader_->LoadElfAt(cunit->GetElfIndex(),
-                              cunit->GetElfImage(),
-                              OatFile::kRelocAll)) {
-    LOG(ERROR) << "Failed to load ELF from compilation unit "
-               << cunit->GetElfIndex();
-  }
-}
-
-
-const void* CompilerLLVM::GetMethodCodeAddr(const CompiledMethod* cm) const {
-  return elf_loader_->GetMethodCodeAddr(cm->GetElfIndex(),
-                                        cm->GetElfFuncIndex());
-}
-
-
-const Method::InvokeStub* CompilerLLVM::
-GetMethodInvokeStubAddr(const CompiledInvokeStub* cm) const {
-  return elf_loader_->GetMethodInvokeStubAddr(cm->GetElfIndex(),
-                                              cm->GetElfFuncIndex());
-}
-
-
-std::vector<ElfImage> CompilerLLVM::GetElfImages() const {
-  std::vector<ElfImage> result;
-
-  for (size_t i = 0; i < cunits_.size(); ++i) {
-    result.push_back(cunits_[i]->GetElfImage());
-  }
-
-  return result;
+CompilationUnit* CompilerLLVM::AllocateCompilationUnit() {
+  MutexLock GUARD(num_cunits_lock_);
+  return new CompilationUnit(this, num_cunits_++);
 }
 
 
 CompiledMethod* CompilerLLVM::
 CompileDexMethod(OatCompilationUnit* oat_compilation_unit) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<MethodCompiler> method_compiler(
-      new MethodCompiler(curr_cunit_, compiler_, oat_compilation_unit));
+      new MethodCompiler(cunit.get(), compiler_, oat_compilation_unit));
 
   return method_compiler->Compile();
 }
@@ -258,14 +125,10 @@
 
 CompiledMethod* CompilerLLVM::
 CompileNativeMethod(OatCompilationUnit* oat_compilation_unit) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<JniCompiler> jni_compiler(
-      new JniCompiler(curr_cunit_, *compiler_, oat_compilation_unit));
+      new JniCompiler(cunit.get(), *compiler_, oat_compilation_unit));
 
   return jni_compiler->Compile();
 }
@@ -273,28 +136,20 @@
 
 CompiledInvokeStub* CompilerLLVM::CreateInvokeStub(bool is_static,
                                                    char const *shorty) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<StubCompiler> stub_compiler(
-    new StubCompiler(curr_cunit_, *compiler_));
+    new StubCompiler(cunit.get(), *compiler_));
 
   return stub_compiler->CreateInvokeStub(is_static, shorty);
 }
 
 
 CompiledInvokeStub* CompilerLLVM::CreateProxyStub(char const *shorty) {
-  MutexLock GUARD(compiler_lock_);
-
-  EnsureCompilationUnit();
-
-  MutexLock GUARD_CUNIT(curr_cunit_->cunit_lock_);
+  UniquePtr<CompilationUnit> cunit(AllocateCompilationUnit());
 
   UniquePtr<StubCompiler> stub_compiler(
-    new StubCompiler(curr_cunit_, *compiler_));
+    new StubCompiler(cunit.get(), *compiler_));
 
   return stub_compiler->CreateProxyStub(shorty);
 }
@@ -324,6 +179,11 @@
   compiler.SetCompilerContext(compiler_llvm);
 }
 
+extern "C" void ArtUnInitCompilerContext(art::Compiler& compiler) {
+  delete ContextOf(compiler);
+  compiler.SetCompilerContext(NULL);
+}
+
 extern "C" art::CompiledMethod* ArtCompileMethod(art::Compiler& compiler,
                                                  const art::DexFile::CodeItem* code_item,
                                                  uint32_t access_flags, uint32_t method_idx,
@@ -338,7 +198,6 @@
     method_idx, access_flags);
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledMethod* result = compiler_llvm->CompileDexMethod(&oat_compilation_unit);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -354,7 +213,6 @@
 
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledMethod* result = compiler_llvm->CompileNativeMethod(&oat_compilation_unit);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -364,7 +222,6 @@
                                                         uint32_t shorty_len) {
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledInvokeStub* result = compiler_llvm->CreateInvokeStub(is_static, shorty);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -373,7 +230,6 @@
                                                        uint32_t shorty_len) {
   art::compiler_llvm::CompilerLLVM* compiler_llvm = ContextOf(compiler);
   art::CompiledInvokeStub* result = compiler_llvm->CreateProxyStub(shorty);
-  compiler_llvm->MaterializeIfThresholdReached();
   return result;
 }
 
@@ -381,37 +237,3 @@
                                                std::string const& filename) {
   ContextOf(compiler)->SetBitcodeFileName(filename);
 }
-
-extern "C" void compilerLLVMMaterializeRemainder(art::Compiler& compiler) {
-  ContextOf(compiler)->MaterializeRemainder();
-}
-
-extern "C" void compilerLLVMEnableAutoElfLoading(art::Compiler& compiler) {
-  art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->EnableAutoElfLoading();
-}
-
-extern "C" const void* compilerLLVMGetMethodCodeAddr(const art::Compiler& compiler,
-                                                     const art::CompiledMethod* cm,
-                                                     const art::Method*) {
-  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodCodeAddr(cm);
-}
-
-extern "C" const art::Method::InvokeStub* compilerLLVMGetMethodInvokeStubAddr(const art::Compiler& compiler,
-                                                                              const art::CompiledInvokeStub* cm,
-                                                                              const art::Method*) {
-  const art::compiler_llvm::CompilerLLVM* compiler_llvm =
-      reinterpret_cast<const art::compiler_llvm::CompilerLLVM*>(compiler.GetCompilerContext());
-  return compiler_llvm->GetMethodInvokeStubAddr(cm);
-}
-
-extern "C" std::vector<art::ElfImage> compilerLLVMGetElfImages(const art::Compiler& compiler) {
-  return ContextOf(compiler)->GetElfImages();
-}
-
-extern "C" void compilerLLVMDispose(art::Compiler& compiler) {
-  delete ContextOf(compiler);
-}
diff --git a/src/compiler_llvm/compiler_llvm.h b/src/compiler_llvm/compiler_llvm.h
index 7cc4a0e..24a766e 100644
--- a/src/compiler_llvm/compiler_llvm.h
+++ b/src/compiler_llvm/compiler_llvm.h
@@ -19,10 +19,10 @@
 
 #include "compiler.h"
 #include "dex_file.h"
-#include "elf_image.h"
 #include "instruction_set.h"
 #include "macros.h"
 #include "object.h"
+#include "procedure_linkage_table.h"
 
 #include <UniquePtr.h>
 
@@ -54,7 +54,6 @@
 namespace compiler_llvm {
 
 class CompilationUnit;
-class ElfLoader;
 class IRBuilder;
 
 class CompilerLLVM {
@@ -63,10 +62,6 @@
 
   ~CompilerLLVM();
 
-  void MaterializeIfThresholdReached();
-
-  void MaterializeRemainder();
-
   Compiler* GetCompiler() const {
     return compiler_;
   }
@@ -75,31 +70,10 @@
     return insn_set_;
   }
 
-  size_t GetNumCompilationUnits() const {
-    return cunits_.size();
-  }
-
-  const CompilationUnit* GetCompilationUnit(size_t i) const {
-    return cunits_[i];
-  }
-
   void SetBitcodeFileName(std::string const& filename) {
     bitcode_filename_ = filename;
   }
 
-  void EnableAutoElfLoading();
-
-  bool IsAutoElfLoadingEnabled() const {
-    return (elf_loader_.get() != NULL);
-  }
-
-  const void* GetMethodCodeAddr(const CompiledMethod* cm) const;
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(
-                                const CompiledInvokeStub* cm) const;
-
-  std::vector<ElfImage> GetElfImages() const;
-
   CompiledMethod* CompileDexMethod(OatCompilationUnit* oat_compilation_unit);
 
   CompiledMethod* CompileNativeMethod(OatCompilationUnit* oat_compilation_unit);
@@ -108,32 +82,29 @@
 
   CompiledInvokeStub* CreateProxyStub(const char *shorty);
 
+  const ProcedureLinkageTable& GetProcedureLinkageTable() const {
+    return plt_;
+  }
+
  private:
-  void EnsureCompilationUnit();
+  CompilationUnit* AllocateCompilationUnit();
 
   void Materialize(CompilationUnit* cunit);
 
-  void LoadElfFromCompilationUnit(const CompilationUnit* cunit);
-
   bool IsBitcodeFileNameAvailable() const {
     return !bitcode_filename_.empty();
   }
 
   Compiler* compiler_;
 
- public:
-  Mutex compiler_lock_;
-
- private:
   InstructionSet insn_set_;
 
-  CompilationUnit* curr_cunit_;
-
-  std::vector<CompilationUnit*> cunits_;
+  Mutex num_cunits_lock_;
+  size_t num_cunits_;
 
   std::string bitcode_filename_;
 
-  UniquePtr<ElfLoader> elf_loader_;
+  ProcedureLinkageTable plt_;
 
   DISALLOW_COPY_AND_ASSIGN(CompilerLLVM);
 };
diff --git a/src/compiler_llvm/elf_loader.cc b/src/compiler_llvm/elf_loader.cc
deleted file mode 100644
index 8432a07..0000000
--- a/src/compiler_llvm/elf_loader.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "elf_loader.h"
-
-#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"
-
-#include <android/librsloader.h>
-
-namespace art {
-namespace compiler_llvm {
-
-
-ElfLoader::~ElfLoader() {
-  // Release every ELF object
-  for (size_t i = 0; i < executables_.size(); ++i) {
-    rsloaderDisposeExec(executables_[i]);
-  }
-}
-
-
-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;
-  }
-
-  if (elf_idx >= executables_.size()) {
-    executables_.resize(elf_idx + 1);
-    elf_images_.resize(elf_idx + 1);
-  }
-
-  RSExecRef executable = rsloaderLoadExecutable(elf_image.begin(),
-                                                elf_image.size(),
-                                                reloc == OatFile::kRelocNone ? 1 : 0);
-
-  if (executable == NULL) {
-    LOG(WARNING) << "Failed to load ELF"
-                 << " image: " << static_cast<const void*>(elf_image.begin())
-                 << " size: " << elf_image.size();
-    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;
-    }
-    relocated = true;
-  }
-
-  executables_[elf_idx] = executable;
-  elf_images_[elf_idx] = elf_image;
-  return true;
-}
-
-
-void ElfLoader::RelocateExecutable() {
-  if (relocated) {
-    return;
-  }
-  LOG(INFO) << "Reload ELF for relocate.";
-  for (size_t i = 0; i < executables_.size(); ++i) {
-    if (executables_[i] != NULL) {
-      // TODO: After implement in-place linking, we will no longer need to dispose and reload.
-      rsloaderDisposeExec(executables_[i]);
-      executables_[i] = rsloaderLoadExecutable(elf_images_[i].begin(), elf_images_[i].size(), 0);
-      if (executables_[i] == NULL) {
-        LOG(FATAL) << "Failed to reload ELF image " << i;
-      }
-      if (!rsloaderRelocateExecutable(executables_[i],
-                                      art_find_runtime_support_func, NULL)) {
-        LOG(FATAL) << "Failed to relocate ELF image " << i;
-      }
-    }
-  }
-  relocated = true;
-}
-
-
-const void* ElfLoader::GetMethodCodeAddr(uint16_t elf_idx,
-                                         uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  return GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str());
-}
-
-
-const Method::InvokeStub* ElfLoader::
-GetMethodInvokeStubAddr(uint16_t elf_idx, uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  return reinterpret_cast<const Method::InvokeStub*>(
-      GetAddr(elf_idx, ElfFuncName(elf_func_idx).c_str()));
-}
-
-
-size_t ElfLoader::GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const {
-  CHECK_LT(elf_idx, executables_.size());
-  CHECK(executables_[elf_idx] != NULL);
-  return rsloaderGetSymbolSize(executables_[elf_idx],
-                               ElfFuncName(elf_func_idx).c_str());
-}
-
-
-const void* ElfLoader::GetAddr(size_t elf_idx, const char* sym_name) const {
-  CHECK_LT(elf_idx, executables_.size());
-  CHECK(executables_[elf_idx] != NULL);
-  return rsloaderGetSymbolAddress(executables_[elf_idx], sym_name);
-}
-
-
-} // namespace compiler_llvm
-} // namespace art
diff --git a/src/compiler_llvm/elf_loader.h b/src/compiler_llvm/elf_loader.h
deleted file mode 100644
index 9e8611c..0000000
--- a/src/compiler_llvm/elf_loader.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
-#define ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
-
-#include "elf_image.h"
-#include "globals.h"
-#include "oat_file.h"
-#include "object.h"
-
-#include <android/librsloader.h>
-#include <vector>
-
-namespace art {
-namespace compiler_llvm {
-
-class ElfLoader {
- public:
-  ElfLoader() : relocated(false) {}
-  ~ElfLoader();
-
-  bool LoadElfAt(size_t elf_idx, const ElfImage& elf_image,
-                 OatFile::RelocationBehavior reloc);
-
-  void RelocateExecutable();
-
-  const void* GetMethodCodeAddr(uint16_t elf_idx,
-                                uint16_t elf_func_idx) const;
-
-  const Method::InvokeStub* GetMethodInvokeStubAddr(uint16_t elf_idx,
-                                                    uint16_t elf_func_idx) const;
-
-  size_t GetCodeSize(uint16_t elf_idx, uint16_t elf_func_idx) const;
-
- private:
-  const void* GetAddr(size_t elf_idx, const char* sym_name) const;
-
-  bool relocated;
-  std::vector<ElfImage> elf_images_;
-  std::vector<RSExecRef> executables_;
-};
-
-
-} // namespace compiler_llvm
-} // namespace art
-
-#endif // ART_SRC_COMPILER_LLVM_ELF_LOADER_H_
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 37ca82f..f4f5be5 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -51,8 +51,7 @@
   class_loader_(oat_compilation_unit->class_loader_),
   dex_cache_(oat_compilation_unit->dex_cache_),
   dex_file_(oat_compilation_unit->dex_file_),
-  method_(dex_cache_->GetResolvedMethod(method_idx_)),
-  elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+  method_(dex_cache_->GetResolvedMethod(method_idx_)) {
 
   // Check: Ensure that the method is resolved
   CHECK_NE(method_, static_cast<art::Method*>(NULL));
@@ -262,26 +261,16 @@
   // Verify the generated bitcode
   VERIFY_LLVM_FUNCTION(*func_);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((sirt_size * 4 + 50) * 50);
-  // NOTE: We will emit 4 LLVM instructions per object argument,
-  // And about 50 instructions for other operations. (Some runtime support will be inlined.)
-  // Beside, we guess that we have to use 50 bytes to represent one LLVM instruction.
+  cunit_->Materialize();
 
-  CompiledMethod* compiled_method =
-      new CompiledMethod(cunit_->GetInstructionSet(),
-                         cunit_->GetElfIndex(),
-                         elf_func_idx_);
-
-  cunit_->RegisterCompiledMethod(func_, compiled_method);
-
-  return compiled_method;
+  return new CompiledMethod(cunit_->GetInstructionSet(),
+                            cunit_->GetCompiledCode());
 }
 
 
 void JniCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(ElfFuncName(elf_func_idx_));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get function type
   llvm::FunctionType* func_type =
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index eef71db..da8f91a 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -72,8 +72,7 @@
     basic_block_landing_pads_(code_item_->tries_size_, NULL),
     basic_block_unwind_(NULL), basic_block_unreachable_(NULL),
     shadow_frame_(NULL), old_shadow_frame_(NULL),
-    already_pushed_shadow_frame_(NULL), shadow_frame_size_(0),
-    elf_func_idx_(cunit_->AcquireUniqueElfFuncIndex()) {
+    already_pushed_shadow_frame_(NULL), shadow_frame_size_(0) {
 }
 
 
@@ -84,7 +83,7 @@
 
 void MethodCompiler::CreateFunction() {
   // LLVM function name
-  std::string func_name(ElfFuncName(elf_func_idx_));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get function type
   llvm::FunctionType* func_type =
@@ -3616,20 +3615,10 @@
   // Verify the generated bitcode
   VERIFY_LLVM_FUNCTION(*func_);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation(code_item_->insns_size_in_code_units_ * 900);
-  // NOTE: From statistics, the bitcode size is 4.5 times bigger than the
-  // Dex file.  Besides, we have to convert the code unit into bytes.
-  // Thus, we got our magic number 9.
+  cunit_->Materialize();
 
-  CompiledMethod* compiled_method =
-    new CompiledMethod(cunit_->GetInstructionSet(),
-                       cunit_->GetElfIndex(),
-                       elf_func_idx_);
-
-  cunit_->RegisterCompiledMethod(func_, compiled_method);
-
-  return compiled_method;
+  return new CompiledMethod(cunit_->GetInstructionSet(),
+                            cunit_->GetCompiledCode());
 }
 
 
diff --git a/src/compiler_llvm/stub_compiler.cc b/src/compiler_llvm/stub_compiler.cc
index 0d64f0d..af05e52 100644
--- a/src/compiler_llvm/stub_compiler.cc
+++ b/src/compiler_llvm/stub_compiler.cc
@@ -48,13 +48,11 @@
 
 CompiledInvokeStub* StubCompiler::CreateInvokeStub(bool is_static,
                                                    char const* shorty) {
-  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
-
   CHECK(shorty != NULL);
   size_t shorty_size = strlen(shorty);
 
   // Function name
-  std::string func_name(ElfFuncName(elf_func_idx));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Get argument types
   llvm::Type* arg_types[] = {
@@ -186,15 +184,10 @@
   // Verify the generated function
   VERIFY_LLVM_FUNCTION(*func);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((shorty_size * 3 + 8) * 50);
-  // NOTE: We will emit 3 LLVM instructions per shorty for the argument,
-  // plus 3 for pointer arithmetic, and 5 for code_addr, retval, ret_addr,
-  // store ret_addr, and ret_void.  Beside, we guess that we have to use
-  // 50 bytes to represent one LLVM instruction.
+  cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetElfIndex(), elf_func_idx);
+                                cunit_->GetCompiledCode());
 }
 
 
@@ -202,10 +195,8 @@
   CHECK(shorty != NULL);
   size_t shorty_size = strlen(shorty);
 
-  uint16_t elf_func_idx = cunit_->AcquireUniqueElfFuncIndex();
-
   // Function name
-  std::string func_name(ElfFuncName(elf_func_idx));
+  std::string func_name(ElfFuncName(cunit_->GetIndex()));
 
   // Accurate function type
   llvm::Type* accurate_ret_type = irb_.getJType(shorty[0], kAccurate);
@@ -266,11 +257,10 @@
   // Verify the generated function
   VERIFY_LLVM_FUNCTION(*func);
 
-  // Add the memory usage approximation of the compilation unit
-  cunit_->AddMemUsageApproximation((shorty_size + 2) * 50);
+  cunit_->Materialize();
 
   return new CompiledInvokeStub(cunit_->GetInstructionSet(),
-                                cunit_->GetElfIndex(), elf_func_idx);
+                                cunit_->GetCompiledCode());
 }
 
 
diff --git a/src/compiler_llvm/utils_llvm.h b/src/compiler_llvm/utils_llvm.h
index dd35f0a..eb5fd53 100644
--- a/src/compiler_llvm/utils_llvm.h
+++ b/src/compiler_llvm/utils_llvm.h
@@ -32,8 +32,8 @@
 #define VERIFY_LLVM_FUNCTION(func)
 #endif
 
-inline static std::string ElfFuncName(uint16_t elf_func_idx) {
-  return StringPrintf("Art%u", static_cast<unsigned int>(elf_func_idx));
+inline static std::string ElfFuncName(uint16_t idx) {
+  return StringPrintf("Art%u", static_cast<unsigned int>(idx));
 }
 
 class CStringLessThanComparator {
diff --git a/src/elf_image.h b/src/elf_image.h
deleted file mode 100644
index 094467a..0000000
--- a/src/elf_image.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ART_SRC_ELF_IMAGE_H_
-#define ART_SRC_ELF_IMAGE_H_
-
-#include "globals.h"
-#include <string>
-#include <vector>
-
-namespace art {
-
-class ElfImage {
- public:
-  explicit ElfImage(const std::vector<uint8_t>& v)
-      : begin_(&*v.begin()), size_(v.size()) {
-  }
-
-  explicit ElfImage(const std::string& s)
-      : begin_(reinterpret_cast<const uint8_t*>(s.data())), size_(s.size()) {
-  }
-
-  explicit ElfImage(const byte* begin, size_t size)
-      : begin_(begin), size_(size) {
-  }
-
-  // TODO: Remove this after implement in-place linking.
-  ElfImage() : begin_(NULL), size_(0) {
-  }
-
-  const byte* begin() const {
-    return begin_;
-  }
-
-  const byte* end() const {
-    return (begin_ + size_);
-  }
-
-  size_t size() const {
-    return size_;
-  }
-
- private:
-  const byte* begin_;
-  size_t size_;
-};
-
-} // namespace art
-
-#endif // ART_SRC_ELF_IMAGE_H_
diff --git a/src/oat.cc b/src/oat.cc
index ce7c133..cd9e0a3 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -29,7 +29,6 @@
 
 OatHeader::OatHeader(InstructionSet instruction_set,
                      const std::vector<const DexFile*>* dex_files,
-                     uint32_t elf_image_count,
                      uint32_t image_file_location_checksum,
                      const std::string& image_file_location) {
   memcpy(magic_, kOatMagic, sizeof(kOatMagic));
@@ -43,9 +42,6 @@
   dex_file_count_ = dex_files->size();
   UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
 
-  elf_image_count_ = elf_image_count;
-  UpdateChecksum(&elf_image_count_, sizeof(elf_image_count_));
-
   image_file_location_checksum_ = image_file_location_checksum;
   UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_));
 
@@ -53,7 +49,6 @@
   UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
   UpdateChecksum(image_file_location.data(), image_file_location_size_);
 
-  elf_image_table_offset_ = 0;
   executable_offset_ = 0;
 }
 
@@ -77,16 +72,6 @@
   return dex_file_count_;
 }
 
-uint32_t OatHeader::GetElfImageCount() const {
-  DCHECK(IsValid());
-  return elf_image_count_;
-}
-
-uint32_t OatHeader::GetElfImageTableOffset() const {
-  DCHECK(IsValid());
-  return elf_image_table_offset_;
-}
-
 uint32_t OatHeader::GetChecksum() const {
   CHECK(IsValid());
   return adler32_checksum_;
@@ -131,12 +116,6 @@
                      GetImageFileLocationSize());
 }
 
-void OatHeader::SetElfImageTableOffset(uint32_t elf_image_table_offset) {
-  DCHECK(IsValid());
-  elf_image_table_offset_ = elf_image_table_offset;
-  UpdateChecksum(&elf_image_table_offset_, sizeof(elf_image_table_offset_));
-}
-
 void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
   DCHECK_ALIGNED(executable_offset, kPageSize);
   CHECK_GT(executable_offset, sizeof(OatHeader));
@@ -156,12 +135,6 @@
     vmap_table_offset_(0),
     gc_map_offset_(0),
     invoke_stub_offset_(0)
-#if defined(ART_USE_LLVM_COMPILER)
-  , code_elf_idx_(static_cast<uint16_t>(-1u)),
-    code_elf_func_idx_(static_cast<uint16_t>(-1u)),
-    invoke_stub_elf_idx_(static_cast<uint16_t>(-1u)),
-    invoke_stub_elf_func_idx_(static_cast<uint16_t>(-1u))
-#endif
 {}
 
 OatMethodOffsets::OatMethodOffsets(uint32_t code_offset,
@@ -173,12 +146,7 @@
                                    uint32_t gc_map_offset,
                                    uint32_t invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-                                 , uint16_t code_elf_idx,
-                                   uint16_t code_elf_func_idx,
-                                   uint16_t invoke_stub_elf_idx,
-                                   uint16_t invoke_stub_elf_func_idx,
-                                   uint16_t proxy_stub_elf_idx,
-                                   uint16_t proxy_stub_elf_func_idx
+                                 , uint32_t proxy_stub_offset
 #endif
                                    )
   : code_offset_(code_offset),
@@ -190,12 +158,7 @@
     gc_map_offset_(gc_map_offset),
     invoke_stub_offset_(invoke_stub_offset)
 #if defined(ART_USE_LLVM_COMPILER)
-  , code_elf_idx_(code_elf_idx),
-    code_elf_func_idx_(code_elf_func_idx),
-    invoke_stub_elf_idx_(invoke_stub_elf_idx),
-    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx),
-    proxy_stub_elf_idx_(proxy_stub_elf_idx),
-    proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx)
+  , proxy_stub_offset_(proxy_stub_offset)
 #endif
 {}
 
diff --git a/src/oat.h b/src/oat.h
index d1e177f..cd3330b 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -30,7 +30,6 @@
   OatHeader();
   OatHeader(InstructionSet instruction_set,
             const std::vector<const DexFile*>* dex_files,
-            uint32_t elf_image_count,
             uint32_t image_file_location_checksum,
             const std::string& image_file_location);
 
@@ -39,11 +38,8 @@
   uint32_t GetChecksum() const;
   void UpdateChecksum(const void* data, size_t length);
   uint32_t GetDexFileCount() const;
-  uint32_t GetElfImageCount() const;
-  uint32_t GetElfImageTableOffset() const;
   uint32_t GetExecutableOffset() const;
   InstructionSet GetInstructionSet() const;
-  void SetElfImageTableOffset(uint32_t elf_image_offset);
   void SetExecutableOffset(uint32_t executable_offset);
   uint32_t GetImageFileLocationChecksum() const;
   uint32_t GetImageFileLocationSize() const;
@@ -60,8 +56,6 @@
 
   InstructionSet instruction_set_;
   uint32_t dex_file_count_;
-  uint32_t elf_image_count_;
-  uint32_t elf_image_table_offset_;
   uint32_t executable_offset_;
 
   uint32_t image_file_location_checksum_;
@@ -74,6 +68,7 @@
 class PACKED OatMethodOffsets {
  public:
   OatMethodOffsets();
+
   OatMethodOffsets(uint32_t code_offset,
                    uint32_t frame_size_in_bytes,
                    uint32_t core_spill_mask,
@@ -83,14 +78,10 @@
                    uint32_t gc_map_offset,
                    uint32_t invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-                 , uint16_t code_elf_idx,
-                   uint16_t code_elf_func_idx,
-                   uint16_t invoke_stub_elf_idx,
-                   uint16_t invoke_stub_elf_func_idx,
-                   uint16_t proxy_stub_elf_idx,
-                   uint16_t proxy_stub_elf_func_idx
+                 , uint32_t proxy_stub_offset
 #endif
                    );
+
   ~OatMethodOffsets();
 
   uint32_t code_offset_;
@@ -103,12 +94,7 @@
   uint32_t invoke_stub_offset_;
 
 #if defined(ART_USE_LLVM_COMPILER)
-  uint16_t code_elf_idx_;
-  uint16_t code_elf_func_idx_;
-  uint16_t invoke_stub_elf_idx_;
-  uint16_t invoke_stub_elf_func_idx_;
-  uint16_t proxy_stub_elf_idx_;
-  uint16_t proxy_stub_elf_func_idx_;
+  uint32_t proxy_stub_offset_;
 #endif
 };
 
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 239239b..f64f512 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -20,10 +20,6 @@
 #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) {
@@ -64,19 +60,12 @@
 }
 
 OatFile::OatFile(const std::string& location)
-    : location_(location)
-#if defined(ART_USE_LLVM_COMPILER)
-    , elf_loader_(new compiler_llvm::ElfLoader())
-#endif
-{
+    : location_(location) {
   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,
@@ -182,31 +171,6 @@
                                                          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_EQ((reinterpret_cast<uintptr_t>(oat) & 0x3), 0u);
-
-  for (uint32_t i = 0, end = oat_header.GetElfImageCount(); i < end; ++i) {
-    uint32_t elf_offset = *reinterpret_cast<const uint32_t*>(oat);
-    oat += sizeof(uint32_t);
-
-    uint32_t elf_size = *reinterpret_cast<const uint32_t*>(oat);
-    oat += sizeof(uint32_t);
-
-    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;
 }
@@ -246,9 +210,7 @@
 }
 
 void OatFile::RelocateExecutable() {
-#if defined(ART_USE_LLVM_COMPILER)
-  elf_loader_->RelocateExecutable();
-#endif
+  UNIMPLEMENTED(WARNING) << "Relocate the executable";
 }
 
 OatFile::OatDexFile::OatDexFile(const OatFile* oat_file,
@@ -308,13 +270,7 @@
       oat_method_offsets.gc_map_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.code_elf_func_idx_,
-      oat_method_offsets.invoke_stub_elf_idx_,
-      oat_method_offsets.invoke_stub_elf_func_idx_,
-      oat_method_offsets.proxy_stub_elf_idx_,
-      oat_method_offsets.proxy_stub_elf_func_idx_
+    , oat_method_offsets.proxy_stub_offset_
 #endif
       );
 }
@@ -329,13 +285,7 @@
                               const uint32_t gc_map_offset,
                               const uint32_t invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-                            , const compiler_llvm::ElfLoader* elf_loader,
-                              const uint16_t code_elf_idx,
-                              const uint16_t code_elf_func_idx,
-                              const uint16_t invoke_stub_elf_idx,
-                              const uint16_t invoke_stub_elf_func_idx,
-                              const uint16_t proxy_stub_elf_idx,
-                              const uint16_t proxy_stub_elf_func_idx
+                            , const uint32_t proxy_stub_offset
 #endif
                               )
   : begin_(base),
@@ -348,13 +298,7 @@
     gc_map_offset_(gc_map_offset),
     invoke_stub_offset_(invoke_stub_offset)
 #if defined(ART_USE_LLVM_COMPILER)
-  , elf_loader_(elf_loader),
-    code_elf_idx_(code_elf_idx),
-    code_elf_func_idx_(code_elf_func_idx),
-    invoke_stub_elf_idx_(invoke_stub_elf_idx),
-    invoke_stub_elf_func_idx_(invoke_stub_elf_func_idx),
-    proxy_stub_elf_idx_(proxy_stub_elf_idx),
-    proxy_stub_elf_func_idx_(proxy_stub_elf_func_idx)
+  , proxy_stub_offset_(proxy_stub_offset)
 #endif
 {
 #ifndef NDEBUG
@@ -374,92 +318,37 @@
 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_, code_elf_func_idx_);
-    CHECK(code != NULL);
-    return code;
-#endif
-  }
+  return GetOatPointer<const void*>(code_offset_);
 }
 
 uint32_t OatFile::OatMethod::GetCodeSize() const {
-  if (!IsCodeInElf()) {
-    uintptr_t code = reinterpret_cast<uint32_t>(GetCode());
+  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 {
-#if !defined(ART_USE_LLVM_COMPILER)
-    UNIMPLEMENTED(ERROR);
+  if (code == 0) {
     return 0;
-#else
-    CHECK(elf_loader_ != NULL);
-    return elf_loader_->GetCodeSize(code_elf_idx_, code_elf_func_idx_);
-#endif
   }
+  // TODO: make this Thumb2 specific
+  code &= ~0x1;
+  return reinterpret_cast<uint32_t*>(code)[-1];
 }
 
 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_,
-                                             invoke_stub_elf_func_idx_);
-    CHECK(stub != NULL);
-    return stub;
-#endif
-  }
+  return GetOatPointer<const Method::InvokeStub*>(invoke_stub_offset_);
 }
 
 uint32_t OatFile::OatMethod::GetInvokeStubSize() const {
-  if (!IsInvokeStubInElf()) {
-    uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub());
-    if (code == 0) {
-      return 0;
-    }
-    // TODO: make this Thumb2 specific
-    code &= ~0x1;
-    return reinterpret_cast<uint32_t*>(code)[-1];
-  } else {
-#if !defined(ART_USE_LLVM_COMPILER)
-    UNIMPLEMENTED(WARNING);
+  uintptr_t code = reinterpret_cast<uint32_t>(GetInvokeStub());
+  if (code == 0) {
     return 0;
-#else
-    CHECK(elf_loader_ != NULL);
-    return elf_loader_->GetCodeSize(invoke_stub_elf_idx_,
-                                    invoke_stub_elf_func_idx_);
-#endif
   }
+  // TODO: make this Thumb2 specific
+  code &= ~0x1;
+  return reinterpret_cast<uint32_t*>(code)[-1];
 }
 
 #if defined(ART_USE_LLVM_COMPILER)
 const void* OatFile::OatMethod::GetProxyStub() const {
-  CHECK(elf_loader_ != NULL);
-  const void* stub = NULL;
-  if (proxy_stub_elf_func_idx_ != static_cast<uint16_t>(-1)) {
-    stub = elf_loader_->GetMethodCodeAddr(proxy_stub_elf_idx_,
-                                          proxy_stub_elf_func_idx_);
-    CHECK(stub != NULL);
-  }
-  return stub;
+  return GetOatPointer<const void*>(proxy_stub_offset_);
 }
 #endif
 
@@ -487,12 +376,4 @@
   method->SetOatInvokeStubOffset(GetInvokeStubOffset());
 }
 
-#if defined(ART_USE_LLVM_COMPILER)
-OatFile::OatElfImage::OatElfImage(const OatFile* oat_file,
-                                  const byte* addr,
-                                  uint32_t size)
-    : oat_file_(oat_file), elf_addr_(addr), elf_size_(size) {
-}
-#endif
-
 }  // namespace art
diff --git a/src/oat_file.h b/src/oat_file.h
index a4ca2de..856a033 100644
--- a/src/oat_file.h
+++ b/src/oat_file.h
@@ -25,14 +25,6 @@
 #include "oat.h"
 #include "object.h"
 
-#if defined(ART_USE_LLVM_COMPILER)
-namespace art {
-  namespace compiler_llvm {
-    class ElfLoader;
-  }
-}
-#endif
-
 namespace art {
 
 class OatFile {
@@ -103,37 +95,6 @@
       return invoke_stub_offset_;
     }
 
-#if defined(ART_USE_LLVM_COMPILER)
-    uint16_t GetCodeElfIndex() const {
-      return code_elf_idx_;
-    }
-    uint16_t GetCodeElfFuncIndex() const {
-      return code_elf_func_idx_;
-    }
-    uint16_t GetInvokeStubElfIndex() const {
-      return invoke_stub_elf_idx_;
-    }
-    uint16_t GetInvokeStubElfFuncIndex() const {
-      return invoke_stub_elf_func_idx_;
-    }
-#endif
-
-    bool IsCodeInElf() const {
-#if defined(ART_USE_LLVM_COMPILER)
-      return (code_elf_idx_ != static_cast<uint16_t>(-1));
-#else
-      return false;
-#endif
-    }
-
-    bool IsInvokeStubInElf() const {
-#if defined(ART_USE_LLVM_COMPILER)
-      return (invoke_stub_elf_idx_ != static_cast<uint16_t>(-1));
-#else
-      return false;
-#endif
-    }
-
     const void* GetCode() const;
     uint32_t GetCodeSize() const;
 
@@ -167,13 +128,7 @@
               const uint32_t gc_map_offset,
               const uint32_t invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-            , const compiler_llvm::ElfLoader* elf_loader,
-              const uint16_t code_elf_idx,
-              const uint16_t code_elf_func_idx,
-              const uint16_t invoke_stub_elf_idx,
-              const uint16_t invoke_stub_elf_func_idx,
-              const uint16_t proxy_stub_elf_idx,
-              const uint16_t proxy_stub_elf_func_idx
+            , const uint32_t proxy_stub_offset
 #endif
               );
 
@@ -198,14 +153,7 @@
     uint32_t invoke_stub_offset_;
 
 #if defined(ART_USE_LLVM_COMPILER)
-    const compiler_llvm::ElfLoader* elf_loader_;
-
-    uint16_t code_elf_idx_;
-    uint16_t code_elf_func_idx_;
-    uint16_t invoke_stub_elf_idx_;
-    uint16_t invoke_stub_elf_func_idx_;
-    uint16_t proxy_stub_elf_idx_;
-    uint16_t proxy_stub_elf_func_idx_;
+    uint32_t proxy_stub_offset_;
 #endif
 
     friend class OatClass;
@@ -266,43 +214,10 @@
     DISALLOW_COPY_AND_ASSIGN(OatDexFile);
   };
 
-#if defined(ART_USE_LLVM_COMPILER)
-  class OatElfImage {
-   public:
-    const byte* begin() const {
-      return elf_addr_;
-    }
-
-    const byte* end() const {
-      return (elf_addr_ + elf_size_);
-    }
-
-    size_t size() const {
-      return elf_size_;
-    }
-
-   private:
-    OatElfImage(const OatFile* oat_file, const byte* addr, uint32_t size);
-
-    const OatFile* oat_file_;
-    const byte* elf_addr_;
-    uint32_t elf_size_;
-
-    friend class OatFile;
-    DISALLOW_COPY_AND_ASSIGN(OatElfImage);
-  };
-#endif
-
   const OatDexFile* GetOatDexFile(const std::string& dex_file_location,
                                   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();
   }
@@ -327,11 +242,6 @@
   typedef SafeMap<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;
   friend class OatDumper;  // For GetBase and GetLimit
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 2558eba..013a561 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -20,7 +20,6 @@
 
 #include "class_linker.h"
 #include "class_loader.h"
-#include "elf_image.h"
 #include "file.h"
 #include "os.h"
 #include "safe_map.h"
@@ -53,15 +52,12 @@
   image_file_location_checksum_ = image_file_location_checksum;
   image_file_location_ = image_file_location;
   dex_files_ = &dex_files;
-  elf_images_ = compiler_->GetElfImages();
   oat_header_ = NULL;
   executable_offset_padding_length_ = 0;
 
   size_t offset = InitOatHeader();
   offset = InitOatDexFiles(offset);
   offset = InitDexFiles(offset);
-  offset = InitOatElfImages(offset);
-  offset = InitElfImages(offset);
   offset = InitOatClasses(offset);
   offset = InitOatCode(offset);
   offset = InitOatCodeDexFiles(offset);
@@ -72,7 +68,6 @@
 OatWriter::~OatWriter() {
   delete oat_header_;
   STLDeleteElements(&oat_dex_files_);
-  STLDeleteElements(&oat_elf_images_);
   STLDeleteElements(&oat_classes_);
 }
 
@@ -80,7 +75,6 @@
   // create the OatHeader
   oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
                               dex_files_,
-                              elf_images_.size(),
                               image_file_location_checksum_,
                               image_file_location_);
   size_t offset = sizeof(*oat_header_);
@@ -115,34 +109,6 @@
   return offset;
 }
 
-size_t OatWriter::InitOatElfImages(size_t offset) {
-  size_t n = elf_images_.size();
-  if (n != 0) {
-    // Offset to ELF image table should be rounded up to 4-byte aligned, so that
-    // we can read the uint32_t directly.
-    offset = RoundUp(offset, 4);
-    oat_header_->SetElfImageTableOffset(offset);
-  } else {
-    oat_header_->SetElfImageTableOffset(0);
-  }
-
-  for (size_t i = 0; i < n; ++i) {
-    OatElfImage* oat_elf_image = new OatElfImage(elf_images_[i]);
-    oat_elf_images_.push_back(oat_elf_image);
-    offset += oat_elf_image->SizeOf();
-  }
-  return offset;
-}
-
-size_t OatWriter::InitElfImages(size_t offset) {
-  for (size_t i = 0; i < oat_elf_images_.size(); ++i) {
-    offset = RoundUp(offset, 4);
-    oat_elf_images_[i]->SetElfOffset(offset);
-    offset += oat_elf_images_[i]->GetElfSize();
-  }
-  return offset;
-}
-
 size_t OatWriter::InitOatClasses(size_t offset) {
   // create the OatClasses
   // calculate the offsets within OatDexFiles to OatClasses
@@ -258,10 +224,6 @@
                                     uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
-#if defined(ART_USE_LLVM_COMPILER)
-  uint16_t code_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t code_elf_func_idx = static_cast<uint16_t>(-1u);
-#endif
   uint32_t frame_size_in_bytes = kStackAlignment;
   uint32_t core_spill_mask = 0;
   uint32_t fp_spill_mask = 0;
@@ -271,125 +233,107 @@
   // derived from CompiledInvokeStub if available
   uint32_t invoke_stub_offset = 0;
 #if defined(ART_USE_LLVM_COMPILER)
-  uint16_t invoke_stub_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t invoke_stub_elf_func_idx = static_cast<uint16_t>(-1u);
-  uint16_t proxy_stub_elf_idx = static_cast<uint16_t>(-1u);
-  uint16_t proxy_stub_elf_func_idx = static_cast<uint16_t>(-1u);
+  uint32_t proxy_stub_offset = 0;
 #endif
 
   CompiledMethod* compiled_method =
       compiler_->GetCompiledMethod(Compiler::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
-    if (compiled_method->IsExecutableInElf()) {
-#if defined(ART_USE_LLVM_COMPILER)
-      code_elf_idx = compiled_method->GetElfIndex();
-      code_elf_func_idx = compiled_method->GetElfFuncIndex();
-#endif
-      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    offset = compiled_method->AlignCode(offset);
+    DCHECK_ALIGNED(offset, kArmAlignment);
+    const std::vector<uint8_t>& code = compiled_method->GetCode();
+    uint32_t code_size = code.size() * sizeof(code[0]);
+    CHECK_NE(code_size, 0U);
+    uint32_t thumb_offset = compiled_method->CodeDelta();
+    code_offset = offset + sizeof(code_size) + thumb_offset;
+
+    // Deduplicate code arrays
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
+    if (code_iter != code_offsets_.end()) {
+      code_offset = code_iter->second;
     } else {
-      offset = compiled_method->AlignCode(offset);
-      DCHECK_ALIGNED(offset, kArmAlignment);
-      const std::vector<uint8_t>& code = compiled_method->GetCode();
-      uint32_t code_size = code.size() * sizeof(code[0]);
-      CHECK_NE(code_size, 0U);
-      uint32_t thumb_offset = compiled_method->CodeDelta();
-      code_offset = offset + sizeof(code_size) + thumb_offset;
+      code_offsets_.Put(&code, code_offset);
+      offset += sizeof(code_size);  // code size is prepended before code
+      offset += code_size;
+      oat_header_->UpdateChecksum(&code[0], code_size);
+    }
+    frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    core_spill_mask = compiled_method->GetCoreSpillMask();
+    fp_spill_mask = compiled_method->GetFpSpillMask();
 
-      // Deduplicate code arrays
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-      if (code_iter != code_offsets_.end()) {
-        code_offset = code_iter->second;
-      } else {
-        code_offsets_.Put(&code, code_offset);
-        offset += sizeof(code_size);  // code size is prepended before code
-        offset += code_size;
-        oat_header_->UpdateChecksum(&code[0], code_size);
-      }
-      frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-      core_spill_mask = compiled_method->GetCoreSpillMask();
-      fp_spill_mask = compiled_method->GetFpSpillMask();
+    const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+    size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
+    mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
 
-      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
-      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
-      mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
+    // Deduplicate mapping tables
+    SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end()) {
+      mapping_table_offset = mapping_iter->second;
+    } else {
+      mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
+      offset += mapping_table_size;
+      oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
+    }
 
-      // Deduplicate mapping tables
-      SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
-      if (mapping_iter != mapping_table_offsets_.end()) {
-        mapping_table_offset = mapping_iter->second;
-      } else {
-        mapping_table_offsets_.Put(&mapping_table, mapping_table_offset);
-        offset += mapping_table_size;
-        oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
-      }
+    const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+    size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
+    vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
 
-      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
-      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
-      vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
+    // Deduplicate vmap tables
+    SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end()) {
+      vmap_table_offset = vmap_iter->second;
+    } else {
+      vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
+      offset += vmap_table_size;
+      oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
+    }
 
-      // Deduplicate vmap tables
-      SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
-      if (vmap_iter != vmap_table_offsets_.end()) {
-        vmap_table_offset = vmap_iter->second;
-      } else {
-        vmap_table_offsets_.Put(&vmap_table, vmap_table_offset);
-        offset += vmap_table_size;
-        oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
-      }
+    const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
+    size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
+    gc_map_offset = (gc_map_size == 0) ? 0 : offset;
 
-      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
-      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
-      gc_map_offset = (gc_map_size == 0) ? 0 : offset;
-
-#ifndef NDEBUG
-      // We expect GC maps except when the class hasn't been verified or the method is native
-      CompiledClass* compiled_class =
-          compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
-      Class::Status status =
-          (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
-      CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
-          << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
+#if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
+    // We expect GC maps except when the class hasn't been verified or the method is native
+    CompiledClass* compiled_class =
+        compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
+    Class::Status status =
+        (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
+    CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
+        << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
 #endif
 
-      // Deduplicate GC maps
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map);
-      if (gc_map_iter != gc_map_offsets_.end()) {
-        gc_map_offset = gc_map_iter->second;
-      } else {
-        gc_map_offsets_.Put(&gc_map, gc_map_offset);
-        offset += gc_map_size;
-        oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
-      }
+    // Deduplicate GC maps
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter = gc_map_offsets_.find(&gc_map);
+    if (gc_map_iter != gc_map_offsets_.end()) {
+      gc_map_offset = gc_map_iter->second;
+    } else {
+      gc_map_offsets_.Put(&gc_map, gc_map_offset);
+      offset += gc_map_size;
+      oat_header_->UpdateChecksum(&gc_map[0], gc_map_size);
     }
   }
 
   const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
-    if (compiled_invoke_stub->IsExecutableInElf()) {
-#if defined(ART_USE_LLVM_COMPILER)
-      invoke_stub_elf_idx = compiled_invoke_stub->GetElfIndex();
-      invoke_stub_elf_func_idx = compiled_invoke_stub->GetElfFuncIndex();
-#endif
-    } else {
-      offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
-      DCHECK_ALIGNED(offset, kArmAlignment);
-      const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
-      uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
-      CHECK_NE(invoke_stub_size, 0U);
-      uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
-      invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset;
+    offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
+    DCHECK_ALIGNED(offset, kArmAlignment);
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
+    uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+    CHECK_NE(invoke_stub_size, 0U);
+    uint32_t thumb_offset = compiled_invoke_stub->CodeDelta();
+    invoke_stub_offset = offset + sizeof(invoke_stub_size) + thumb_offset;
 
-      // Deduplicate invoke stubs
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
-      if (stub_iter != code_offsets_.end()) {
-        invoke_stub_offset = stub_iter->second;
-      } else {
-        code_offsets_.Put(&invoke_stub, invoke_stub_offset);
-        offset += sizeof(invoke_stub_size);  // invoke stub size is prepended before code
-        offset += invoke_stub_size;
-        oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
-      }
+    // Deduplicate invoke stubs
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end()) {
+      invoke_stub_offset = stub_iter->second;
+    } else {
+      code_offsets_.Put(&invoke_stub, invoke_stub_offset);
+      offset += sizeof(invoke_stub_size);  // invoke stub size is prepended before code
+      offset += invoke_stub_size;
+      oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
     }
   }
 
@@ -397,9 +341,24 @@
   if (!is_static) {
     const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
     if (compiled_proxy_stub != NULL) {
-      DCHECK(compiled_proxy_stub->IsExecutableInElf());
-      proxy_stub_elf_idx = compiled_proxy_stub->GetElfIndex();
-      proxy_stub_elf_func_idx = compiled_proxy_stub->GetElfFuncIndex();
+      offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
+      DCHECK_ALIGNED(offset, kArmAlignment);
+      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
+      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
+      CHECK_NE(proxy_stub_size, 0U);
+      uint32_t thumb_offset = compiled_proxy_stub->CodeDelta();
+      proxy_stub_offset = offset + sizeof(proxy_stub_size) + thumb_offset;
+
+      // Deduplicate proxy stubs
+      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&proxy_stub);
+      if (stub_iter != code_offsets_.end()) {
+        proxy_stub_offset = stub_iter->second;
+      } else {
+        code_offsets_.Put(&proxy_stub, proxy_stub_offset);
+        offset += sizeof(proxy_stub_size);  // proxy stub size is prepended before code
+        offset += proxy_stub_size;
+        oat_header_->UpdateChecksum(&proxy_stub[0], proxy_stub_size);
+      }
     }
   }
 #endif
@@ -414,12 +373,7 @@
                          gc_map_offset,
                          invoke_stub_offset
 #if defined(ART_USE_LLVM_COMPILER)
-                       , code_elf_idx,
-                         code_elf_func_idx,
-                         invoke_stub_elf_idx,
-                         invoke_stub_elf_func_idx,
-                         proxy_stub_elf_idx,
-                         proxy_stub_elf_func_idx
+                       , proxy_stub_offset
 #endif
                          );
 
@@ -505,25 +459,6 @@
       return false;
     }
   }
-  for (size_t i = 0; i != oat_elf_images_.size(); ++i) {
-    if (!oat_elf_images_[i]->Write(file)) {
-      PLOG(ERROR) << "Failed to write oat elf information to " << file->name();
-      return false;
-    }
-  }
-  for (size_t i = 0; i != oat_elf_images_.size(); ++i) {
-    uint32_t expected_offset = oat_elf_images_[i]->GetElfOffset();
-    off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET);
-    if (static_cast<uint32_t>(actual_offset) != expected_offset) {
-      PLOG(ERROR) << "Failed to seek to dex file section."
-                  << " Actual: " << actual_offset
-                  << " Expected: " << expected_offset;
-      return false;
-    }
-    if (!oat_elf_images_[i]->WriteElfImage(file)) {
-      return false;
-    }
-  }
   for (size_t i = 0; i != oat_classes_.size(); ++i) {
     if (!oat_classes_[i]->Write(file)) {
       PLOG(ERROR) << "Failed to write oat methods information to " << file->name();
@@ -629,126 +564,169 @@
 
 
   if (compiled_method != NULL) {  // ie. not an abstract method
-    if (!compiled_method->IsExecutableInElf()) {
-      uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
-      uint32_t aligned_code_delta = aligned_code_offset - code_offset;
-      if (aligned_code_delta != 0) {
-        off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
-        if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
-          PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
-                      << " Expected: " << aligned_code_offset << " File: " << file->name();
-          return 0;
-        }
-        code_offset += aligned_code_delta;
-        DCHECK_CODE_OFFSET();
+    uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
+    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+    if (aligned_code_delta != 0) {
+      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+        PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
+                    << " Expected: " << aligned_code_offset << " File: " << file->name();
+        return 0;
       }
-      DCHECK_ALIGNED(code_offset, kArmAlignment);
-      const std::vector<uint8_t>& code = compiled_method->GetCode();
-      uint32_t code_size = code.size() * sizeof(code[0]);
-      CHECK_NE(code_size, 0U);
-
-      // Deduplicate code arrays
-      size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-      if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
-        DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&code_size, sizeof(code_size))) {
-          ReportWriteFailure("method code size", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += sizeof(code_size);
-        DCHECK_CODE_OFFSET();
-        if (!file->WriteFully(&code[0], code_size)) {
-          ReportWriteFailure("method code", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += code_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
-      size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
-
-      // Deduplicate mapping tables
-      SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
-          mapping_table_offsets_.find(&mapping_table);
-      if (mapping_iter != mapping_table_offsets_.end() &&
-          code_offset != method_offsets.mapping_table_offset_) {
-        DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
-            || mapping_iter->second == method_offsets.mapping_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
-            || code_offset == method_offsets.mapping_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
-          ReportWriteFailure("mapping table", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += mapping_table_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
-      size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
-
-      // Deduplicate vmap tables
-      SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
-          vmap_table_offsets_.find(&vmap_table);
-      if (vmap_iter != vmap_table_offsets_.end() &&
-          code_offset != method_offsets.vmap_table_offset_) {
-        DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
-            || vmap_iter->second == method_offsets.vmap_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
-            || code_offset == method_offsets.vmap_table_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
-          ReportWriteFailure("vmap table", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += vmap_table_size;
-      }
-      DCHECK_CODE_OFFSET();
-
-      const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
-      size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
-
-      // Deduplicate GC maps
-      SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
-          gc_map_offsets_.find(&gc_map);
-      if (gc_map_iter != gc_map_offsets_.end() &&
-          code_offset != method_offsets.gc_map_offset_) {
-        DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
-            || gc_map_iter->second == method_offsets.gc_map_offset_)
-            << PrettyMethod(method_idx, dex_file);
-      } else {
-        DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
-            || code_offset == method_offsets.gc_map_offset_)
-            << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&gc_map[0], gc_map_size)) {
-          ReportWriteFailure("GC map", method_idx, dex_file, file);
-          return 0;
-        }
-        code_offset += gc_map_size;
-      }
+      code_offset += aligned_code_delta;
       DCHECK_CODE_OFFSET();
     }
+    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    const std::vector<uint8_t>& code = compiled_method->GetCode();
+    uint32_t code_size = code.size() * sizeof(code[0]);
+    CHECK_NE(code_size, 0U);
+
+    // Deduplicate code arrays
+    size_t offset = code_offset + sizeof(code_size) + compiled_method->CodeDelta();
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
+    if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
+      DCHECK(code_iter->second == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK(offset == method_offsets.code_offset_) << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&code_size, sizeof(code_size))) {
+        ReportWriteFailure("method code size", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += sizeof(code_size);
+      DCHECK_CODE_OFFSET();
+      if (!file->WriteFully(&code[0], code_size)) {
+        ReportWriteFailure("method code", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += code_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
+    size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
+
+    // Deduplicate mapping tables
+    SafeMap<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+        mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end() &&
+        code_offset != method_offsets.mapping_table_offset_) {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || mapping_iter->second == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || code_offset == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
+        ReportWriteFailure("mapping table", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += mapping_table_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
+    size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
+
+    // Deduplicate vmap tables
+    SafeMap<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+        vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end() &&
+        code_offset != method_offsets.vmap_table_offset_) {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || vmap_iter->second == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || code_offset == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
+        ReportWriteFailure("vmap table", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += vmap_table_size;
+    }
+    DCHECK_CODE_OFFSET();
+
+    const std::vector<uint8_t>& gc_map = compiled_method->GetGcMap();
+    size_t gc_map_size = gc_map.size() * sizeof(gc_map[0]);
+
+    // Deduplicate GC maps
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator gc_map_iter =
+        gc_map_offsets_.find(&gc_map);
+    if (gc_map_iter != gc_map_offsets_.end() &&
+        code_offset != method_offsets.gc_map_offset_) {
+      DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
+          || gc_map_iter->second == method_offsets.gc_map_offset_)
+          << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK((gc_map_size == 0 && method_offsets.gc_map_offset_ == 0)
+          || code_offset == method_offsets.gc_map_offset_)
+          << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&gc_map[0], gc_map_size)) {
+        ReportWriteFailure("GC map", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += gc_map_size;
+    }
+    DCHECK_CODE_OFFSET();
   }
   const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
   const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
-    if (!compiled_invoke_stub->IsExecutableInElf()) {
+    uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
+                                                             compiler_->GetInstructionSet());
+    uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+    if (aligned_code_delta != 0) {
+      off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
+      if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
+        PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
+                    << " Expected: " << aligned_code_offset;
+        return 0;
+      }
+      code_offset += aligned_code_delta;
+      DCHECK_CODE_OFFSET();
+    }
+    DCHECK_ALIGNED(code_offset, kArmAlignment);
+    const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
+    uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
+    CHECK_NE(invoke_stub_size, 0U);
+
+    // Deduplicate invoke stubs
+    size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
+    SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
+        code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
+      DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+    } else {
+      DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+      if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
+        ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += sizeof(invoke_stub_size);
+      DCHECK_CODE_OFFSET();
+      if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
+        ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
+        return 0;
+      }
+      code_offset += invoke_stub_size;
+      DCHECK_CODE_OFFSET();
+    }
+  }
+
+#if defined(ART_USE_LLVM_COMPILER)
+  if (!is_static) {
+    const CompiledInvokeStub* compiled_proxy_stub = compiler_->FindProxyStub(shorty);
+    if (compiled_proxy_stub != NULL) {
       uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
                                                                compiler_->GetInstructionSet());
       uint32_t aligned_code_delta = aligned_code_offset - code_offset;
+      CHECK(aligned_code_delta < 48u);
       if (aligned_code_delta != 0) {
         off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
         if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
-          PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
+          PLOG(ERROR) << "Failed to seek to align proxy stub code. Actual: " << new_offset
                       << " Expected: " << aligned_code_offset;
           return 0;
         }
@@ -756,33 +734,35 @@
         DCHECK_CODE_OFFSET();
       }
       DCHECK_ALIGNED(code_offset, kArmAlignment);
-      const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
-      uint32_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
-      CHECK_NE(invoke_stub_size, 0U);
+      const std::vector<uint8_t>& proxy_stub = compiled_proxy_stub->GetCode();
+      uint32_t proxy_stub_size = proxy_stub.size() * sizeof(proxy_stub[0]);
+      CHECK_NE(proxy_stub_size, 0U);
 
-      // Deduplicate invoke stubs
-      size_t offset = code_offset + sizeof(invoke_stub_size) + compiled_invoke_stub->CodeDelta();
+      // Deduplicate proxy stubs
+      size_t offset = code_offset + sizeof(proxy_stub_size) + compiled_proxy_stub->CodeDelta();
       SafeMap<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
-          code_offsets_.find(&invoke_stub);
-      if (stub_iter != code_offsets_.end() && offset != method_offsets.invoke_stub_offset_) {
-        DCHECK(stub_iter->second == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
+          code_offsets_.find(&proxy_stub);
+      if (stub_iter != code_offsets_.end() && offset != method_offsets.proxy_stub_offset_) {
+        DCHECK(stub_iter->second == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
       } else {
-        DCHECK(offset == method_offsets.invoke_stub_offset_) << PrettyMethod(method_idx, dex_file);
-        if (!file->WriteFully(&invoke_stub_size, sizeof(invoke_stub_size))) {
-          ReportWriteFailure("invoke stub code size", method_idx, dex_file, file);
+        DCHECK(offset == method_offsets.proxy_stub_offset_) << PrettyMethod(method_idx, dex_file);
+        if (!file->WriteFully(&proxy_stub_size, sizeof(proxy_stub_size))) {
+          ReportWriteFailure("proxy stub code size", method_idx, dex_file, file);
           return 0;
         }
-        code_offset += sizeof(invoke_stub_size);
+        code_offset += sizeof(proxy_stub_size);
         DCHECK_CODE_OFFSET();
-        if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
-          ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
+        if (!file->WriteFully(&proxy_stub[0], proxy_stub_size)) {
+          ReportWriteFailure("proxy stub code", method_idx, dex_file, file);
           return 0;
         }
-        code_offset += invoke_stub_size;
+        code_offset += proxy_stub_size;
+        DCHECK_CODE_OFFSET();
       }
       DCHECK_CODE_OFFSET();
     }
   }
+#endif
 
   return code_offset;
 }
@@ -867,48 +847,4 @@
   return true;
 }
 
-OatWriter::OatElfImage::OatElfImage(const ElfImage& image)
-    : elf_offset_(0), elf_size_(image.size()), elf_addr_(image.begin()) {
-}
-
-size_t OatWriter::OatElfImage::SizeOf() const {
-  return (sizeof(elf_offset_) + sizeof(elf_size_));
-}
-
-uint32_t OatWriter::OatElfImage::GetElfSize() const {
-  return elf_size_;
-}
-
-uint32_t OatWriter::OatElfImage::GetElfOffset() const {
-  DCHECK_NE(elf_offset_, 0U);
-  return elf_offset_;
-}
-
-void OatWriter::OatElfImage::SetElfOffset(uint32_t offset) {
-  DCHECK_NE(offset, 0U);
-  DCHECK_EQ((offset & 0x3LU), 0U);
-  elf_offset_ = offset;
-}
-
-bool OatWriter::OatElfImage::Write(File* file) const {
-  DCHECK_NE(elf_offset_, 0U);
-  if (!file->WriteFully(&elf_offset_, sizeof(elf_offset_))) {
-    PLOG(ERROR) << "Failed to write ELF offset to " << file->name();
-    return false;
-  }
-  if (!file->WriteFully(&elf_size_, sizeof(elf_size_))) {
-    PLOG(ERROR) << "Failed to write ELF size to " << file->name();
-    return false;
-  }
-  return true;
-}
-
-bool OatWriter::OatElfImage::WriteElfImage(File* file) const {
-  if (!file->WriteFully(elf_addr_, elf_size_)) {
-    PLOG(ERROR) << "Failed to write ELF image to " << file->name();
-    return false;
-  }
-  return true;
-}
-
 }  // namespace art
diff --git a/src/oat_writer.h b/src/oat_writer.h
index 29072ab..b748dbc 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -49,16 +49,6 @@
 // ...
 // OatClass[C]
 //
-// OatElfImage[0]    one OatElfImage for each ELF image
-// OatElfImage[1]    contains the size, checksum, and offset to the ELF image.
-// ...
-// OatElfImage[E]
-//
-// ELF[0]
-// ELF[1]
-// ...
-// ELF[E]
-//
 // padding           if necessary so that the following code will be page aligned
 //
 // CompiledMethod    one variable sized blob with the contents of each CompiledMethod
@@ -92,8 +82,6 @@
   size_t InitOatDexFiles(size_t offset);
   size_t InitDexFiles(size_t offset);
   size_t InitOatClasses(size_t offset);
-  size_t InitOatElfImages(size_t offset);
-  size_t InitElfImages(size_t offset);
   size_t InitOatCode(size_t offset);
   size_t InitOatCodeDexFiles(size_t offset);
   size_t InitOatCodeDexFile(size_t offset,
@@ -155,25 +143,6 @@
     DISALLOW_COPY_AND_ASSIGN(OatClass);
   };
 
-  class OatElfImage {
-   public:
-    explicit OatElfImage(const ElfImage& elf_image);
-    size_t SizeOf() const;
-    uint32_t GetElfSize() const;
-    uint32_t GetElfOffset() const;
-    void SetElfOffset(uint32_t offset);
-    bool Write(File* file) const;
-    bool WriteElfImage(File* file) const;
-
-   private:
-    // data to write
-    uint32_t elf_offset_;
-    const uint32_t elf_size_;
-
-    const byte* const elf_addr_;
-    DISALLOW_COPY_AND_ASSIGN(OatElfImage);
-  };
-
   const Compiler* compiler_;
 
   // TODO: remove the ClassLoader when the code storage moves out of Method
@@ -182,8 +151,6 @@
   // note OatFile does not take ownership of the DexFiles
   const std::vector<const DexFile*>* dex_files_;
 
-  std::vector<ElfImage> elf_images_;
-
   // dependency on the image
   uint32_t image_file_location_checksum_;
   std::string image_file_location_;
@@ -192,7 +159,6 @@
   OatHeader* oat_header_;
   std::vector<OatDexFile*> oat_dex_files_;
   std::vector<OatClass*> oat_classes_;
-  std::vector<OatElfImage*> oat_elf_images_;
   uint32_t executable_offset_padding_length_;
 
   template <class T> struct MapCompare {
diff --git a/src/oatdump.cc b/src/oatdump.cc
index b599eaa..a33cd09 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -57,11 +57,6 @@
           "      Example: --boot-image=/system/framework/boot.art\n"
           "\n");
   fprintf(stderr,
-          "  --extract-elf-to=<file.elf>: provide the prefix of the filename for\n"
-          "      the output ELF files.\n"
-          "      Example: --extract-elf-to=output.elf\n"
-          "\n");
-  fprintf(stderr,
           "  --host-prefix may be used to translate host paths to target paths during\n"
           "      cross compilation.\n"
           "      Example: --host-prefix=out/target/product/crespo\n"
@@ -113,9 +108,6 @@
     os << "DEX FILE COUNT:\n";
     os << oat_header.GetDexFileCount() << "\n\n";
 
-    os << "ELF IMAGE COUNT:\n";
-    os << oat_header.GetElfImageCount() << "\n\n";
-
     os << "EXECUTABLE OFFSET:\n";
     os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
 
@@ -318,35 +310,17 @@
     os << StringPrintf("\t\tgc_map: %p (offset=0x%08x)\n",
                        oat_method.GetGcMap(), oat_method.GetGcMapOffset());
     DumpGcMap(os, oat_method.GetGcMap());
-    os << StringPrintf(
-#if defined(ART_USE_LLVM_COMPILER)
-                       "\t\tCODE: %p (offset=0x%08x size=%d elf_idx=%d elf_func_idx=%d)%s\n",
-#else
-                       "\t\tCODE: %p (offset=0x%08x size=%d)%s\n",
-#endif
+    os << StringPrintf("\t\tCODE: %p (offset=0x%08x size=%d)%s\n",
                        oat_method.GetCode(),
                        oat_method.GetCodeOffset(),
                        oat_method.GetCodeSize(),
-#if defined(ART_USE_LLVM_COMPILER)
-                       static_cast<int>(oat_method.GetCodeElfIndex()),
-                       static_cast<int>(oat_method.GetCodeElfFuncIndex()),
-#endif
                        oat_method.GetCode() != NULL ? "..." : "");
     DumpCode(os, oat_method.GetCode(), oat_method.GetCodeSize(), oat_method.GetMappingTable(),
              dex_file, code_item);
-    os << StringPrintf(
-#if defined(ART_USE_LLVM_COMPILER)
-                       "\t\tINVOKE STUB: %p (offset=0x%08x size=%d elf_idx=%d elf_func_idx=%d)%s\n",
-#else
-                       "\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n",
-#endif
+    os << StringPrintf("\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n",
                        oat_method.GetInvokeStub(),
                        oat_method.GetInvokeStubOffset(),
                        oat_method.GetInvokeStubSize(),
-#if defined(ART_USE_LLVM_COMPILER)
-                       static_cast<int>(oat_method.GetInvokeStubElfIndex()),
-                       static_cast<int>(oat_method.GetInvokeStubElfFuncIndex()),
-#endif
                        oat_method.GetInvokeStub() != NULL ? "..." : "");
     DumpCode(os, reinterpret_cast<const void*>(oat_method.GetInvokeStub()),
              oat_method.GetInvokeStubSize(), NULL, dex_file, NULL);
@@ -1158,8 +1132,6 @@
       image_filename = option.substr(strlen("--image=")).data();
     } else if (option.starts_with("--boot-image=")) {
       boot_image_filename = option.substr(strlen("--boot-image=")).data();
-    } else if (option.starts_with("--extract-elf-to=")) {
-      elf_filename_prefix = option.substr(strlen("--extract-elf-to=")).data();
     } else if (option.starts_with("--host-prefix=")) {
       host_prefix.reset(new std::string(option.substr(strlen("--host-prefix=")).data()));
     } else if (option.starts_with("--output=")) {
@@ -1204,25 +1176,6 @@
     }
     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) {
-        const OatFile::OatElfImage* elf_image = oat_file->GetOatElfImage(i);
-
-        std::string elf_filename(
-            StringPrintf("%s-%u", elf_filename_prefix.c_str(), i));
-
-        UniquePtr<File> elf_file(OS::OpenFile(elf_filename.c_str(), true));
-
-        if (!elf_file->WriteFully(elf_image->begin(), elf_image->size())) {
-          fprintf(stderr, "Failed to write ELF image to: %s\n",
-                  elf_filename.c_str());
-        }
-      }
-    }
-#endif
     return EXIT_SUCCESS;
   }
 
diff --git a/src/runtime.cc b/src/runtime.cc
index 5f20a4b..b5928b2 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -48,6 +48,10 @@
 #include "verifier/method_verifier.h"
 #include "well_known_classes.h"
 
+#if defined(ART_USE_LLVM_COMPILER)
+#include "compiler_llvm/procedure_linkage_table.h"
+#endif
+
 #include "JniConstants.h" // Last to avoid LOG redefinition in ics-mr1-plus-art.
 
 namespace art {
@@ -83,13 +87,27 @@
       tracer_(NULL),
       use_compile_time_class_path_(false),
       main_thread_group_(NULL),
-      system_thread_group_(NULL) {
+      system_thread_group_(NULL)
+#if defined(ART_USE_LLVM_COMPILER)
+#if defined(__arm__)
+    , plt_(kArm)
+#elif defined(__mips__)
+    , plt_(kMips)
+#elif defined(__i386__)
+    , plt_(kX86)
+#endif
+#endif
+      {
   for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) {
     resolution_stub_array_[i] = NULL;
   }
   for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) {
     callee_save_methods_[i] = NULL;
   }
+
+#if defined(ART_USE_LLVM_COMPILER)
+  CHECK(plt_.AllocateTable()) << "Failed to allocate PLT";
+#endif
 }
 
 Runtime::~Runtime() {
diff --git a/src/runtime.h b/src/runtime.h
index a6cebe7..ba579ea 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -33,6 +33,10 @@
 #include "safe_map.h"
 #include "stringpiece.h"
 
+#if defined(ART_USE_LLVM_COMPILER)
+#include "compiler_llvm/procedure_linkage_table.h"
+#endif
+
 namespace art {
 
 template<class T> class PrimitiveArray;
@@ -422,6 +426,9 @@
 
   jobject main_thread_group_;
   jobject system_thread_group_;
+#if defined(ART_USE_LLVM_COMPILER)
+  compiler_llvm::ProcedureLinkageTable plt_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(Runtime);
 };