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); }
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; }
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; }
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); } } }
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 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; }
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 }
void ARMGNULDBackend::scanInputExceptionSections(Module& pModule, Input& pInput) { std::unique_ptr<ARMInputExMap> exMap(new ARMInputExMap()); // Scan the input and collect all related sections. LDContext* ctx = pInput.context(); for (LDContext::sect_iterator it = ctx->sectBegin(), end = ctx->sectEnd(); it != end; ++it) { LDSection* sect = *it; llvm::StringRef name(sect->name()); if (name.startswith(".ARM.exidx")) { ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); exTuple->setExIdxSection(sect); exTuple->setTextSection(sect->getLink()); } else if (name.startswith(".ARM.extab")) { ARMExSectionTuple* exTuple = exMap->getOrCreateByExSection(name); exTuple->setExTabSection(sect); } else if (name.startswith(".rel.ARM.exidx")) { ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); exTuple->setRelExIdxSection(sect); } else if (name.startswith(".rel.ARM.extab")) { ARMExSectionTuple* exTuple = exMap->getOrCreateByRelExSection(name); exTuple->setRelExIdxSection(sect); } } // Remove the invalid exception tuples and convert LDSection to RegionFragment // or RelocData. ARMInputExMap::iterator it = exMap->begin(); ARMInputExMap::iterator end = exMap->end(); while (it != end) { ARMExSectionTuple* exTuple = it->second.get(); LDSection* const text = exTuple->getTextSection(); LDSection* const exIdx = exTuple->getExIdxSection(); LDSection* const exTab = exTuple->getExTabSection(); LDSection* const relExIdx = exTuple->getRelExIdxSection(); LDSection* const relExTab = exTuple->getRelExTabSection(); // Check the .ARM.exidx section. if (!exIdx) { if (exTab) { fatal(diag::eh_missing_exidx_section) << exTab->name() << pInput.name(); } else if (relExIdx) { fatal(diag::eh_missing_exidx_section) << relExIdx->name() << pInput.name(); } else if (relExTab) { fatal(diag::eh_missing_exidx_section) << relExTab->name() << pInput.name(); } else { llvm_unreachable("unexpected bad exception tuple"); } } // Check the text section. if (!text) { fatal(diag::eh_missing_text_section) << exIdx->name() << pInput.name(); } // Ignore the exception section if the text section is ignored. if ((text->kind() == LDFileFormat::Ignore) || (text->kind() == LDFileFormat::Folded)) { // Set the related exception sections as LDFileFormat::Ignore. exIdx->setKind(LDFileFormat::Ignore); if (exTab) { exTab->setKind(LDFileFormat::Ignore); } // Remove this tuple from the input exception map. exMap->erase(it++); continue; } // Get RegionFragment from ".text", ".ARM.exidx", and ".ARM.extab" sections. RegionFragment* textFrag = findRegionFragment(*text); RegionFragment* exIdxFrag = findRegionFragment(*exIdx); RegionFragment* exTabFrag = exTab ? findRegionFragment(*exTab) : NULL; exTuple->setTextFragment(textFrag); exTuple->setExIdxFragment(exIdxFrag); exTuple->setExTabFragment(exTabFrag); // Get the RelocData from ".rel.ARM.exidx" and ".rel.ARM.extab" sections. RelocData* exIdxRD = relExIdx ? relExIdx->getRelocData() : NULL; RelocData* exTabRD = relExTab ? relExTab->getRelocData() : NULL; exTuple->setExIdxRelocData(exIdxRD); exTuple->setExTabRelocData(exTabRD); // If there is no region fragment in the .ARM.extab section, then we can // skip this tuple. if (!exIdxFrag) { exMap->erase(it++); continue; } // TODO: Sort the RelocData w.r.t. the fixup offset. // Check next tuple ++it; } // Add input map m_ExData.addInputMap(&pInput, std::move(exMap)); }