void ELFObjectWriter::emitSectionHeader(const Module& pModule,
                                        const LinkerConfig& pConfig,
                                        MemoryArea& pOutput) const
{
  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;

  // emit section header
  unsigned int sectNum = pModule.size();
  unsigned int header_size = sizeof(ElfXX_Shdr) * sectNum;
  MemoryRegion* region = pOutput.request(getLastStartOffset<SIZE>(pModule),
                                         header_size);
  ElfXX_Shdr* shdr = (ElfXX_Shdr*)region->start();

  // Iterate the SectionTable in LDContext
  unsigned int sectIdx = 0;
  unsigned int shstridx = 0; // NULL section has empty name
  for (; sectIdx < sectNum; ++sectIdx) {
    const LDSection *ld_sect   = pModule.getSectionTable().at(sectIdx);
    shdr[sectIdx].sh_name      = shstridx;
    shdr[sectIdx].sh_type      = ld_sect->type();
    shdr[sectIdx].sh_flags     = ld_sect->flag();
    shdr[sectIdx].sh_addr      = ld_sect->addr();
    shdr[sectIdx].sh_offset    = ld_sect->offset();
    shdr[sectIdx].sh_size      = ld_sect->size();
    shdr[sectIdx].sh_addralign = ld_sect->align();
    shdr[sectIdx].sh_entsize   = getSectEntrySize<SIZE>(*ld_sect);
    shdr[sectIdx].sh_link      = getSectLink(*ld_sect, pConfig);
    shdr[sectIdx].sh_info      = getSectInfo(*ld_sect);

    // adjust strshidx
    shstridx += ld_sect->name().size() + 1;
  }
}
void ELFObjectWriter::emitProgramHeader(MemoryArea& pOutput) const
{
  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;

  uint64_t start_offset, phdr_size;

  start_offset = sizeof(ElfXX_Ehdr);
  phdr_size = sizeof(ElfXX_Phdr);
  // Program header must start directly after ELF header
  MemoryRegion *region =
    pOutput.request(start_offset,
                    target().elfSegmentTable().size() * phdr_size);

  ElfXX_Phdr* phdr = (ElfXX_Phdr*)region->start();

  // Iterate the elf segment table in GNULDBackend
  size_t index = 0;
  ELFSegmentFactory::const_iterator seg = target().elfSegmentTable().begin(),
                                 segEnd = target().elfSegmentTable().end();
  for (; seg != segEnd; ++seg, ++index) {
    phdr[index].p_type   = (*seg)->type();
    phdr[index].p_flags  = (*seg)->flag();
    phdr[index].p_offset = (*seg)->offset();
    phdr[index].p_vaddr  = (*seg)->vaddr();
    phdr[index].p_paddr  = (*seg)->paddr();
    phdr[index].p_filesz = (*seg)->filesz();
    phdr[index].p_memsz  = (*seg)->memsz();
    phdr[index].p_align  = (*seg)->align();
  }
}
/// isMyFormat
bool ELFDynObjReader::isMyFormat(Input &pInput, bool &pContinue) const
{
    assert(pInput.hasMemArea());

    // Don't warning about the frequently requests.
    // MemoryArea has a list of cache to handle this.
    size_t hdr_size = m_pELFReader->getELFHeaderSize();
    if (pInput.memArea()->size() < hdr_size)
        return false;

    MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
                           hdr_size);

    uint8_t* ELF_hdr = region->start();
    bool result = true;
    if (!m_pELFReader->isELF(ELF_hdr)) {
        pContinue = true;
        result = false;
    } else if (Input::DynObj != m_pELFReader->fileType(ELF_hdr)) {
        pContinue = true;
        result = false;
    } else if (!m_pELFReader->isMyEndian(ELF_hdr)) {
        pContinue = false;
        result = false;
    } else if (!m_pELFReader->isMyMachine(ELF_hdr)) {
        pContinue = false;
        result = false;
    }
    pInput.memArea()->release(region);
    return result;
}
/// computePCBegin - return the address of FDE's pc
/// @ref binutils gold: ehframe.cc:222
uint32_t EhFrameHdr::computePCBegin(const EhFrame::FDE& pFDE,
                                    const MemoryRegion& pEhFrameRegion)
{
    uint8_t fde_encoding = pFDE.getCIE().getFDEEncode();
    unsigned int eh_value = fde_encoding & 0x7;

    // check the size to read in
    if (eh_value == llvm::dwarf::DW_EH_PE_absptr) {
        eh_value = DW_EH_PE_udata4;
    }

    size_t pc_size = 0x0;
    switch (eh_value) {
    case DW_EH_PE_udata2:
        pc_size = 2;
        break;
    case DW_EH_PE_udata4:
        pc_size = 4;
        break;
    case DW_EH_PE_udata8:
        pc_size = 8;
        break;
    default:
        // TODO
        break;
    }

    SizeTraits<32>::Address pc = 0x0;
    const uint8_t* offset = (const uint8_t*) pEhFrameRegion.start() +
                            pFDE.getOffset() +
                            pFDE.getDataStart();
    std::memcpy(&pc, offset, pc_size);

    // adjust the signed value
    bool is_signed = (fde_encoding & llvm::dwarf::DW_EH_PE_signed) != 0x0;
    if (DW_EH_PE_udata2 == eh_value && is_signed)
        pc = (pc ^ 0x8000) - 0x8000;

    // handle eh application
    switch (fde_encoding & 0x70)
    {
    case DW_EH_PE_absptr:
        break;
    case DW_EH_PE_pcrel:
        pc += m_EhFrame.addr() + pFDE.getOffset() + pFDE.getDataStart();
        break;
    case DW_EH_PE_datarel:
        // TODO
        break;
    default:
        // TODO
        break;
    }
    return pc;
}
void ELFObjectWriter::writeELFHeader(const LinkerConfig& pConfig,
                                     const Module& pModule,
                                     MemoryArea& pOutput) const
{
  typedef typename ELFSizeTraits<SIZE>::Ehdr ElfXX_Ehdr;
  typedef typename ELFSizeTraits<SIZE>::Shdr ElfXX_Shdr;
  typedef typename ELFSizeTraits<SIZE>::Phdr ElfXX_Phdr;

  // ELF header must start from 0x0
  MemoryRegion *region = pOutput.request(0, sizeof(ElfXX_Ehdr));
  ElfXX_Ehdr* header = (ElfXX_Ehdr*)region->start();

  memcpy(header->e_ident, ElfMagic, EI_MAG3+1);

  header->e_ident[EI_CLASS]      = (SIZE == 32) ? ELFCLASS32 : ELFCLASS64;
  header->e_ident[EI_DATA]       = pConfig.targets().isLittleEndian()?
                                       ELFDATA2LSB : ELFDATA2MSB;
  header->e_ident[EI_VERSION]    = target().getInfo().ELFVersion();
  header->e_ident[EI_OSABI]      = target().getInfo().OSABI();
  header->e_ident[EI_ABIVERSION] = target().getInfo().ABIVersion();

  // FIXME: add processor-specific and core file types.
  switch(pConfig.codeGenType()) {
    case LinkerConfig::Object:
      header->e_type = ET_REL;
      break;
    case LinkerConfig::DynObj:
      header->e_type = ET_DYN;
      break;
    case LinkerConfig::Exec:
      header->e_type = ET_EXEC;
      break;
    default:
      llvm::errs() << "unspported output file type: " << pConfig.codeGenType() << ".\n";
      header->e_type = ET_NONE;
  }
  header->e_machine   = target().getInfo().machine();
  header->e_version   = header->e_ident[EI_VERSION];
  header->e_entry     = getEntryPoint(pConfig, pModule);

  if (LinkerConfig::Object != pConfig.codeGenType())
    header->e_phoff   = sizeof(ElfXX_Ehdr);
  else
    header->e_phoff   = 0x0;

  header->e_shoff     = getLastStartOffset<SIZE>(pModule);
  header->e_flags     = target().getInfo().flags();
  header->e_ehsize    = sizeof(ElfXX_Ehdr);
  header->e_phentsize = sizeof(ElfXX_Phdr);
  header->e_phnum     = target().elfSegmentTable().size();
  header->e_shentsize = sizeof(ElfXX_Shdr);
  header->e_shnum     = pModule.size();
  header->e_shstrndx  = pModule.getSection(".shstrtab")->index();
}
/// emitShStrTab - emit section string table
void
ELFObjectWriter::emitShStrTab(const LDSection& pShStrTab,
                              const Module& pModule,
                              MemoryArea& pOutput)
{
  // write out data
  MemoryRegion* region = pOutput.request(pShStrTab.offset(), pShStrTab.size());
  unsigned char* data = region->start();
  size_t shstrsize = 0;
  Module::const_iterator section, sectEnd = pModule.end();
  for (section = pModule.begin(); section != sectEnd; ++section) {
    strcpy((char*)(data + shstrsize), (*section)->name().data());
    shstrsize += (*section)->name().size() + 1;
  }
}
// SetUp() will be called immediately before each test.
void ELFReaderTest::SetUp()
{
  Path path(TOPDIR);
  path.append("unittests/test_x86_64.o");

  m_pInput = m_pIRBuilder->ReadInput("test_x86_64", path);
  ASSERT_TRUE(NULL!=m_pInput);

  ASSERT_TRUE(m_pInput->hasMemArea());
  size_t hdr_size = m_pELFReader->getELFHeaderSize();
  MemoryRegion* region = m_pInput->memArea()->request(m_pInput->fileOffset(),
                                                    hdr_size);
  uint8_t* ELF_hdr = region->start();
  bool shdr_result = m_pELFReader->readSectionHeaders(*m_pInput, ELF_hdr);
  m_pInput->memArea()->release(region);
  ASSERT_TRUE(shdr_result);
}
/// readDSO
bool ELFDynObjReader::readDSO(Input& pInput)
{
  assert(pInput.hasMemArea());

  size_t hdr_size = m_pELFReader->getELFHeaderSize();
  MemoryRegion* region = pInput.memArea()->request(pInput.fileOffset(),
                                                   hdr_size);
  uint8_t* ELF_hdr = region->start();

  bool shdr_result = m_pELFReader->readSectionHeaders(pInput, m_Linker, ELF_hdr);
  pInput.memArea()->release(region);

  // read .dynamic to get the correct SONAME
  bool dyn_result = m_pELFReader->readDynamic(pInput);

  return (shdr_result && dyn_result);
}
void ELFObjectWriter::emitRela(const LinkerConfig& pConfig,
                               const RelocData& pRelocData,
                               MemoryRegion& pRegion) const
{
  typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela;
  typedef typename ELFSizeTraits<SIZE>::Addr ElfXX_Addr;
  typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word;

  ElfXX_Rela* rel = reinterpret_cast<ElfXX_Rela*>(pRegion.start());

  const Relocation* relocation = 0;
  const FragmentRef* frag_ref = 0;

  for (RelocData::const_iterator it = pRelocData.begin(),
       ie = pRelocData.end(); it != ie; ++it, ++rel) {
    ElfXX_Addr r_offset = 0;
    ElfXX_Word r_sym = 0;

    relocation = &(llvm::cast<Relocation>(*it));
    frag_ref = &(relocation->targetRef());

    if(LinkerConfig::DynObj == pConfig.codeGenType() ||
       LinkerConfig::Exec == pConfig.codeGenType()) {
      r_offset = static_cast<ElfXX_Addr>(
                      frag_ref->frag()->getParent()->getSection().addr() +
                      frag_ref->getOutputOffset());
    }
    else {
      r_offset = static_cast<ElfXX_Addr>(frag_ref->getOutputOffset());
    }

    if( relocation->symInfo() == NULL )
      r_sym = 0;
    else
      r_sym = static_cast<ElfXX_Word>(
              target().getSymbolIdx(relocation->symInfo()->outSymbol()));

    target().emitRelocation(*rel, relocation->type(),
                            r_sym, r_offset, relocation->addend());
  }
}
uint64_t ARMGNULDBackend::emitSectionData(const Output& pOutput,
                                          const LDSection& pSection,
                                          const MCLDInfo& pInfo,
                                          MemoryRegion& pRegion) const
{
  assert(pRegion.size() && "Size of MemoryRegion is zero!");

  ELFFileFormat* file_format = getOutputFormat(pOutput);

  if (&pSection == m_pAttributes) {
    // FIXME: Currently Emitting .ARM.attributes directly from the input file.
    const llvm::MCSectionData* sect_data = pSection.getSectionData();
    assert(sect_data &&
           "Emit .ARM.attribute failed, MCSectionData doesn't exist!");

    uint8_t* start =
              llvm::cast<MCRegionFragment>(
                     sect_data->getFragmentList().front()).getRegion().start();

    memcpy(pRegion.start(), start, pRegion.size());
    return pRegion.size();
  }

  if (&pSection == &(file_format->getPLT())) {
    assert(NULL != m_pPLT && "emitSectionData failed, m_pPLT is NULL!");
    uint64_t result = m_pPLT->emit(pRegion);
    return result;
  }

  if (&pSection == &(file_format->getGOT())) {
    assert(NULL != m_pGOT && "emitSectionData failed, m_pGOT is NULL!");
    uint64_t result = m_pGOT->emit(pRegion);
    return result;
  }

  llvm::report_fatal_error(llvm::Twine("Unable to emit section `") +
                           pSection.name() +
                           llvm::Twine("'.\n"));
  return 0x0;
}
void raw_mem_ostream::write_impl(const char *pPtr, size_t pSize)
{
  MemoryRegion* region = m_MemoryArea.request(m_Position, pSize);
  memcpy(region->start(), pPtr, pSize);
  m_Position += pSize;
}