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