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; }