16a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom/*
26a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Copyright (C) 2012 The Android Open Source Project
36a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
46a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License");
56a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * you may not use this file except in compliance with the License.
66a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * You may obtain a copy of the License at
76a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
86a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *      http://www.apache.org/licenses/LICENSE-2.0
96a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom *
106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * Unless required by applicable law or agreed to in writing, software
116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS,
126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * See the License for the specific language governing permissions and
146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom * limitations under the License.
156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom */
166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "elf_writer_mclinker.h"
186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
196a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <llvm/Support/TargetSelect.h>
206a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/Environment.h>
226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/IRBuilder.h>
236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/Linker.h>
246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/LinkerConfig.h>
256a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/MC/ZOption.h>
266a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/Module.h>
276a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/Support/Path.h>
286a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include <mcld/Support/TargetSelect.h>
296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
306a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "base/unix_file/fd_file.h"
317f55288906c21b99801d75bb6fe17fe25af5c1e9Brian Carlstrom#include "class_linker.h"
327f55288906c21b99801d75bb6fe17fe25af5c1e9Brian Carlstrom#include "dex_method_iterator.h"
337940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h"
347f55288906c21b99801d75bb6fe17fe25af5c1e9Brian Carlstrom#include "elf_file.h"
356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#include "globals.h"
36ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method.h"
37ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
387f55288906c21b99801d75bb6fe17fe25af5c1e9Brian Carlstrom#include "mirror/object-inl.h"
39c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "oat_writer.h"
407f55288906c21b99801d75bb6fe17fe25af5c1e9Brian Carlstrom#include "scoped_thread_state_change.h"
41c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom#include "vector_output_stream.h"
426a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
436a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromnamespace art {
446a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
456a47b9dc850b903aabefcfab4adb132cb68bba2eBrian CarlstromElfWriterMclinker::ElfWriterMclinker(const CompilerDriver& driver, File* elf_file)
466a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  : ElfWriter(driver, elf_file), oat_input_(NULL) {}
476a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
486a47b9dc850b903aabefcfab4adb132cb68bba2eBrian CarlstromElfWriterMclinker::~ElfWriterMclinker() {}
496a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
506a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrombool ElfWriterMclinker::Create(File* elf_file,
51c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom                               OatWriter& oat_writer,
526a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                               const std::vector<const DexFile*>& dex_files,
536a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                               const std::string& android_root,
546a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                               bool is_host,
556a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                               const CompilerDriver& driver) {
566a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ElfWriterMclinker elf_writer(driver, elf_file);
57c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  return elf_writer.Write(oat_writer, dex_files, android_root, is_host);
586a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
596a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
60c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrombool ElfWriterMclinker::Write(OatWriter& oat_writer,
616a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                              const std::vector<const DexFile*>& dex_files,
626a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                              const std::string& android_root,
636a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                              bool is_host) {
64c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  std::vector<uint8_t> oat_contents;
65c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  oat_contents.reserve(oat_writer.GetSize());
66c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  VectorOutputStream output_stream("oat contents", oat_contents);
67c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  CHECK(oat_writer.Write(output_stream));
68c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  CHECK_EQ(oat_writer.GetSize(), oat_contents.size());
69c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom
706a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  Init();
716a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  AddOatInput(oat_contents);
726a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#if defined(ART_USE_PORTABLE_COMPILER)
736a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  AddMethodInputs(dex_files);
746a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  AddRuntimeInputs(android_root, is_host);
756a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#endif
766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (!Link()) {
776a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
79c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  oat_contents.clear();
806a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#if defined(ART_USE_PORTABLE_COMPILER)
816a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  FixupOatMethodOffsets(dex_files);
826a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#endif
836a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  return true;
846a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
856a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromstatic void InitializeLLVM() {
876a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: this is lifted from art's compiler_llvm.cc, should be factored out
886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (kIsTargetBuild) {
896a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    llvm::InitializeNativeTarget();
906a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    // TODO: odd that there is no InitializeNativeTargetMC?
916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  } else {
926a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    llvm::InitializeAllTargets();
936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    llvm::InitializeAllTargetMCs();
946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::Init() {
986a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string target_triple;
996a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string target_cpu;
1006a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string target_attr;
1016a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CompilerDriver::InstructionSetToLLVMTarget(compiler_driver_->GetInstructionSet(),
1026a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                             target_triple,
1036a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                             target_cpu,
1046a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                             target_attr);
1056a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1066a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // Based on mclinker's llvm-mcld.cpp main() and LinkerTest
1076a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  //
1086a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: LinkerTest uses mcld::Initialize(), but it does an
1096a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // llvm::InitializeAllTargets, which we don't want. Basically we
1106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // want mcld::InitializeNative, but it doesn't exist yet, so we
1116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // inline the minimal we need here.
1126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  InitializeLLVM();
1136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::InitializeAllTargets();
1146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::InitializeAllLinkers();
1156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::InitializeAllEmulations();
1166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::InitializeAllDiagnostics();
1176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_config_.reset(new mcld::LinkerConfig(target_triple));
1196a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(linker_config_.get() != NULL);
1206a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_config_->setCodeGenType(mcld::LinkerConfig::DynObj);
1216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_config_->options().setSOName(elf_file_->GetPath());
1226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // error on undefined symbols.
1246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: should this just be set if kIsDebugBuild?
1256a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_config_->options().setNoUndefined(true);
1266a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1276a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (compiler_driver_->GetInstructionSet() == kMips) {
1286a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     // MCLinker defaults MIPS section alignment to 0x10000, not
1296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     // 0x1000.  The ABI says this is because the max page size is
1306a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     // general is 64k but that isn't true on Android.
1316a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     mcld::ZOption z_option;
1326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     z_option.setKind(mcld::ZOption::MaxPageSize);
1336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     z_option.setPageSize(kPageSize);
1346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom     linker_config_->options().addZOption(z_option);
1356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
1366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: Wire up mcld DiagnosticEngine to LOG?
1386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_config_->options().setColor(false);
1396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (false) {
1406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    // enables some tracing of input file processing
1416a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    linker_config_->options().setTrace(true);
1426a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
1436a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1446a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // Based on alone::Linker::config
1456a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  module_.reset(new mcld::Module(linker_config_->options().soname()));
1466a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(module_.get() != NULL);
1476a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ir_builder_.reset(new mcld::IRBuilder(*module_.get(), *linker_config_.get()));
1486a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(ir_builder_.get() != NULL);
1496a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_.reset(new mcld::Linker());
1506a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(linker_.get() != NULL);
1516a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  linker_->config(*linker_config_.get());
1526a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
1536a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1546a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::AddOatInput(std::vector<uint8_t>& oat_contents) {
1556a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // Add an artificial memory input. Based on LinkerTest.
1566a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  UniquePtr<OatFile> oat_file(OatFile::OpenMemory(oat_contents, elf_file_->GetPath()));
1576a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(oat_file.get() != NULL) << elf_file_->GetPath();
1586a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1596a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const char* oat_data_start = reinterpret_cast<const char*>(&oat_file->GetOatHeader());
1606a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const size_t oat_data_length = oat_file->GetOatHeader().GetExecutableOffset();
1616a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const char* oat_code_start = oat_data_start + oat_data_length;
1626a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const size_t oat_code_length = oat_file->Size() - oat_data_length;
1636a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of oat_input?
1656a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  oat_input_ = ir_builder_->CreateInput("oat contents",
1666a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                        mcld::sys::fs::Path("oat contents path"),
1676a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                        mcld::Input::Object);
1686a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(oat_input_ != NULL);
1696a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1706a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of null_section?
1716a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::LDSection* null_section = ir_builder_->CreateELFHeader(*oat_input_,
1726a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               "",
1736a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               mcld::LDFileFormat::Null,
1746a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               llvm::ELF::SHT_NULL,
1756a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               0);
1766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(null_section != NULL);
1776a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: we should split readonly data from readonly executable
1796a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // code like .oat does.  We need to control section layout with
1806a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // linker script like functionality to guarantee references
1816a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // between sections maintain relative position which isn't
1826a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // possible right now with the mclinker APIs.
1836a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(oat_code_start != NULL);
1846a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1856a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // we need to ensure that oatdata is page aligned so when we
1866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // fixup the segment load addresses, they remain page aligned.
1876a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  uint32_t alignment = kPageSize;
1886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1896a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of text_section?
1906a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::LDSection* text_section = ir_builder_->CreateELFHeader(*oat_input_,
1916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               ".text",
1926a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               llvm::ELF::SHT_PROGBITS,
1936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               llvm::ELF::SHF_EXECINSTR
1946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               | llvm::ELF::SHF_ALLOC,
1956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                               alignment);
1966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(text_section != NULL);
1976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
1986a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::SectionData* text_sectiondata = ir_builder_->CreateSectionData(*text_section);
1996a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(text_sectiondata != NULL);
2006a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2016a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: why does IRBuilder::CreateRegion take a non-const pointer?
2026a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Fragment* text_fragment = ir_builder_->CreateRegion(const_cast<char*>(oat_data_start),
2036a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                            oat_file->Size());
2046a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(text_fragment != NULL);
2056a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ir_builder_->AppendFragment(*text_fragment, *text_sectiondata);
2066a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2076a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ir_builder_->AddSymbol(*oat_input_,
2086a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         "oatdata",
2096a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Object,
2106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Define,
2116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Global,
2126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         oat_data_length,  // size
2136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         0,                // offset
2146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         text_section);
2156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ir_builder_->AddSymbol(*oat_input_,
2176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         "oatexec",
2186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Function,
2196a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Define,
2206a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Global,
2216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         oat_code_length,  // size
2226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         oat_data_length,  // offset
2236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         text_section);
2246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2256a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  ir_builder_->AddSymbol(*oat_input_,
2266a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         "oatlastword",
2276a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Object,
2286a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Define,
2296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         mcld::ResolveInfo::Global,
2306a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         0,                // size
2316a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         // subtract a word so symbol is within section
2326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         (oat_data_length + oat_code_length) - sizeof(uint32_t),  // offset
2336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                         text_section);
2346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
2356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#if defined(ART_USE_PORTABLE_COMPILER)
2376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::AddMethodInputs(const std::vector<const DexFile*>& dex_files) {
2386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  DCHECK(oat_input_ != NULL);
2396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  DexMethodIterator it(dex_files);
2416a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  while (it.HasNext()) {
2426a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    const DexFile& dex_file = it.GetDexFile();
2436a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    uint32_t method_idx = it.GetMemberIndex();
2446a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    const CompiledMethod* compiled_method =
2453693c086ad4d5ba13ffcc7c7f481b21f67543660Brian Carlstrom      compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, method_idx));
2466a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    if (compiled_method != NULL) {
2476a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      AddCompiledCodeInput(*compiled_method);
2486a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    }
2496a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    it.Next();
2506a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
2516a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  added_symbols_.clear();
2526a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
2536a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2546a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::AddCompiledCodeInput(const CompiledCode& compiled_code) {
2556a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // Check if we've seen this compiled code before. If so skip
2566a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // it. This can happen for reused code such as invoke stubs.
2576a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const std::string& symbol = compiled_code.GetSymbol();
2586a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  SafeMap<const std::string*, const std::string*>::iterator it = added_symbols_.find(&symbol);
2596a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (it != added_symbols_.end()) {
2606a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return;
2616a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
2626a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  added_symbols_.Put(&symbol, &symbol);
2636a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // Add input to supply code for symbol
2656a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const std::vector<uint8_t>& code = compiled_code.GetCode();
2666a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of code_input?
2676a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: why does IRBuilder::ReadInput take a non-const pointer?
2686a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Input* code_input = ir_builder_->ReadInput(symbol,
2696a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                   const_cast<uint8_t*>(&code[0]),
2706a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                   code.size());
2716a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(code_input != NULL);
2726a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
2736a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2746a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::AddRuntimeInputs(const std::string& android_root, bool is_host) {
2756a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string libart_so(android_root);
2766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  libart_so += kIsDebugBuild ? "/lib/libartd.so" : "/lib/libart.so";
2776a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of libart_so_input?
2786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Input* libart_so_input = ir_builder_->ReadInput(libart_so, libart_so);
2796a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(libart_so_input != NULL);
2806a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2816a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string host_prebuilt_dir("prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6");
2826a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2836a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string compiler_runtime_lib;
2846a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (is_host) {
2856a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    compiler_runtime_lib += host_prebuilt_dir;
2866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    compiler_runtime_lib += "/lib/gcc/i686-linux/4.6.x-google/libgcc.a";
2876a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  } else {
2886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    compiler_runtime_lib += android_root;
2896a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    compiler_runtime_lib += "/lib/libcompiler_rt.a";
2906a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
2916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of compiler_runtime_lib_input?
2926a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Input* compiler_runtime_lib_input = ir_builder_->ReadInput(compiler_runtime_lib,
2936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                                   compiler_runtime_lib);
2946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(compiler_runtime_lib_input != NULL);
2956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
2966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string libc_lib;
2976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (is_host) {
2986a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libc_lib += host_prebuilt_dir;
2996a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libc_lib += "/sysroot/usr/lib/libc.so.6";
3006a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  } else {
3016a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libc_lib += android_root;
3026a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libc_lib += "/lib/libc.so";
3036a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3046a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of libc_lib_input?
3056a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Input* libc_lib_input_input = ir_builder_->ReadInput(libc_lib, libc_lib);
3066a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(libc_lib_input_input != NULL);
3076a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3086a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  std::string libm_lib;
3096a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (is_host) {
3106a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libm_lib += host_prebuilt_dir;
3116a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libm_lib += "/sysroot/usr/lib/libm.so";
3126a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  } else {
3136a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libm_lib += android_root;
3146a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    libm_lib += "/lib/libm.so";
3156a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3166a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: ownership of libm_lib_input?
3176a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Input* libm_lib_input_input = ir_builder_->ReadInput(libm_lib, libm_lib);
3186a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(libm_lib_input_input != NULL);
3196a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
3206a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#endif
3216a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3226a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrombool ElfWriterMclinker::Link() {
3236a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // link inputs
3246a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (!linker_->link(*module_.get(), *ir_builder_.get())) {
3256a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    LOG(ERROR) << "Failed to link " << elf_file_->GetPath();
3266a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
3276a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3286a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3296a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // emit linked output
3306a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  // TODO: avoid dup of fd by fixing Linker::emit to not close the argument fd.
3316a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  int fd = dup(elf_file_->Fd());
3326a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (fd == -1) {
3336a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    PLOG(ERROR) << "Failed to dup file descriptor for " << elf_file_->GetPath();
3346a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
3356a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3366a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (!linker_->emit(fd)) {
3376a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    LOG(ERROR) << "Failed to emit " << elf_file_->GetPath();
3386a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return false;
3396a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3406a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  mcld::Finalize();
3416a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  LOG(INFO) << "ELF file written successfully: " << elf_file_->GetPath();
3426a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  return true;
3436a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
3446a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3456a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#if defined(ART_USE_PORTABLE_COMPILER)
3466a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromvoid ElfWriterMclinker::FixupOatMethodOffsets(const std::vector<const DexFile*>& dex_files) {
3476a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  UniquePtr<ElfFile> elf_file(ElfFile::Open(elf_file_, true, false));
3486a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK(elf_file.get() != NULL) << elf_file_->GetPath();
3496a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3506a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  llvm::ELF::Elf32_Addr oatdata_address = GetOatDataAddress(elf_file.get());
3516a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  DexMethodIterator it(dex_files);
3526a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  while (it.HasNext()) {
3536a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    const DexFile& dex_file = it.GetDexFile();
3546a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    uint32_t method_idx = it.GetMemberIndex();
3556a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    InvokeType invoke_type = it.GetInvokeType();
356ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ArtMethod* method = NULL;
3576a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    if (compiler_driver_->IsImage()) {
3586a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      ClassLinker* linker = Runtime::Current()->GetClassLinker();
3596a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      mirror::DexCache* dex_cache = linker->FindDexCache(dex_file);
3606a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      // Unchecked as we hold mutator_lock_ on entry.
3616a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      ScopedObjectAccessUnchecked soa(Thread::Current());
3626a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      method = linker->ResolveMethod(dex_file, method_idx, dex_cache, NULL, NULL, invoke_type);
3636a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      CHECK(method != NULL);
3646a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    }
3656a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    const CompiledMethod* compiled_method =
3663693c086ad4d5ba13ffcc7c7f481b21f67543660Brian Carlstrom      compiler_driver_->GetCompiledMethod(MethodReference(&dex_file, method_idx));
3676a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    if (compiled_method != NULL) {
3686a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      uint32_t offset = FixupCompiledCodeOffset(*elf_file.get(), oatdata_address, *compiled_method);
3696a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      // Don't overwrite static method trampoline
3706a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      if (method != NULL &&
3716a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom          (!method->IsStatic() ||
3726a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom           method->IsConstructor() ||
3736a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom           method->GetDeclaringClass()->IsInitialized())) {
3746a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom        method->SetOatCodeOffset(offset);
3756a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom      }
3766a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    }
3776a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    it.Next();
3786a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3796a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  symbol_to_compiled_code_offset_.clear();
3806a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
3816a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3826a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstromuint32_t ElfWriterMclinker::FixupCompiledCodeOffset(ElfFile& elf_file,
3836a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                    llvm::ELF::Elf32_Addr oatdata_address,
3846a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                    const CompiledCode& compiled_code) {
3856a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const std::string& symbol = compiled_code.GetSymbol();
3866a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  SafeMap<const std::string*, uint32_t>::iterator it = symbol_to_compiled_code_offset_.find(&symbol);
3876a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  if (it != symbol_to_compiled_code_offset_.end()) {
3886a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    return it->second;
3896a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
3906a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3916a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  llvm::ELF::Elf32_Addr compiled_code_address = elf_file.FindSymbolAddress(llvm::ELF::SHT_SYMTAB,
3926a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                                           symbol,
3936a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom                                                                           true);
3946a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK_NE(0U, compiled_code_address) << symbol;
3956a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  CHECK_LT(oatdata_address, compiled_code_address) << symbol;
3966a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  uint32_t compiled_code_offset = compiled_code_address - oatdata_address;
3976a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  symbol_to_compiled_code_offset_.Put(&symbol, compiled_code_offset);
3986a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
3996a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  const std::vector<uint32_t>& offsets = compiled_code.GetOatdataOffsetsToCompliledCodeOffset();
4006a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  for (uint32_t i = 0; i < offsets.size(); i++) {
4016a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    uint32_t oatdata_offset = oatdata_address + offsets[i];
4026a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    uint32_t* addr = reinterpret_cast<uint32_t*>(elf_file.Begin() + oatdata_offset);
4036a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom    *addr = compiled_code_offset;
4046a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  }
4056a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom  return compiled_code_offset;
4066a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}
4076a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom#endif
4086a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom
4096a47b9dc850b903aabefcfab4adb132cb68bba2eBrian Carlstrom}  // namespace art
410