/*
 * 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_writer.h"

#include <llvm/Support/TargetSelect.h>

#include <mcld/Environment.h>
#include <mcld/IRBuilder.h>
#include <mcld/Linker.h>
#include <mcld/LinkerConfig.h>
#include <mcld/MC/ZOption.h>
#include <mcld/Module.h>
#include <mcld/Support/Path.h>
#include <mcld/Support/TargetSelect.h>

#include "base/unix_file/fd_file.h"
#include "class_linker.h"
#include "compiler/driver/compiler_driver.h"
#include "compiler/llvm/utils_llvm.h"
#include "dex_file-inl.h"
#include "dex_method_iterator.h"
#include "elf_file.h"
#include "invoke_type.h"
#include "mirror/abstract_method-inl.h"
#include "mirror/object-inl.h"
#include "oat.h"
#include "oat_file.h"
#include "scoped_thread_state_change.h"

namespace art {

bool ElfWriter::Create(File* elf_file,
                       std::vector<uint8_t>& oat_contents,
                       const std::vector<const DexFile*>& dex_files,
                       const std::string& android_root,
                       bool is_host,
                       const CompilerDriver& driver) {
  ElfWriter elf_writer(driver, elf_file);
  return elf_writer.Write(oat_contents, dex_files, android_root, is_host);
}

ElfWriter::ElfWriter(const CompilerDriver& driver, File* elf_file)
  : compiler_driver_(&driver), elf_file_(elf_file), oat_input_(NULL) {}

ElfWriter::~ElfWriter() {}

bool ElfWriter::Write(std::vector<uint8_t>& oat_contents,
                      const std::vector<const DexFile*>& dex_files,
                      const std::string& android_root,
                      bool is_host) {
  Init();
  AddOatInput(oat_contents);
#if defined(ART_USE_PORTABLE_COMPILER)
  AddMethodInputs(dex_files);
  AddRuntimeInputs(android_root, is_host);
#endif
  if (!Link()) {
    return false;
  }
#if defined(ART_USE_PORTABLE_COMPILER)
  FixupOatMethodOffsets(dex_files);
#endif
  return true;
}

static void InitializeLLVM() {
  // TODO: this is lifted from art's compiler_llvm.cc, should be factored out
  if (kIsTargetBuild) {
    llvm::InitializeNativeTarget();
    // TODO: odd that there is no InitializeNativeTargetMC?
  } else {
    llvm::InitializeAllTargets();
    llvm::InitializeAllTargetMCs();
  }
}

void ElfWriter::Init() {
  std::string target_triple;
  std::string target_cpu;
  std::string target_attr;
  CompilerDriver::InstructionSetToLLVMTarget(compiler_driver_->GetInstructionSet(),
                                       target_triple,
                                       target_cpu,
                                       target_attr);

  // Based on mclinker's llvm-mcld.cpp main() and LinkerTest
  //
  // TODO: LinkerTest uses mcld::Initialize(), but it does an
  // llvm::InitializeAllTargets, which we don't want. Basically we
  // want mcld::InitializeNative, but it doesn't exist yet, so we
  // inline the minimal we need here.
  InitializeLLVM();
  mcld::InitializeAllTargets();
  mcld::InitializeAllLinkers();
  mcld::InitializeAllEmulations();
  mcld::InitializeAllDiagnostics();

  linker_config_.reset(new mcld::LinkerConfig(target_triple));
  CHECK(linker_config_.get() != NULL);
  linker_config_->setCodeGenType(mcld::LinkerConfig::DynObj);
  linker_config_->options().setSOName(elf_file_->GetPath());

  // error on undefined symbols.
  // TODO: should this just be set if kIsDebugBuild?
  linker_config_->options().setNoUndefined(true);

  if (compiler_driver_->GetInstructionSet() == kMips) {
     // MCLinker defaults MIPS section alignment to 0x10000, not
     // 0x1000.  The ABI says this is because the max page size is
     // general is 64k but that isn't true on Android.
     mcld::ZOption z_option;
     z_option.setKind(mcld::ZOption::MaxPageSize);
     z_option.setPageSize(kPageSize);
     linker_config_->options().addZOption(z_option);
  }

  // TODO: Wire up mcld DiagnosticEngine to LOG?
  linker_config_->options().setColor(false);
  if (false) {
    // enables some tracing of input file processing
    linker_config_->options().setTrace(true);
  }

  // Based on alone::Linker::config
  module_.reset(new mcld::Module(linker_config_->options().soname()));
  CHECK(module_.get() != NULL);
  ir_builder_.reset(new mcld::IRBuilder(*module_.get(), *linker_config_.get()));
  CHECK(ir_builder_.get() != NULL);
  linker_.reset(new mcld::Linker());
  CHECK(linker_.get() != NULL);
  linker_->config(*linker_config_.get());
}

void ElfWriter::AddOatInput(std::vector<uint8_t>& oat_contents) {
  // Add an artificial memory input. Based on LinkerTest.
  UniquePtr<OatFile> oat_file(OatFile::OpenMemory(oat_contents, elf_file_->GetPath()));
  CHECK(oat_file.get() != NULL) << elf_file_->GetPath();

  const char* oat_data_start = reinterpret_cast<const char*>(&oat_file->GetOatHeader());
  const size_t oat_data_length = oat_file->GetOatHeader().GetExecutableOffset();
  const char* oat_code_start = oat_data_start + oat_data_length;
  const size_t oat_code_length = oat_file->Size() - oat_data_length;

  // TODO: ownership of oat_input?
  oat_input_ = ir_builder_->CreateInput("oat contents",
                                        mcld::sys::fs::Path("oat contents path"),
                                        mcld::Input::Object);
  CHECK(oat_input_ != NULL);

  // TODO: ownership of null_section?
  mcld::LDSection* null_section = ir_builder_->CreateELFHeader(*oat_input_,
                                                               "",
                                                               mcld::LDFileFormat::Null,
                                                               llvm::ELF::SHT_NULL,
                                                               0);
  CHECK(null_section != NULL);

  // TODO: we should split readonly data from readonly executable
  // code like .oat does.  We need to control section layout with
  // linker script like functionality to guarantee references
  // between sections maintain relative position which isn't
  // possible right now with the mclinker APIs.
  CHECK(oat_code_start != NULL);

  // we need to ensure that oatdata is page aligned so when we
  // fixup the segment load addresses, they remain page aligned.
  uint32_t alignment = kPageSize;

  // TODO: ownership of text_section?
  mcld::LDSection* text_section = ir_builder_->CreateELFHeader(*oat_input_,
                                                               ".text",
                                                               llvm::ELF::SHT_PROGBITS,
                                                               llvm::ELF::SHF_EXECINSTR
                                                               | llvm::ELF::SHF_ALLOC,
                                                               alignment);
  CHECK(text_section != NULL);

  mcld::SectionData* text_sectiondata = ir_builder_->CreateSectionData(*text_section);
  CHECK(text_sectiondata != NULL);

  // TODO: why does IRBuilder::CreateRegion take a non-const pointer?
  mcld::Fragment* text_fragment = ir_builder_->CreateRegion(const_cast<char*>(oat_data_start),
                                                            oat_file->Size());
  CHECK(text_fragment != NULL);
  ir_builder_->AppendFragment(*text_fragment, *text_sectiondata);

  ir_builder_->AddSymbol(*oat_input_,
                         "oatdata",
                         mcld::ResolveInfo::Object,
                         mcld::ResolveInfo::Define,
                         mcld::ResolveInfo::Global,
                         oat_data_length,  // size
                         0,                // offset
                         text_section);

  ir_builder_->AddSymbol(*oat_input_,
                         "oatexec",
                         mcld::ResolveInfo::Function,
                         mcld::ResolveInfo::Define,
                         mcld::ResolveInfo::Global,
                         oat_code_length,  // size
                         oat_data_length,  // offset
                         text_section);

  ir_builder_->AddSymbol(*oat_input_,
                         "oatlastword",
                         mcld::ResolveInfo::Object,
                         mcld::ResolveInfo::Define,
                         mcld::ResolveInfo::Global,
                         0,                // size
                         // subtract a word so symbol is within section
                         (oat_data_length + oat_code_length) - sizeof(uint32_t),  // offset
                         text_section);
}

#if defined(ART_USE_PORTABLE_COMPILER)
void ElfWriter::AddMethodInputs(const std::vector<const DexFile*>& dex_files) {
  DCHECK(oat_input_ != NULL);

  DexMethodIterator it(dex_files);
  while (it.HasNext()) {
    const DexFile& dex_file = it.GetDexFile();
    uint32_t method_idx = it.GetMemberIndex();
    const CompiledMethod* compiled_method =
      compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(&dex_file, method_idx));
    if (compiled_method != NULL) {
      AddCompiledCodeInput(*compiled_method);
    }
    it.Next();
  }
  added_symbols_.clear();
}

void ElfWriter::AddCompiledCodeInput(const CompiledCode& compiled_code) {
  // Check if we've seen this compiled code before. If so skip
  // it. This can happen for reused code such as invoke stubs.
  const std::string& symbol = compiled_code.GetSymbol();
  SafeMap<const std::string*, const std::string*>::iterator it = added_symbols_.find(&symbol);
  if (it != added_symbols_.end()) {
    return;
  }
  added_symbols_.Put(&symbol, &symbol);

  // Add input to supply code for symbol
  const std::vector<uint8_t>& code = compiled_code.GetCode();
  // TODO: ownership of code_input?
  // TODO: why does IRBuilder::ReadInput take a non-const pointer?
  mcld::Input* code_input = ir_builder_->ReadInput(symbol,
                                                   const_cast<uint8_t*>(&code[0]),
                                                   code.size());
  CHECK(code_input != NULL);
}

void ElfWriter::AddRuntimeInputs(const std::string& android_root, bool is_host) {
  std::string libart_so(android_root);
  libart_so += kIsDebugBuild ? "/lib/libartd.so" : "/lib/libart.so";
  // TODO: ownership of libart_so_input?
  mcld::Input* libart_so_input = ir_builder_->ReadInput(libart_so, libart_so);
  CHECK(libart_so_input != NULL);

  std::string host_prebuilt_dir("prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6");

  std::string compiler_runtime_lib;
  if (is_host) {
    compiler_runtime_lib += host_prebuilt_dir;
    compiler_runtime_lib += "/lib/gcc/i686-linux/4.6.x-google/libgcc.a";
  } else {
    compiler_runtime_lib += android_root;
    compiler_runtime_lib += "/lib/libcompiler_rt.a";
  }
  // TODO: ownership of compiler_runtime_lib_input?
  mcld::Input* compiler_runtime_lib_input = ir_builder_->ReadInput(compiler_runtime_lib,
                                                                   compiler_runtime_lib);
  CHECK(compiler_runtime_lib_input != NULL);

  std::string libc_lib;
  if (is_host) {
    libc_lib += host_prebuilt_dir;
    libc_lib += "/sysroot/usr/lib/libc.so.6";
  } else {
    libc_lib += android_root;
    libc_lib += "/lib/libc.so";
  }
  // TODO: ownership of libc_lib_input?
  mcld::Input* libc_lib_input_input = ir_builder_->ReadInput(libc_lib, libc_lib);
  CHECK(libc_lib_input_input != NULL);

  std::string libm_lib;
  if (is_host) {
    libm_lib += host_prebuilt_dir;
    libm_lib += "/sysroot/usr/lib/libm.so";
  } else {
    libm_lib += android_root;
    libm_lib += "/lib/libm.so";
  }
  // TODO: ownership of libm_lib_input?
  mcld::Input* libm_lib_input_input = ir_builder_->ReadInput(libm_lib, libm_lib);
  CHECK(libm_lib_input_input != NULL);

}
#endif

bool ElfWriter::Link() {
  // link inputs
  if (!linker_->link(*module_.get(), *ir_builder_.get())) {
    LOG(ERROR) << "Failed to link " << elf_file_->GetPath();
    return false;
  }

  // emit linked output
  // TODO: avoid dup of fd by fixing Linker::emit to not close the argument fd.
  int fd = dup(elf_file_->Fd());
  if (fd == -1) {
    PLOG(ERROR) << "Failed to dup file descriptor for " << elf_file_->GetPath();
    return false;
  }
  if (!linker_->emit(fd)) {
    LOG(ERROR) << "Failed to emit " << elf_file_->GetPath();
    return false;
  }
  mcld::Finalize();
  LOG(INFO) << "ELF file written successfully: " << elf_file_->GetPath();
  return true;
}

static llvm::ELF::Elf32_Addr GetOatDataAddress(ElfFile* elf_file) {
  llvm::ELF::Elf32_Addr oatdata_address = elf_file->FindSymbolAddress(llvm::ELF::SHT_DYNSYM,
                                                                      "oatdata",
                                                                      false);
  CHECK_NE(0U, oatdata_address);
  return oatdata_address;
}

#if defined(ART_USE_PORTABLE_COMPILER)
void ElfWriter::FixupOatMethodOffsets(const std::vector<const DexFile*>& dex_files) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(elf_file_, true, false));
  CHECK(elf_file.get() != NULL) << elf_file_->GetPath();

  llvm::ELF::Elf32_Addr oatdata_address = GetOatDataAddress(elf_file.get());
  DexMethodIterator it(dex_files);
  while (it.HasNext()) {
    const DexFile& dex_file = it.GetDexFile();
    uint32_t method_idx = it.GetMemberIndex();
    InvokeType invoke_type = it.GetInvokeType();
    mirror::AbstractMethod* method = NULL;
    if (compiler_driver_->IsImage()) {
      ClassLinker* linker = Runtime::Current()->GetClassLinker();
      mirror::DexCache* dex_cache = linker->FindDexCache(dex_file);
      // Unchecked as we hold mutator_lock_ on entry.
      ScopedObjectAccessUnchecked soa(Thread::Current());
      method = linker->ResolveMethod(dex_file, method_idx, dex_cache, NULL, NULL, invoke_type);
      CHECK(method != NULL);
    }
    const CompiledMethod* compiled_method =
      compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(&dex_file, method_idx));
    if (compiled_method != NULL) {
      uint32_t offset = FixupCompiledCodeOffset(*elf_file.get(), oatdata_address, *compiled_method);
      // Don't overwrite static method trampoline
      if (method != NULL &&
          (!method->IsStatic() ||
           method->IsConstructor() ||
           method->GetDeclaringClass()->IsInitialized())) {
        method->SetOatCodeOffset(offset);
      }
    }
    it.Next();
  }
  symbol_to_compiled_code_offset_.clear();
}

uint32_t ElfWriter::FixupCompiledCodeOffset(ElfFile& elf_file,
                                            llvm::ELF::Elf32_Addr oatdata_address,
                                            const CompiledCode& compiled_code) {
  const std::string& symbol = compiled_code.GetSymbol();
  SafeMap<const std::string*, uint32_t>::iterator it = symbol_to_compiled_code_offset_.find(&symbol);
  if (it != symbol_to_compiled_code_offset_.end()) {
    return it->second;
  }

  llvm::ELF::Elf32_Addr compiled_code_address = elf_file.FindSymbolAddress(llvm::ELF::SHT_SYMTAB,
                                                                           symbol,
                                                                           true);
  CHECK_NE(0U, compiled_code_address) << symbol;
  CHECK_LT(oatdata_address, compiled_code_address) << symbol;
  uint32_t compiled_code_offset = compiled_code_address - oatdata_address;
  symbol_to_compiled_code_offset_.Put(&symbol, compiled_code_offset);

  const std::vector<uint32_t>& offsets = compiled_code.GetOatdataOffsetsToCompliledCodeOffset();
  for (uint32_t i = 0; i < offsets.size(); i++) {
    uint32_t oatdata_offset = oatdata_address + offsets[i];
    uint32_t* addr = reinterpret_cast<uint32_t*>(elf_file.Begin() + oatdata_offset);
    *addr = compiled_code_offset;
  }
  return compiled_code_offset;
}
#endif

static const bool DEBUG_FIXUP = false;

bool ElfWriter::Fixup(File* file, uintptr_t oat_data_begin) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, true, false));
  CHECK(elf_file.get() != NULL);

  // Lookup "oatdata" symbol address.
  ::llvm::ELF::Elf32_Addr oatdata_address = GetOatDataAddress(elf_file.get());
  ::llvm::ELF::Elf32_Off base_address = oat_data_begin - oatdata_address;

  if (!FixupDynamic(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup .dynamic in " << file->GetPath();
      return false;
  }
  if (!FixupSectionHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup section headers in " << file->GetPath();
      return false;
  }
  if (!FixupProgramHeaders(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup program headers in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, true)) {
      LOG(WARNING) << "Failed fo fixup .dynsym in " << file->GetPath();
      return false;
  }
  if (!FixupSymbols(*elf_file.get(), base_address, false)) {
      LOG(WARNING) << "Failed fo fixup .symtab in " << file->GetPath();
      return false;
  }
  if (!FixupRelocations(*elf_file.get(), base_address)) {
      LOG(WARNING) << "Failed fo fixup .rel.dyn in " << file->GetPath();
      return false;
  }
  return true;
}

// MIPS seems to break the rules d_val vs d_ptr even though their values are between DT_LOPROC and DT_HIPROC
#define DT_MIPS_RLD_VERSION  0x70000001 // d_val
#define DT_MIPS_TIME_STAMP   0x70000002 // d_val
#define DT_MIPS_ICHECKSUM    0x70000003 // d_val
#define DT_MIPS_IVERSION     0x70000004 // d_val
#define DT_MIPS_FLAGS        0x70000005 // d_val
#define DT_MIPS_BASE_ADDRESS 0x70000006 // d_ptr
#define DT_MIPS_CONFLICT     0x70000008 // d_ptr
#define DT_MIPS_LIBLIST      0x70000009 // d_ptr
#define DT_MIPS_LOCAL_GOTNO  0x7000000A // d_val
#define DT_MIPS_CONFLICTNO   0x7000000B // d_val
#define DT_MIPS_LIBLISTNO    0x70000010 // d_val
#define DT_MIPS_SYMTABNO     0x70000011 // d_val
#define DT_MIPS_UNREFEXTNO   0x70000012 // d_val
#define DT_MIPS_GOTSYM       0x70000013 // d_val
#define DT_MIPS_HIPAGENO     0x70000014 // d_val
#define DT_MIPS_RLD_MAP      0x70000016 // d_ptr

bool ElfWriter::FixupDynamic(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: C++0x auto.
  for (::llvm::ELF::Elf32_Word i = 0; i < elf_file.GetDynamicNum(); i++) {
    ::llvm::ELF::Elf32_Dyn& elf_dyn = elf_file.GetDynamic(i);
    ::llvm::ELF::Elf32_Word d_tag = elf_dyn.d_tag;
    bool elf_dyn_needs_fixup = false;
    switch (d_tag) {
      // case 1: well known d_tag values that imply Elf32_Dyn.d_un contains an address in d_ptr
      case ::llvm::ELF::DT_PLTGOT:
      case ::llvm::ELF::DT_HASH:
      case ::llvm::ELF::DT_STRTAB:
      case ::llvm::ELF::DT_SYMTAB:
      case ::llvm::ELF::DT_RELA:
      case ::llvm::ELF::DT_INIT:
      case ::llvm::ELF::DT_FINI:
      case ::llvm::ELF::DT_REL:
      case ::llvm::ELF::DT_DEBUG:
      case ::llvm::ELF::DT_JMPREL: {
        elf_dyn_needs_fixup = true;
        break;
      }
      // d_val or ignored values
      case ::llvm::ELF::DT_NULL:
      case ::llvm::ELF::DT_NEEDED:
      case ::llvm::ELF::DT_PLTRELSZ:
      case ::llvm::ELF::DT_RELASZ:
      case ::llvm::ELF::DT_RELAENT:
      case ::llvm::ELF::DT_STRSZ:
      case ::llvm::ELF::DT_SYMENT:
      case ::llvm::ELF::DT_SONAME:
      case ::llvm::ELF::DT_RPATH:
      case ::llvm::ELF::DT_SYMBOLIC:
      case ::llvm::ELF::DT_RELSZ:
      case ::llvm::ELF::DT_RELENT:
      case ::llvm::ELF::DT_PLTREL:
      case ::llvm::ELF::DT_TEXTREL:
      case ::llvm::ELF::DT_BIND_NOW:
      case ::llvm::ELF::DT_INIT_ARRAYSZ:
      case ::llvm::ELF::DT_FINI_ARRAYSZ:
      case ::llvm::ELF::DT_RUNPATH:
      case ::llvm::ELF::DT_FLAGS: {
        break;
      }
      // boundary values that should not be used
      case ::llvm::ELF::DT_ENCODING:
      case ::llvm::ELF::DT_LOOS:
      case ::llvm::ELF::DT_HIOS:
      case ::llvm::ELF::DT_LOPROC:
      case ::llvm::ELF::DT_HIPROC: {
        LOG(FATAL) << "Illegal d_tag value 0x" << std::hex << d_tag;
        break;
      }
      default: {
        // case 2: "regular" DT_* ranges where even d_tag values imply an address in d_ptr
        if ((::llvm::ELF::DT_ENCODING  < d_tag && d_tag < ::llvm::ELF::DT_LOOS)
            || (::llvm::ELF::DT_LOOS   < d_tag && d_tag < ::llvm::ELF::DT_HIOS)
            || (::llvm::ELF::DT_LOPROC < d_tag && d_tag < ::llvm::ELF::DT_HIPROC)) {
          // Special case for MIPS which breaks the regular rules between DT_LOPROC and DT_HIPROC
          if (elf_file.GetHeader().e_machine == ::llvm::ELF::EM_MIPS) {
            switch (d_tag) {
              case DT_MIPS_RLD_VERSION:
              case DT_MIPS_TIME_STAMP:
              case DT_MIPS_ICHECKSUM:
              case DT_MIPS_IVERSION:
              case DT_MIPS_FLAGS:
              case DT_MIPS_LOCAL_GOTNO:
              case DT_MIPS_CONFLICTNO:
              case DT_MIPS_LIBLISTNO:
              case DT_MIPS_SYMTABNO:
              case DT_MIPS_UNREFEXTNO:
              case DT_MIPS_GOTSYM:
              case DT_MIPS_HIPAGENO: {
                break;
              }
              case DT_MIPS_BASE_ADDRESS:
              case DT_MIPS_CONFLICT:
              case DT_MIPS_LIBLIST:
              case DT_MIPS_RLD_MAP: {
                elf_dyn_needs_fixup = true;
                break;
              }
              default: {
                LOG(FATAL) << "Unknown MIPS d_tag value 0x" << std::hex << d_tag;
                break;
              }
            }
          } else if ((elf_dyn.d_tag % 2) == 0) {
            elf_dyn_needs_fixup = true;
          }
        } else {
          LOG(FATAL) << "Unknown d_tag value 0x" << std::hex << d_tag;
        }
        break;
      }
    }
    if (elf_dyn_needs_fixup) {
      uint32_t d_ptr = elf_dyn.d_un.d_ptr;
      if (DEBUG_FIXUP) {
        LOG(INFO) << StringPrintf("In %s moving Elf32_Dyn[%d] from 0x%08x to 0x%08x",
                                  elf_file.GetFile().GetPath().c_str(), i,
                                  d_ptr, d_ptr + base_address);
      }
      d_ptr += base_address;
      elf_dyn.d_un.d_ptr = d_ptr;
    }
  }
  return true;
}

bool ElfWriter::FixupSectionHeaders(ElfFile& elf_file, uintptr_t base_address) {
  for (::llvm::ELF::Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
    ::llvm::ELF::Elf32_Shdr& sh = elf_file.GetSectionHeader(i);
    // 0 implies that the section will not exist in the memory of the process
    if (sh.sh_addr == 0) {
      continue;
    }
    if (DEBUG_FIXUP) {
      LOG(INFO) << StringPrintf("In %s moving Elf32_Shdr[%d] from 0x%08x to 0x%08x",
                                elf_file.GetFile().GetPath().c_str(), i,
                                sh.sh_addr, sh.sh_addr + base_address);
    }
    sh.sh_addr += base_address;
  }
  return true;
}

bool ElfWriter::FixupProgramHeaders(ElfFile& elf_file, uintptr_t base_address) {
  // TODO: ELFObjectFile doesn't have give to Elf32_Phdr, so we do that ourselves for now.
  for (::llvm::ELF::Elf32_Word i = 0; i < elf_file.GetProgramHeaderNum(); i++) {
    ::llvm::ELF::Elf32_Phdr& ph = elf_file.GetProgramHeader(i);
    CHECK_EQ(ph.p_vaddr, ph.p_paddr) << elf_file.GetFile().GetPath() << " i=" << i;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))))
            << elf_file.GetFile().GetPath() << " i=" << i;
    if (DEBUG_FIXUP) {
      LOG(INFO) << StringPrintf("In %s moving Elf32_Phdr[%d] from 0x%08x to 0x%08x",
                                elf_file.GetFile().GetPath().c_str(), i,
                                ph.p_vaddr, ph.p_vaddr + base_address);
    }
    ph.p_vaddr += base_address;
    ph.p_paddr += base_address;
    CHECK((ph.p_align == 0) || (0 == ((ph.p_vaddr - ph.p_offset) & (ph.p_align - 1))))
            << elf_file.GetFile().GetPath() << " i=" << i;
  }
  return true;
}

bool ElfWriter::FixupSymbols(ElfFile& elf_file, uintptr_t base_address, bool dynamic) {
  ::llvm::ELF::Elf32_Word section_type = dynamic ? ::llvm::ELF::SHT_DYNSYM : ::llvm::ELF::SHT_SYMTAB;
  // TODO: Unfortunate ELFObjectFile has protected symbol access, so use ElfFile
  ::llvm::ELF::Elf32_Shdr* symbol_section = elf_file.FindSectionByType(section_type);
  CHECK(symbol_section != NULL) << elf_file.GetFile().GetPath();
  for (uint32_t i = 0; i < elf_file.GetSymbolNum(*symbol_section); i++) {
    ::llvm::ELF::Elf32_Sym& symbol = elf_file.GetSymbol(section_type, i);
    if (symbol.st_value != 0) {
      if (DEBUG_FIXUP) {
        LOG(INFO) << StringPrintf("In %s moving Elf32_Sym[%d] from 0x%08x to 0x%08x",
                                  elf_file.GetFile().GetPath().c_str(), i,
                                  symbol.st_value, symbol.st_value + base_address);
      }
      symbol.st_value += base_address;
    }
  }
  return true;
}

bool ElfWriter::FixupRelocations(ElfFile& elf_file, uintptr_t base_address) {
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file.GetSectionHeaderNum(); i++) {
    llvm::ELF::Elf32_Shdr& sh = elf_file.GetSectionHeader(i);
    if (sh.sh_type == llvm::ELF::SHT_REL) {
      for (uint32_t i = 0; i < elf_file.GetRelNum(sh); i++) {
        llvm::ELF::Elf32_Rel& rel = elf_file.GetRel(sh, i);
        if (DEBUG_FIXUP) {
          LOG(INFO) << StringPrintf("In %s moving Elf32_Rel[%d] from 0x%08x to 0x%08x",
                                    elf_file.GetFile().GetPath().c_str(), i,
                                    rel.r_offset, rel.r_offset + base_address);
        }
        rel.r_offset += base_address;
      }
    } else if (sh.sh_type == llvm::ELF::SHT_RELA) {
      for (uint32_t i = 0; i < elf_file.GetRelaNum(sh); i++) {
        llvm::ELF::Elf32_Rela& rela = elf_file.GetRela(sh, i);
        if (DEBUG_FIXUP) {
          LOG(INFO) << StringPrintf("In %s moving Elf32_Rela[%d] from 0x%08x to 0x%08x",
                                    elf_file.GetFile().GetPath().c_str(), i,
                                    rela.r_offset, rela.r_offset + base_address);
        }
        rela.r_offset += base_address;
      }
    }
  }
  return true;
}

bool ElfWriter::Strip(File* file) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, true, false));
  CHECK(elf_file.get() != NULL);

  // ELF files produced by MCLinker look roughly like this
  //
  // +------------+
  // | Elf32_Ehdr | contains number of Elf32_Shdr and offset to first
  // +------------+
  // | Elf32_Phdr | program headers
  // | Elf32_Phdr |
  // | ...        |
  // | Elf32_Phdr |
  // +------------+
  // | section    | mixture of needed and unneeded sections
  // +------------+
  // | section    |
  // +------------+
  // | ...        |
  // +------------+
  // | section    |
  // +------------+
  // | Elf32_Shdr | section headers
  // | Elf32_Shdr |
  // | ...        | contains offset to section start
  // | Elf32_Shdr |
  // +------------+
  //
  // To strip:
  // - leave the Elf32_Ehdr and Elf32_Phdr values in place.
  // - walk the sections making a new set of Elf32_Shdr section headers for what we want to keep
  // - move the sections are keeping up to fill in gaps of sections we want to strip
  // - write new Elf32_Shdr section headers to end of file, updating Elf32_Ehdr
  // - truncate rest of file
  //

  std::vector<llvm::ELF::Elf32_Shdr> section_headers;
  std::vector<llvm::ELF::Elf32_Word> section_headers_original_indexes;
  section_headers.reserve(elf_file->GetSectionHeaderNum());


  llvm::ELF::Elf32_Shdr& string_section = elf_file->GetSectionNameStringSection();
  for (llvm::ELF::Elf32_Word i = 0; i < elf_file->GetSectionHeaderNum(); i++) {
    llvm::ELF::Elf32_Shdr& sh = elf_file->GetSectionHeader(i);
    const char* name = elf_file->GetString(string_section, sh.sh_name);
    if (name == NULL) {
      CHECK_EQ(0U, i);
      section_headers.push_back(sh);
      section_headers_original_indexes.push_back(0);
      continue;
    }
    if (StartsWith(name, ".debug")
        || (strcmp(name, ".strtab") == 0)
        || (strcmp(name, ".symtab") == 0)) {
      continue;
    }
    section_headers.push_back(sh);
    section_headers_original_indexes.push_back(i);
  }
  CHECK_NE(0U, section_headers.size());
  CHECK_EQ(section_headers.size(), section_headers_original_indexes.size());

  // section 0 is the NULL section, sections start at offset of first section
  llvm::ELF::Elf32_Off offset = elf_file->GetSectionHeader(1).sh_offset;
  for (size_t i = 1; i < section_headers.size(); i++) {
    llvm::ELF::Elf32_Shdr& new_sh = section_headers[i];
    llvm::ELF::Elf32_Shdr& old_sh = elf_file->GetSectionHeader(section_headers_original_indexes[i]);
    CHECK_EQ(new_sh.sh_name, old_sh.sh_name);
    if (old_sh.sh_addralign > 1) {
      offset = RoundUp(offset, old_sh.sh_addralign);
    }
    if (old_sh.sh_offset == offset) {
      // already in place
      offset += old_sh.sh_size;
      continue;
    }
    // shift section earlier
    memmove(elf_file->Begin() + offset,
            elf_file->Begin() + old_sh.sh_offset,
            old_sh.sh_size);
    new_sh.sh_offset = offset;
    offset += old_sh.sh_size;
  }

  llvm::ELF::Elf32_Off shoff = offset;
  size_t section_headers_size_in_bytes = section_headers.size() * sizeof(llvm::ELF::Elf32_Shdr);
  memcpy(elf_file->Begin() + offset, &section_headers[0], section_headers_size_in_bytes);
  offset += section_headers_size_in_bytes;

  elf_file->GetHeader().e_shnum = section_headers.size();
  elf_file->GetHeader().e_shoff = shoff;
  int result = ftruncate(file->Fd(), offset);
  if (result != 0) {
    PLOG(ERROR) << "Failed to truncate while stripping ELF file: " << file->GetPath();
    return false;
  }
  return true;
}

void ElfWriter::GetOatElfInformation(File* file,
                                     size_t& oat_loaded_size,
                                     size_t& oat_data_offset) {
  UniquePtr<ElfFile> elf_file(ElfFile::Open(file, false, false));
  CHECK(elf_file.get() != NULL);

  oat_loaded_size = elf_file->GetLoadedSize();
  CHECK_NE(0U, oat_loaded_size);
  oat_data_offset = GetOatDataAddress(elf_file.get());
  CHECK_NE(0U, oat_data_offset);
}

}  // namespace art
