/// checkValidReloc - When we attempt to generate a dynamic relocation for /// ouput file, check if the relocation is supported by dynamic linker. void ARMGNULDBackend::checkValidReloc(Relocation& pReloc, const MCLDInfo& pLDInfo, const Output& pOutput) const { // If not building a PIC object, no relocation type is invalid if (!isPIC(pLDInfo, pOutput)) return; switch(pReloc.type()) { case llvm::ELF::R_ARM_RELATIVE: case llvm::ELF::R_ARM_COPY: case llvm::ELF::R_ARM_GLOB_DAT: case llvm::ELF::R_ARM_JUMP_SLOT: case llvm::ELF::R_ARM_ABS32: case llvm::ELF::R_ARM_ABS32_NOI: case llvm::ELF::R_ARM_PC24: case llvm::ELF::R_ARM_TLS_DTPMOD32: case llvm::ELF::R_ARM_TLS_DTPOFF32: case llvm::ELF::R_ARM_TLS_TPOFF32: break; default: llvm::report_fatal_error(llvm::Twine("Attempt to generate unsupported") + llvm::Twine(" relocation type ") + llvm::Twine((int)pReloc.type()) + llvm::Twine(" for symbol '") + llvm::Twine(pReloc.symInfo()->name()) + llvm::Twine("', recompile with -fPIC") ); break; } }
Relocator::Result relocPCREL(Relocation& pReloc, HexagonRelocator& pParent) { ResolveInfo* rsym = pReloc.symInfo(); int64_t result; Relocator::Address S = pReloc.symValue(); Relocator::DWord A = pReloc.addend(); Relocator::DWord P = pReloc.place(); FragmentRef& target_fragref = pReloc.targetRef(); Fragment* target_frag = target_fragref.frag(); LDSection& target_sect = target_frag->getParent()->getSection(); result = (int64_t)(S + A - P); // for relocs inside non ALLOC, just apply if ((llvm::ELF::SHF_ALLOC & target_sect.flag()) == 0) { return applyRel(pReloc, result); } if (!rsym->isLocal()) { if (rsym->reserved() & HexagonRelocator::ReservePLT) { S = helper_get_PLT_address(*rsym, pParent); result = (int64_t)(S + A - P); applyRel(pReloc, result); return Relocator::OK; } } return applyRel(pReloc, result); }
void Stub::applyFixup(Relocation& pSrcReloc, IRBuilder& pBuilder, BranchIsland& pIsland) { // build a name for stub symbol std::string sym_name("__"); sym_name.append(pSrcReloc.symInfo()->name()) .append("_") .append(name()) .append("@") .append(pIsland.name()); // create LDSymbol for the stub LDSymbol* symbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>( sym_name, ResolveInfo::Function, ResolveInfo::Define, ResolveInfo::Local, size(), initSymValue(), FragmentRef::Create(*this, initSymValue()), ResolveInfo::Default); setSymInfo(symbol->resolveInfo()); // add relocations of this stub (i.e., set the branch target of the stub) for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) { Relocation* reloc = Relocation::Create((*it)->type(), *(FragmentRef::Create(*this, (*it)->offset())), (*it)->addend()); reloc->setSymInfo(pSrcReloc.symInfo()); pIsland.addRelocation(*reloc); } }
uint32_t NyuziRelocator::getDebugStringOffset(Relocation& pReloc) const { if (pReloc.type() != llvm::ELF::R_NYUZI_ABS32) error(diag::unsupport_reloc_for_debug_string) << getName(pReloc.type()); return pReloc.symInfo()->outSymbol()->fragRef()->offset() + pReloc.target() + pReloc.addend(); }
void GarbageCollection::setUpReachedSections() { // traverse all the input relocations to setup the reached sections 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) { // bypass the discarded relocation section // 1. its section kind is changed to Ignore. (The target section is a // discarded group section.) // 2. it has no reloc data. (All symbols in the input relocs are in the // discarded group sections) LDSection* reloc_sect = *rs; LDSection* apply_sect = reloc_sect->getLink(); if ((LDFileFormat::Ignore == reloc_sect->kind()) || (!reloc_sect->hasRelocData())) continue; // bypass the apply target sections which are not handled by gc (currently // we only handle the Regular and BSS sections) if (apply_sect->kind() != LDFileFormat::Regular && apply_sect->kind() != LDFileFormat::BSS) continue; bool add_first = false; SectionListTy* reached_sects = NULL; RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end(); for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd; ++reloc_it) { Relocation* reloc = llvm::cast<Relocation>(reloc_it); ResolveInfo* sym = reloc->symInfo(); // only the target symbols defined in the input fragments can make the // reference if (NULL == sym) continue; if (!sym->isDefine() || !sym->outSymbol()->hasFragRef()) continue; // only the target symbols defined in the concerned sections can make // the reference const LDSection* target_sect = &sym->outSymbol()->fragRef()->frag()->getParent()->getSection(); if (target_sect->kind() != LDFileFormat::Regular && target_sect->kind() != LDFileFormat::BSS) continue; // setup the reached list, if we first add the element to reached list // of this section, create an entry in ReachedSections map if (!add_first) { assert(NULL == reached_sects); reached_sects = &m_ReachedSections[apply_sect]; add_first = true; } reached_sects->insert(target_sect); } reached_sects = NULL; add_first = false; } } }
uint32_t RelocationTable::addRelocation(uint64_t offset, uint64_t info){ Relocation* newreloc = NULL; if (elfFile->is64Bit()){ if (type == ElfRelType_rela){ RelocationAddend64* rel = new RelocationAddend64(NULL,relocations.size()); rel->SET(r_addend,0); newreloc = rel; } else { newreloc = new Relocation64(NULL,relocations.size()); } } else { if (type == ElfRelType_rela){ RelocationAddend32* rel = new RelocationAddend32(NULL,relocations.size()); rel->SET(r_addend,0); newreloc = rel; } else { newreloc = new Relocation32(NULL,relocations.size()); } } newreloc->SET(r_offset,offset); newreloc->SET(r_info,info); relocations.append(newreloc); sizeInBytes += relocationSize; // returns the offset of the new entry return relocations.size()-1; verify(); }
/// addStub - add a stub into the island bool BranchIsland::addStub(const Stub* pPrototype, const Relocation& pReloc, Stub& pStub) { bool exist = false; Key key(pPrototype, pReloc.symInfo()->outSymbol(), pReloc.addend()); StubEntryType* entry = m_StubMap.insert(key, exist); if (!exist) { entry->setValue(&pStub); m_pRear = &pStub; SectionData* sd = m_Entry.getParent(); // insert alignment fragment // TODO: check if we can reduce this alignment fragment for some cases AlignFragment* align_frag = new AlignFragment(pStub.alignment(), 0x0, 1u, pStub.alignment() - 1); align_frag->setParent(sd); sd->getFragmentList().insert(end(), align_frag); align_frag->setOffset(align_frag->getPrevNode()->getOffset() + align_frag->getPrevNode()->size()); // insert stub fragment pStub.setParent(sd); sd->getFragmentList().insert(end(), &pStub); pStub.setOffset(pStub.getPrevNode()->getOffset() + pStub.getPrevNode()->size()); } return !exist; }
void CodeSection::relocate(address at, RelocationHolder const& spec, int format) { Relocation* reloc = spec.reloc(); relocInfo::relocType rtype = (relocInfo::relocType) reloc->type(); if (rtype == relocInfo::none) return; // The assertion below has been adjusted, to also work for // relocation for fixup. Sometimes we want to put relocation // information for the next instruction, since it will be patched // with a call. assert(start() <= at && at <= end()+1, "cannot relocate data outside code boundaries"); if (!has_locs()) { // no space for relocation information provided => code cannot be // relocated. Make sure that relocate is only called with rtypes // that can be ignored for this kind of code. assert(rtype == relocInfo::none || rtype == relocInfo::runtime_call_type || rtype == relocInfo::internal_word_type|| rtype == relocInfo::section_word_type || rtype == relocInfo::external_word_type, "code needs relocation information"); // leave behind an indication that we attempted a relocation DEBUG_ONLY(_locs_start = _locs_limit = (relocInfo*)badAddress); return; } // Advance the point, noting the offset we'll have to record. csize_t offset = at - locs_point(); set_locs_point(at); // Test for a couple of overflow conditions; maybe expand the buffer. relocInfo* end = locs_end(); relocInfo* req = end + relocInfo::length_limit; // Check for (potential) overflow if (req >= locs_limit() || offset >= relocInfo::offset_limit()) { req += (uint)offset / (uint)relocInfo::offset_limit(); if (req >= locs_limit()) { // Allocate or reallocate. expand_locs(locs_count() + (req - end)); // reload pointer end = locs_end(); } } // If the offset is giant, emit filler relocs, of type 'none', but // each carrying the largest possible offset, to advance the locs_point. while (offset >= relocInfo::offset_limit()) { assert(end < locs_limit(), "adjust previous paragraph of code"); *end++ = filler_relocInfo(); offset -= filler_relocInfo().addr_offset(); } // If it's a simple reloc with no data, we'll just write (rtype | offset). (*end) = relocInfo(rtype, offset, format); // If it has data, insert the prefix, as (data_prefix_tag | data1), data2. end->initialize(this, reloc); }
Relocator::Result abs(Relocation& pReloc, NyuziRelocator& pParent) { Relocator::DWord A = pReloc.addend(); Relocator::DWord S = pReloc.symValue(); pReloc.target() = S + A; return Relocator::OK; }
void ARMGNULDBackend::updateAddend(Relocation& pReloc, const LDSymbol& pInputSym, const Layout& pLayout) const { // Update value keep in addend if we meet a section symbol if(pReloc.symInfo()->type() == ResolveInfo::Section) { pReloc.setAddend(pLayout.getOutputOffset( *pInputSym.fragRef()) + pReloc.addend()); } }
// R_386_PC32: S + A - P X86RelocationFactory::Result rel32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { // perform static relocation RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); pReloc.target() = pReloc.symValue() + A - pReloc.place(pParent.getLayout()); return X86RelocationFactory::OK; }
// R_386_GOTPC: GOT_ORG + A - P X86RelocationFactory::Result gotpc32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); // Apply relocation. pReloc.target() = GOT_ORG + A - pReloc.place(pParent.getLayout()); return X86RelocationFactory::OK; }
// R_386_GOTOFF: S + A - GOT_ORG X86RelocationFactory::Result gotoff32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); X86RelocationFactory::Address S = pReloc.symValue(); pReloc.target() = S + A - GOT_ORG; return X86RelocationFactory::OK; }
void X86RelocationFactory::applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo) { Relocation::Type type = pRelocation.type(); /// the prototype of applying function typedef Result (*ApplyFunctionType)(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent); // the table entry of applying functions struct ApplyFunctionTriple { ApplyFunctionType func; unsigned int type; const char* name; }; // declare the table of applying functions static ApplyFunctionTriple apply_functions[] = { DECL_X86_APPLY_RELOC_FUNC_PTRS }; if (type >= sizeof (apply_functions) / sizeof (apply_functions[0]) ) { llvm::report_fatal_error(llvm::Twine("Unknown relocation type ") + llvm::Twine((int) type) + llvm::Twine(" to symbol `") + pRelocation.symInfo()->name() + llvm::Twine("'.")); return; } // apply the relocation Result result = apply_functions[type].func(pRelocation, pLDInfo, *this); // check result if (Overflow == result) { llvm::report_fatal_error(llvm::Twine("Applying relocation `") + llvm::Twine(apply_functions[type].name) + llvm::Twine("' causes overflow. on symbol: `") + llvm::Twine(pRelocation.symInfo()->name()) + llvm::Twine("'.")); return; } if (BadReloc == result) { llvm::report_fatal_error(llvm::Twine("Applying relocation `") + llvm::Twine(apply_functions[type].name) + llvm::Twine("' encounters unexpected opcode. " "on symbol: `") + llvm::Twine(pRelocation.symInfo()->name()) + llvm::Twine("'.")); return; } }
// R_386_32: S + A X86RelocationFactory::Result abs32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { ResolveInfo* rsym = pReloc.symInfo(); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); RelocationFactory::DWord S = pReloc.symValue(); bool has_dyn_rel = pParent.getTarget().symbolNeedsDynRel( *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo, pLDInfo.output(), true); const LDSection* target_sect = pParent.getLayout().getOutputLDSection( *(pReloc.targetRef().frag())); assert(NULL != target_sect); // If the flag of target section is not ALLOC, we will not scan this relocation // but perform static relocation. (e.g., applying .debug section) if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { pReloc.target() = S + A; return X86RelocationFactory::OK; } // A local symbol may need REL Type dynamic relocation if (rsym->isLocal() && has_dyn_rel) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); pReloc.target() = S + A; return X86RelocationFactory::OK; } // An external symbol may need PLT and dynamic relocation if (!rsym->isLocal()) { if (rsym->reserved() & X86GNULDBackend::ReservePLT) { S = helper_PLT(pReloc, pParent); pReloc.target() = S + A; } // If we generate a dynamic relocation (except R_386_RELATIVE) // for a place, we should not perform static relocation on it // in order to keep the addend store in the place correct. if (has_dyn_rel) { if (helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); } else { helper_DynRel(pReloc, pReloc.type(), pParent); return X86RelocationFactory::OK; } } } // perform static relocation pReloc.target() = S + A; return X86RelocationFactory::OK; }
Relocator::Result lea(Relocation& pReloc, NyuziRelocator& pParent) { Relocator::Address S = pReloc.symValue(); Relocator::Address P = pReloc.place(); int offset = S - (P + 4); if (helper_check_signed_overflow(offset, 13)) return Relocator::Overflow; pReloc.target() = helper_replace_field(pReloc.target(), offset, 10, 13); return Relocator::OK; }
// R_386_32: S + A X86RelocationFactory::Result abs32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { ResolveInfo* rsym = pReloc.symInfo(); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); RelocationFactory::DWord S = pReloc.symValue(); if(rsym->isLocal() && (rsym->reserved() & X86GNULDBackend::ReserveRel)) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); pReloc.target() = S + A; return X86RelocationFactory::OK; } else if(!rsym->isLocal()) { if(rsym->reserved() & X86GNULDBackend::ReservePLT) { S = helper_PLT(pReloc, pParent); pReloc.target() = S + A; } if(rsym->reserved() & X86GNULDBackend::ReserveRel) { if(helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); } else { helper_DynRel(pReloc, pReloc.type(), pParent); return X86RelocationFactory::OK; } } } // perform static relocation pReloc.target() = S + A; return X86RelocationFactory::OK; }
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; }
// R_386_GOT32: GOT(S) + A - GOT_ORG X86RelocationFactory::Result got32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { if(!(pReloc.symInfo()->reserved() & (X86GNULDBackend::ReserveGOT |X86GNULDBackend::GOTRel))) { return X86RelocationFactory::BadReloc; } X86RelocationFactory::Address GOT_S = helper_GOT(pReloc, pLDInfo, pParent); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); X86RelocationFactory::Address GOT_ORG = helper_GOT_ORG(pParent); // Apply relocation. pReloc.target() = GOT_S + A - GOT_ORG; return X86RelocationFactory::OK; }
RelocationFactory::Result X86RelocationFactory::applyRelocation(Relocation& pRelocation, const MCLDInfo& pLDInfo) { Relocation::Type type = pRelocation.type(); if (type >= sizeof (ApplyFunctions) / sizeof (ApplyFunctions[0]) ) { fatal(diag::unknown_relocation) << (int)type << pRelocation.symInfo()->name(); return Unknown; } // apply the relocation return ApplyFunctions[type].func(pRelocation, pLDInfo, *this); }
void AArch64GNULDBackend::scanErrata(Module& pModule, IRBuilder& pBuilder, size_t& num_new_stubs, size_t& stubs_strlen) { // TODO: Implement AArch64 ErrataStubFactory to create the specific erratum // stub and simplify the logics. for (Module::iterator sect = pModule.begin(), sectEnd = pModule.end(); sect != sectEnd; ++sect) { if (((*sect)->kind() == LDFileFormat::TEXT) && (*sect)->hasSectionData()) { SectionData* sd = (*sect)->getSectionData(); for (SectionData::iterator it = sd->begin(), ie = sd->end(); it != ie; ++it) { Fragment* frag = llvm::dyn_cast<RegionFragment>(it); if (frag != NULL) { FragmentRef* frag_ref = FragmentRef::Create(*frag, 0); for (unsigned offset = 0; offset < frag->size(); offset += AArch64InsnHelpers::InsnSize) { Stub* stub = getStubFactory()->create(*frag_ref, pBuilder, *getBRIslandFactory()); if (stub != NULL) { // A stub symbol should be local assert(stub->symInfo() != NULL && stub->symInfo()->isLocal()); const AArch64CA53ErratumStub* erratum_stub = reinterpret_cast<const AArch64CA53ErratumStub*>(stub); assert(erratum_stub != NULL); // Rewrite the erratum instruction as a branch to the stub. uint64_t offset = frag_ref->offset() + erratum_stub->getErratumInsnOffset(); Relocation* reloc = Relocation::Create(llvm::ELF::R_AARCH64_JUMP26, *(FragmentRef::Create(*frag, offset)), /* pAddend */0); reloc->setSymInfo(stub->symInfo()); reloc->target() = AArch64InsnHelpers::buildBranchInsn(); addExtraRelocation(reloc); ++num_new_stubs; stubs_strlen += stub->symInfo()->nameSize() + 1; } frag_ref->assign(*frag, offset + AArch64InsnHelpers::InsnSize); } // for each INSN } } // for each FRAGMENT } } // for each TEXT section }
void HexagonLDBackend::scanRelocation(Relocation& pReloc, IRBuilder& pBuilder, Module& pModule, LDSection& pSection) { pReloc.updateAddend(); }
bool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) { uint64_t sym_value = 0x0; LDSymbol* symbol = pRel.symInfo()->outSymbol(); if (symbol->hasFragRef()) { uint64_t value = symbol->fragRef()->getOutputOffset(); uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr(); sym_value = addr + value; } Stub* stub = getStubFactory()->create( pRel, sym_value, pBuilder, *getBRIslandFactory()); if (stub == NULL) return false; assert(stub->symInfo() != NULL); // increase the size of .symtab and .strtab LDSection& symtab = getOutputFormat()->getSymTab(); LDSection& strtab = getOutputFormat()->getStrTab(); symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym)); strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1); return true; }
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); }
void ARMGNULDBackend::scanRelocation(Relocation& pReloc, const LDSymbol& pInputSym, MCLinker& pLinker, const MCLDInfo& pLDInfo, const Output& pOutput) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); assert(NULL != rsym && "ResolveInfo of relocation not set while scanRelocation"); // Scan relocation type to determine if an GOT/PLT/Dynamic Relocation // entries should be created. // FIXME: Below judgements concern only .so is generated as output // FIXME: Below judgements concern nothing about TLS related relocation // A refernece to symbol _GLOBAL_OFFSET_TABLE_ implies that a .got section // is needed if(NULL == m_pGOT && NULL != m_pGOTSymbol) { if(rsym == m_pGOTSymbol->resolveInfo()) { createARMGOT(pLinker, pOutput); } } // rsym is local if(rsym->isLocal()) scanLocalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); // rsym is external else scanGlobalReloc(pReloc, pInputSym, pLinker, pLDInfo, pOutput); }
void HexagonRelocator::partialScanRelocation(Relocation& pReloc, Module& pModule, const LDSection& pSection) { pReloc.updateAddend(); // if we meet a section symbol if (pReloc.symInfo()->type() == ResolveInfo::Section) { LDSymbol* input_sym = pReloc.symInfo()->outSymbol(); // 1. update the relocation target offset assert(input_sym->hasFragRef()); // 2. get the output LDSection which the symbol defined in const LDSection& out_sect = input_sym->fragRef()->frag()->getParent()->getSection(); ResolveInfo* sym_info = pModule.getSectionSymbolSet().get(out_sect)->resolveInfo(); // set relocation target symbol to the output section symbol's resolveInfo pReloc.setSymInfo(sym_info); } }
bool MipsLA25Stub::isMyDuty(const Relocation& pReloc, uint64_t pSource, uint64_t pTargetSymValue) const { if (llvm::ELF::R_MIPS_26 != pReloc.type()) return false; const ResolveInfo* rsym = pReloc.symInfo(); if (!rsym->isDefine()) return false; if (rsym->isDyn() || rsym->isUndef()) return false; if (!m_Target.hasNonPICBranch(rsym)) return false; return true; }
Relocator::Result HexagonRelocator::applyRelocation(Relocation& pRelocation) { Relocation::Type type = pRelocation.type(); if (type > 85) { // 86-255 relocs do not exists for Hexagon return Relocator::Unknown; } // apply the relocation return ApplyFunctions[type].func(pRelocation, *this); }
// R_386_PC32: S + A - P X86RelocationFactory::Result rel32(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { ResolveInfo* rsym = pReloc.symInfo(); RelocationFactory::DWord A = pReloc.target() + pReloc.addend(); RelocationFactory::DWord S = pReloc.symValue(); RelocationFactory::DWord P = pReloc.place(pParent.getLayout()); const LDSection* target_sect = pParent.getLayout().getOutputLDSection( *(pReloc.targetRef().frag())); assert(NULL != target_sect); // If the flag of target section is not ALLOC, we will not scan this relocation // but perform static relocation. (e.g., applying .debug section) if (0x0 == (llvm::ELF::SHF_ALLOC & target_sect->flag())) { pReloc.target() = S + A - P; return X86RelocationFactory::OK; } // An external symbol may need PLT and dynamic relocation if (!rsym->isLocal()) { if (rsym->reserved() & X86GNULDBackend::ReservePLT) { S = helper_PLT(pReloc, pParent); pReloc.target() = S + A - P; } if (pParent.getTarget().symbolNeedsDynRel( *rsym, (rsym->reserved() & X86GNULDBackend::ReservePLT), pLDInfo, pLDInfo.output(), false)) { if (helper_use_relative_reloc(*rsym, pLDInfo, pParent) ) { helper_DynRel(pReloc, llvm::ELF::R_386_RELATIVE, pParent); } else { helper_DynRel(pReloc, pReloc.type(), pParent); return X86RelocationFactory::OK; } } } // perform static relocation pReloc.target() = S + A - P; return X86RelocationFactory::OK; }