bool ARMGNULDBackend::mergeSection(Module& pModule, const Input& pInput, LDSection& pSection) { switch (pSection.type()) { case llvm::ELF::SHT_ARM_ATTRIBUTES: { return attribute().merge(pInput, pSection); } case llvm::ELF::SHT_ARM_EXIDX: { assert(NULL != pSection.getLink()); if ((pSection.getLink()->kind() == LDFileFormat::Ignore) || (pSection.getLink()->kind() == LDFileFormat::Folded)) { // if the target section of the .ARM.exidx is Ignore, then it should be // ignored as well pSection.setKind(LDFileFormat::Ignore); return true; } } /** fall through **/ default: { ObjectBuilder builder(pModule); builder.MergeSection(pInput, pSection); return true; } } // end of switch return true; }
void GarbageCollection::stripSections() { // Traverse all the input Regular and BSS sections, if a section is not found // in the ReferencedSections, then it should be garbage collected Module::obj_iterator obj, objEnd = m_Module.obj_end(); for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) { LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd(); for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) { LDSection* section = *sect; if (LDFileFormat::Regular != section->kind() && LDFileFormat::BSS != section->kind()) continue; if (m_ReferencedSections.find(section) == m_ReferencedSections.end()) section->setKind(LDFileFormat::Ignore); } } // Traverse all the relocation sections, if its target section is set to // Ignore, then set the relocation section to Ignore as well Module::obj_iterator input, inEnd = m_Module.obj_end(); for (input = m_Module.obj_begin(); input != inEnd; ++input) { LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { LDSection* reloc_sect = *rs; if (LDFileFormat::Ignore == reloc_sect->getLink()->kind()) reloc_sect->setKind(LDFileFormat::Ignore); } } }
bool SectionSymbolSet::finalize(LDSection& pOutSect, SymbolTable& pSymTab, bool relocatable) { if (!relocatable && pOutSect.size() == 0) return true; LDSymbol* sym = get(pOutSect); assert(NULL != sym); SectionData* data = NULL; switch (pOutSect.kind()) { case LDFileFormat::Relocation: // Relocation section should not have section symbol. return true; case LDFileFormat::EhFrame: if (EhFrame *ehframe = pOutSect.getEhFrame()) data = ehframe->getSectionData(); break; default: data = pOutSect.getSectionData(); break; } FragmentRef* frag_ref; if (data && !data->empty()) frag_ref = FragmentRef::Create(data->front(), 0x0); else frag_ref = FragmentRef::Null(); sym->setFragmentRef(frag_ref); // push symbol into output symbol table pSymTab.add(*sym); return true; }
void IdenticalCodeFolding::findCandidates(FoldingCandidates& pCandidateList) { Module::obj_iterator obj, objEnd = m_Module.obj_end(); for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) { std::set<const LDSection*> funcptr_access_set; typedef std::map<LDSection*, LDSection*> CandidateMap; CandidateMap candidate_map; LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd(); for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) { switch ((*sect)->kind()) { case LDFileFormat::TEXT: { candidate_map.insert( std::make_pair(*sect, reinterpret_cast<LDSection*>(NULL))); break; } case LDFileFormat::Relocation: { LDSection* target = (*sect)->getLink(); if (target->kind() == LDFileFormat::TEXT) { candidate_map[target] = *sect; } // Safe icf if (m_Config.options().getICFMode() == GeneralOptions::ICF::Safe) { RelocData::iterator rel, relEnd = (*sect)->getRelocData()->end(); for (rel = (*sect)->getRelocData()->begin(); rel != relEnd; ++rel) { LDSymbol* sym = rel->symInfo()->outSymbol(); if (sym->hasFragRef() && (sym->type() == ResolveInfo::Function)) { const LDSection* def = &sym->fragRef()->frag()->getParent()->getSection(); if (!isSymCtorOrDtor(*rel->symInfo()) && m_Backend.mayHaveUnsafeFunctionPointerAccess(*target) && m_Backend.getRelocator() ->mayHaveFunctionPointerAccess(*rel)) { funcptr_access_set.insert(def); } } } // for each reloc } break; } default: { // skip break; } } // end of switch } // for each section CandidateMap::iterator candidate, candidateEnd = candidate_map.end(); for (candidate = candidate_map.begin(); candidate != candidateEnd; ++candidate) { if ((m_Config.options().getICFMode() == GeneralOptions::ICF::All) || (funcptr_access_set.count(candidate->first) == 0)) { size_t index = m_KeptSections.size(); m_KeptSections[candidate->first] = ObjectAndId(*obj, index); pCandidateList.push_back( FoldingCandidate(candidate->first, candidate->second, *obj)); } } // for each possible candidate } // for each obj }
void HexagonRelocator::scanRelocation(Relocation& pReloc, IRBuilder& pLinker, Module& pModule, LDSection& pSection, Input& pInput) { if (LinkerConfig::Object == config().codeGenType()) return; // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); assert(rsym != NULL && "ResolveInfo of relocation not set while scanRelocation"); if (config().isCodeStatic()) return; assert(pSection.getLink() != NULL); if ((pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC) == 0) return; if (rsym->isLocal()) // rsym is local scanLocalReloc(pReloc, pLinker, pModule, pSection); else // rsym is external scanGlobalReloc(pReloc, pLinker, pModule, pSection); // check if we should issue undefined reference for the relocation target // symbol if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) issueUndefRef(pReloc, pSection, pInput); }
/// emitRelocation void ELFObjectWriter::emitRelocation(const LinkerConfig& pConfig, const LDSection& pSection, MemoryRegion& pRegion) const { const RelocData* sect_data = pSection.getRelocData(); assert(NULL != sect_data && "SectionData is NULL in emitRelocation!"); if (pSection.type() == SHT_REL) { if (pConfig.targets().is32Bits()) emitRel<32>(pConfig, *sect_data, pRegion); else if (pConfig.targets().is64Bits()) emitRel<64>(pConfig, *sect_data, pRegion); else { fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str() << pConfig.targets().bitclass(); } } else if (pSection.type() == SHT_RELA) { if (pConfig.targets().is32Bits()) emitRela<32>(pConfig, *sect_data, pRegion); else if (pConfig.targets().is64Bits()) emitRela<64>(pConfig, *sect_data, pRegion); else { fatal(diag::unsupported_bitclass) << pConfig.targets().triple().str() << pConfig.targets().bitclass(); } } else llvm::report_fatal_error("unsupported relocation section type!"); }
/// 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; } }
/// getSectInfo - compute ElfXX_Shdr::sh_info uint64_t ELFObjectWriter::getSectInfo(const LDSection& pSection) const { if (llvm::ELF::SHT_SYMTAB == pSection.type() || llvm::ELF::SHT_DYNSYM == pSection.type()) return pSection.getInfo(); if (llvm::ELF::SHT_REL == pSection.type() || llvm::ELF::SHT_RELA == pSection.type()) { const LDSection* info_link = pSection.getLink(); if (NULL != info_link) return info_link->index(); } return 0x0; }
void GarbageCollection::getEntrySections(SectionVecTy& pEntry) { // all the KEEP sections defined in ldscript are entries, traverse all the // input sections and check the SectionMap to find the KEEP sections Module::obj_iterator obj, objEnd = m_Module.obj_end(); SectionMap& sect_map = m_Module.getScript().sectionMap(); for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) { const std::string input_name = (*obj)->name(); LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd(); for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) { LDSection* section = *sect; if (LDFileFormat::Regular != section->kind() && LDFileFormat::BSS != section->kind()) continue; SectionMap::Input* sm_input = sect_map.find(input_name, section->name()).second; if ((sm_input != NULL) && (InputSectDesc::Keep == sm_input->policy())) pEntry.push_back(section); } } // get the sections those the entry symbols defined in Module::SymbolTable& sym_tab = m_Module.getSymbolTable(); if (LinkerConfig::Exec == m_Config.codeGenType()) { assert(NULL != m_pEntry); pEntry.push_back(&m_pEntry->fragRef()->frag()->getParent()->getSection()); } else { // when building shared objects, the global define symbols are entries SymbolCategory::iterator it, end = sym_tab.regularEnd(); for (it = sym_tab.dynamicBegin(); it != end; ++it) { LDSymbol* sym = *it; if (!sym->resolveInfo()->isDefine() || !sym->hasFragRef()) continue; // only the target symbols defined in the concerned sections can make // the reference const LDSection* sect = &sym->fragRef()->frag()->getParent()->getSection(); if (sect->kind() != LDFileFormat::Regular && sect->kind() != LDFileFormat::BSS) continue; pEntry.push_back(sect); } } }
//===----------------------------------------------------------------------===// // HexagonGOTPLT //===----------------------------------------------------------------------===// HexagonGOTPLT::HexagonGOTPLT(LDSection& pSection) : HexagonGOT(pSection) { // Skip GOT0 entries for (size_t i = 0; i < HexagonGOTPLT0Num; ++i) { create(); } pSection.setAlign(8); }
bool SectionSymbolSet::add(LDSection& pOutSect, NamePool& pNamePool) { // create the resolveInfo for this section symbol llvm::StringRef sym_name = llvm::StringRef(pOutSect.name()); ResolveInfo* sym_info = pNamePool.createSymbol(sym_name, false, ResolveInfo::Section, ResolveInfo::Define, ResolveInfo::Local, 0x0, // size ResolveInfo::Default); // create the output section symbol and set its fragRef to the first fragment // of the section LDSymbol* sym = LDSymbol::Create(*sym_info); sym_info->setSymPtr(sym); // insert the symbol to the Section to Symbol hash map bool exist = false; SectHashTableType::entry_type* entry = m_pSectionSymbolMap->insert(&pOutSect, exist); assert(!exist); entry->setValue(sym); return true; }
bool ARMGNULDBackend::readSection(Input& pInput, MCLinker& pLinker, LDSection& pInputSectHdr) { LDSection& out_sect = pLinker.getOrCreateOutputSectHdr(pInputSectHdr.name(), pInputSectHdr.kind(), pInputSectHdr.type(), pInputSectHdr.flag()); // FIXME: (Luba) // Handle ARM attributes in the right way. // In current milestone, MCLinker goes through the shortcut. // It reads input's ARM attributes and copies the first ARM attributes // into the output file. The correct way is merge these sections, not // just copy. if ((0 == out_sect.name().compare(".ARM.attributes")) && (0 != out_sect.size())) return true; MemoryRegion* region = pInput.memArea()->request(pInputSectHdr.offset(), pInputSectHdr.size()); llvm::MCSectionData& sect_data = pLinker.getOrCreateSectData(pInputSectHdr); new MCRegionFragment(*region, §_data); out_sect.setSize(out_sect.size() + pInputSectHdr.size()); return true; }
/// mayHaveUnsafeFunctionPointerAccess - check if the section may have unsafe /// function pointer access bool ARMGNULDBackend::mayHaveUnsafeFunctionPointerAccess(const LDSection& pSection) const { llvm::StringRef name(pSection.name()); return !name.startswith(".ARM.exidx") && !name.startswith(".ARM.extab") && GNULDBackend::mayHaveUnsafeFunctionPointerAccess(pSection); }
void NyuziRelocator::scanRelocation(Relocation& pReloc, IRBuilder& pBuilder, Module& pModule, LDSection& pSection, Input& pInput) { ResolveInfo* rsym = pReloc.symInfo(); assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); assert(NULL != pSection.getLink()); if (0 == (pSection.getLink()->flag() & llvm::ELF::SHF_ALLOC)) return; // check if we shoule issue undefined reference for the relocation target // symbol if (rsym->isUndef() && !rsym->isDyn() && !rsym->isWeak() && !rsym->isNull()) issueUndefRef(pReloc, pSection, pInput); }
/// merge Input Sections bool HexagonLDBackend::mergeSection(Module& pModule, const Input& pInputFile, LDSection& pInputSection) { if ((pInputSection.flag() & llvm::ELF::SHF_HEX_GPREL) || (pInputSection.kind() == LDFileFormat::LinkOnce) || (pInputSection.kind() == LDFileFormat::Target)) { SectionData* sd = NULL; if (!m_psdata->hasSectionData()) { sd = IRBuilder::CreateSectionData(*m_psdata); m_psdata->setSectionData(sd); } sd = m_psdata->getSectionData(); MoveSectionDataAndSort(*pInputSection.getSectionData(), *sd); } else { ObjectBuilder builder(pModule); builder.MergeSection(pInputFile, pInputSection); } return true; }
//========================== // DebugString void DebugString::merge(LDSection& pSection) { // get the fragment contents llvm::StringRef strings; SectionData::iterator it, end = pSection.getSectionData()->end(); for (it = pSection.getSectionData()->begin(); it != end; ++it) { if ((*it).getKind() == Fragment::Region) { RegionFragment* frag = llvm::cast<RegionFragment>(&(*it)); strings = frag->getRegion().data(); } } // get the debug strings and add them into merged string table const char* str = strings.data(); const char* str_end = str + pSection.size(); while (str < str_end) { size_t len = string_length(str); m_StringTable.insertString(llvm::StringRef(str, len)); str = str + len + 1; } }
//===----------------------------------------------------------------------===// // HexagonGOTPLT //===----------------------------------------------------------------------===// HexagonGOTPLT::HexagonGOTPLT(LDSection& pSection) : HexagonGOT(pSection) { // Create GOT0 entries reserve(HexagonGOTPLT0Num); // Skip GOT0 entries for (size_t i = 0; i < HexagonGOTPLT0Num; ++i) { consume(); } pSection.setAlign(8); }
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; }
uint64_t X86GNULDBackend::emitSectionData(const LDSection& pSection, MemoryRegion& pRegion) const { assert(pRegion.size() && "Size of MemoryRegion is zero!"); const ELFFileFormat* FileFormat = getOutputFormat(); assert(FileFormat && "ELFFileFormat is NULL in X86GNULDBackend::emitSectionData!"); unsigned int EntrySize = 0; uint64_t RegionSize = 0; if (&pSection == &(FileFormat->getPLT())) { assert(m_pPLT && "emitSectionData failed, m_pPLT is NULL!"); unsigned char* buffer = pRegion.getBuffer(); m_pPLT->applyPLT0(); m_pPLT->applyPLT1(); X86PLT::iterator it = m_pPLT->begin(); unsigned int plt0_size = llvm::cast<PLTEntryBase>((*it)).size(); memcpy(buffer, llvm::cast<PLTEntryBase>((*it)).getValue(), plt0_size); RegionSize += plt0_size; ++it; PLTEntryBase* plt1 = 0; X86PLT::iterator ie = m_pPLT->end(); while (it != ie) { plt1 = &(llvm::cast<PLTEntryBase>(*it)); EntrySize = plt1->size(); memcpy(buffer + RegionSize, plt1->getValue(), EntrySize); RegionSize += EntrySize; ++it; } } else if (&pSection == &(FileFormat->getGOT())) { RegionSize += emitGOTSectionData(pRegion); } else if (&pSection == &(FileFormat->getGOTPLT())) { RegionSize += emitGOTPLTSectionData(pRegion, FileFormat); } else { fatal(diag::unrecognized_output_sectoin) << pSection.name() << "*****@*****.**"; } return RegionSize; }
uint64_t ELFObjectWriter::getSectEntrySize(const LDSection& pSection) const { typedef typename ELFSizeTraits<SIZE>::Word ElfXX_Word; typedef typename ELFSizeTraits<SIZE>::Sym ElfXX_Sym; typedef typename ELFSizeTraits<SIZE>::Rel ElfXX_Rel; typedef typename ELFSizeTraits<SIZE>::Rela ElfXX_Rela; typedef typename ELFSizeTraits<SIZE>::Dyn ElfXX_Dyn; if (llvm::ELF::SHT_DYNSYM == pSection.type() || llvm::ELF::SHT_SYMTAB == pSection.type()) return sizeof(ElfXX_Sym); if (llvm::ELF::SHT_REL == pSection.type()) return sizeof(ElfXX_Rel); if (llvm::ELF::SHT_RELA == pSection.type()) return sizeof(ElfXX_Rela); if (llvm::ELF::SHT_HASH == pSection.type() || llvm::ELF::SHT_GNU_HASH == pSection.type()) return sizeof(ElfXX_Word); if (llvm::ELF::SHT_DYNAMIC == pSection.type()) return sizeof(ElfXX_Dyn); return 0x0; }
/// group - group fragments and create islands when needed /// @param pSectionData - the SectionData holds fragments need to be grouped void BranchIslandFactory::group(Module& pModule) { /* FIXME: Currently only support relaxing .text section! */ LDSection* text = pModule.getSection(".text"); if (text != NULL && text->hasSectionData()) { SectionData& sd = *text->getSectionData(); uint64_t group_end = m_MaxFwdBranchRange; for (SectionData::iterator it = sd.begin(), ie = sd.end(); it != ie; ++it) { if ((*it).getOffset() + (*it).size() > group_end) { Fragment* frag = (*it).getPrevNode(); while (frag != NULL && frag->getKind() == Fragment::Alignment) { frag = frag->getPrevNode(); } if (frag != NULL) { produce(*frag); group_end = (*it).getOffset() + m_MaxFwdBranchRange; } } } if (getIslands(sd.back()).first == NULL) produce(sd.back()); } }
void HexagonRelocator::scanLocalReloc(Relocation& pReloc, IRBuilder& pBuilder, Module& pModule, LDSection& pSection) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); switch (pReloc.type()) { case llvm::ELF::R_HEX_LO16: case llvm::ELF::R_HEX_HI16: case llvm::ELF::R_HEX_16: case llvm::ELF::R_HEX_8: case llvm::ELF::R_HEX_32_6_X: case llvm::ELF::R_HEX_16_X: case llvm::ELF::R_HEX_12_X: case llvm::ELF::R_HEX_11_X: case llvm::ELF::R_HEX_10_X: case llvm::ELF::R_HEX_9_X: case llvm::ELF::R_HEX_8_X: case llvm::ELF::R_HEX_7_X: case llvm::ELF::R_HEX_6_X: assert(!(rsym->reserved() & ReserveRel) && "Cannot apply this relocation for read only section"); return; case llvm::ELF::R_HEX_32: // If buiding PIC object (shared library or PIC executable), // a dynamic relocations with RELATIVE type to this location is needed. // Reserve an entry in .rel.dyn if (config().isCodeIndep()) { Relocation& reloc = helper_DynRel_init(rsym, *pReloc.targetRef().frag(), pReloc.targetRef().offset(), llvm::ELF::R_HEX_RELATIVE, *this); // we need to set up the relocation addend at apply relocation, record // the // relocation getRelRelMap().record(pReloc, reloc); // set Rel bit rsym->setReserved(rsym->reserved() | ReserveRel); getTarget().checkAndSetHasTextRel(*pSection.getLink()); } return; default: return; } }
void Relocator::issueUndefRef(Relocation& pReloc, LDSection& pSection, Input& pInput) { FragmentRef::Offset undef_sym_pos = pReloc.targetRef().offset(); std::string sect_name(pSection.name()); sect_name = sect_name.substr(sect_name.find('.', /*pos=*/1)); // Drop .rel(a) prefix std::string reloc_sym(pReloc.symInfo()->name()); if (reloc_sym.substr(0, 2) == "_Z") reloc_sym = demangleSymbol(reloc_sym); std::stringstream ss; ss << "0x" << std::hex << undef_sym_pos; std::string undef_sym_pos_hex(ss.str()); if (sect_name.substr(0, 5) != ".text") { // Function name is only valid for text section fatal(diag::undefined_reference) << reloc_sym << pInput.path() << sect_name << undef_sym_pos_hex; return; } std::string caller_file_name; std::string caller_func_name; for (LDContext::sym_iterator i = pInput.context()->symTabBegin(), e = pInput.context()->symTabEnd(); i != e; ++i) { LDSymbol& sym = **i; if (sym.resolveInfo()->type() == ResolveInfo::File) caller_file_name = sym.resolveInfo()->name(); if (sym.resolveInfo()->type() == ResolveInfo::Function && sym.value() <= undef_sym_pos && sym.value() + sym.size() > undef_sym_pos) { caller_func_name = sym.name(); break; } } if (caller_func_name.substr(0, 2) == "_Z") caller_func_name = demangleSymbol(caller_func_name); fatal(diag::undefined_reference_text) << reloc_sym << pInput.path() << caller_file_name << caller_func_name; }
bool MipsAbiFlags::fillBySection(const Input& pInput, const LDSection& pSection, MipsAbiFlags& mipsAbi) { assert(pSection.type() == llvm::ELF::SHT_MIPS_ABIFLAGS && "Unexpected section type"); if (pSection.size() != size()) { error(diag::error_Mips_abiflags_invalid_size) << pInput.name(); return false; } const SectionData* secData = pSection.getSectionData(); if (secData->size() != 2 || !llvm::isa<RegionFragment>(secData->front())) { error(diag::error_Mips_abiflags_invalid_size) << pInput.name(); return false; } const auto& frag = llvm::cast<RegionFragment>(secData->front()); auto* data = reinterpret_cast<const ElfMipsAbiFlags*>(frag.getRegion().data()); if (data->version != 0) { error(diag::error_Mips_abiflags_invalid_version) << int(data->version) << pInput.name(); return false; } mipsAbi.m_IsaLevel = data->isa_level; mipsAbi.m_IsaRev = data->isa_rev; mipsAbi.m_GprSize = data->gpr_size; mipsAbi.m_Cpr1Size = data->cpr1_size; mipsAbi.m_Cpr2Size = data->cpr2_size; mipsAbi.m_FpAbi = data->fp_abi; mipsAbi.m_IsaExt = data->isa_ext; mipsAbi.m_Ases = data->ases; mipsAbi.m_Flags1 = data->flags1; return true; }
/// emit void ELFDynamic::emit(const LDSection& pSection, MemoryRegion& pRegion) const { if (pRegion.size() < pSection.size()) { llvm::report_fatal_error(llvm::Twine("the given memory is smaller") + llvm::Twine(" than the section's demaind.\n")); } uint8_t* address = (uint8_t*)pRegion.begin(); EntryListType::const_iterator entry, entryEnd = m_NeedList.end(); for (entry = m_NeedList.begin(); entry != entryEnd; ++entry) address += (*entry)->emit(address); entryEnd = m_EntryList.end(); for (entry = m_EntryList.begin(); entry != entryEnd; ++entry) address += (*entry)->emit(address); }
uint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection, MemoryRegion& pRegion) const { assert(pRegion.size() && "Size of MemoryRegion is zero!"); const ELFFileFormat* file_format = getOutputFormat(); if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) { return m_pGOT->emit(pRegion); } if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) { return m_pPLT->emit(pRegion); } if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) { return m_pGOTPLT->emit(pRegion); } fatal(diag::unrecognized_output_sectoin) << pSection.name() << "*****@*****.**"; return 0; }
/// emitSectionData void ELFObjectWriter::emitSectionData(const LDSection& pSection, MemoryRegion& pRegion) const { const SectionData* sd = NULL; switch (pSection.kind()) { case LDFileFormat::Relocation: assert(pSection.hasRelocData()); return; case LDFileFormat::EhFrame: assert(pSection.hasEhFrame()); sd = pSection.getEhFrame()->getSectionData(); break; default: assert(pSection.hasSectionData()); sd = pSection.getSectionData(); break; } emitSectionData(*sd, pRegion); }
/// getSectLink - compute ElfXX_Shdr::sh_link uint64_t ELFObjectWriter::getSectLink(const LDSection& pSection, const LinkerConfig& pConfig) const { if (llvm::ELF::SHT_SYMTAB == pSection.type()) return target().getOutputFormat()->getStrTab().index(); if (llvm::ELF::SHT_DYNSYM == pSection.type()) return target().getOutputFormat()->getDynStrTab().index(); if (llvm::ELF::SHT_DYNAMIC == pSection.type()) return target().getOutputFormat()->getDynStrTab().index(); if (llvm::ELF::SHT_HASH == pSection.type() || llvm::ELF::SHT_GNU_HASH == pSection.type()) return target().getOutputFormat()->getDynSymTab().index(); if (llvm::ELF::SHT_REL == pSection.type() || llvm::ELF::SHT_RELA == pSection.type()) { if (LinkerConfig::Object == pConfig.codeGenType()) return target().getOutputFormat()->getSymTab().index(); else return target().getOutputFormat()->getDynSymTab().index(); } // FIXME: currently we link ARM_EXIDX section to output text section here if (llvm::ELF::SHT_ARM_EXIDX == pSection.type()) return target().getOutputFormat()->getText().index(); return llvm::ELF::SHN_UNDEF; }
bool MipsGNULDBackend::doRelax(Module& pModule, IRBuilder& pBuilder, bool& pFinished) { assert(getStubFactory() != NULL && getBRIslandFactory() != NULL); bool isRelaxed = false; for (Module::obj_iterator input = pModule.obj_begin(); input != pModule.obj_end(); ++input) { LDContext* context = (*input)->context(); for (LDContext::sect_iterator rs = context->relocSectBegin(); rs != context->relocSectEnd(); ++rs) { LDSection* sec = *rs; if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData()) continue; for (RelocData::iterator reloc = sec->getRelocData()->begin(); reloc != sec->getRelocData()->end(); ++reloc) { if (llvm::ELF::R_MIPS_26 != reloc->type()) continue; if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc))) isRelaxed = true; } } } SectionData* textData = getOutputFormat()->getText().getSectionData(); // find the first fragment w/ invalid offset due to stub insertion Fragment* invalid = NULL; pFinished = true; for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(), ie = getBRIslandFactory()->end(); ii != ie; ++ii) { BranchIsland& island = *ii; if (island.end() == textData->end()) break; Fragment* exit = island.end(); if ((island.offset() + island.size()) > exit->getOffset()) { invalid = exit; pFinished = false; break; } } // reset the offset of invalid fragments while (invalid != NULL) { invalid->setOffset(invalid->getPrevNode()->getOffset() + invalid->getPrevNode()->size()); invalid = invalid->getNextNode(); } // reset the size of .text if (isRelaxed) getOutputFormat()->getText().setSize(textData->back().getOffset() + textData->back().size()); return isRelaxed; }
void IdenticalCodeFolding::foldIdenticalCode() { // 1. Find folding candidates. FoldingCandidates candidate_list; findCandidates(candidate_list); // 2. Initialize constant section content for (size_t i = 0; i < candidate_list.size(); ++i) { candidate_list[i].initConstantContent(m_Backend, m_KeptSections); } // 3. Find identical code until convergence bool converged = false; size_t iterations = 0; while (!converged && (iterations < m_Config.options().getICFIterations())) { converged = matchCandidates(candidate_list); ++iterations; } if (m_Config.options().printICFSections()) { debug(diag::debug_icf_iterations) << iterations; } // 4. Fold the identical code typedef std::set<Input*> FoldedObjects; FoldedObjects folded_objs; KeptSections::iterator kept, keptEnd = m_KeptSections.end(); size_t index = 0; for (kept = m_KeptSections.begin(); kept != keptEnd; ++kept, ++index) { LDSection* sect = (*kept).first; Input* obj = (*kept).second.first; size_t kept_index = (*kept).second.second; if (index != kept_index) { sect->setKind(LDFileFormat::Folded); folded_objs.insert(obj); if (m_Config.options().printICFSections()) { KeptSections::iterator it = m_KeptSections.begin() + kept_index; LDSection* kept_sect = (*it).first; Input* kept_obj = (*it).second.first; debug(diag::debug_icf_folded_section) << sect->name() << obj->name() << kept_sect->name() << kept_obj->name(); } } } // Adjust the fragment reference of the folded symbols. FoldedObjects::iterator fobj, fobjEnd = folded_objs.end(); for (fobj = folded_objs.begin(); fobj != fobjEnd; ++fobj) { LDContext::sym_iterator sym, symEnd = (*fobj)->context()->symTabEnd(); for (sym = (*fobj)->context()->symTabBegin(); sym != symEnd; ++sym) { if ((*sym)->hasFragRef() && ((*sym)->type() == ResolveInfo::Function)) { LDSymbol* out_sym = (*sym)->resolveInfo()->outSymbol(); FragmentRef* frag_ref = out_sym->fragRef(); LDSection* sect = &(frag_ref->frag()->getParent()->getSection()); if (sect->kind() == LDFileFormat::Folded) { size_t kept_index = m_KeptSections[sect].second; LDSection* kept_sect = (*(m_KeptSections.begin() + kept_index)).first; frag_ref->assign(kept_sect->getSectionData()->front(), frag_ref->offset()); } } } // for each symbol } // for each folded object }