// 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; }
// 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; }
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); }
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 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); }
Relocator::Result relocAbs(Relocation& pReloc, HexagonRelocator& pParent) { ResolveInfo* rsym = pReloc.symInfo(); Relocator::Address S = pReloc.symValue(); Relocator::DWord A = pReloc.addend(); Relocation* rel_entry = pParent.getRelRelMap().lookUp(pReloc); bool has_dyn_rel = (rel_entry != NULL); // if the flag of target section is not ALLOC, we eprform only static // relocation. if (0 == (llvm::ELF::SHF_ALLOC & pReloc.targetRef().frag()->getParent()->getSection().flag())) { return applyAbs(pReloc); } // a local symbol with .rela type relocation if (rsym->isLocal() && has_dyn_rel) { rel_entry->setAddend(S + A); return Relocator::OK; } if (!rsym->isLocal()) { if (rsym->reserved() & HexagonRelocator::ReservePLT) { S = helper_get_PLT_address(*rsym, pParent); } if (has_dyn_rel) { if (llvm::ELF::R_HEX_32 == pReloc.type() && helper_use_relative_reloc(*rsym, pParent)) { rel_entry->setAddend(S + A); } else { rel_entry->setAddend(A); return Relocator::OK; } } } return applyAbs(pReloc); }
// 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; }
TEST_F( StaticResolverTest, SetUpBinding) { ResolveInfo* sym = ResolveInfo::Create("abc"); sym->setIsSymbol(true); // ASSERT_FALSE( sym->isSymbol() ); ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setBinding(ResolveInfo::Global); ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( ResolveInfo::Global == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setBinding(ResolveInfo::Weak); ASSERT_TRUE( sym->isSymbol() ); ASSERT_FALSE( sym->isGlobal() ); ASSERT_TRUE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( ResolveInfo::Weak == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setBinding(ResolveInfo::Local); ASSERT_TRUE( sym->isSymbol() ); ASSERT_FALSE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_TRUE( sym->isLocal() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( ResolveInfo::Local == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); }
TEST_F( StaticResolverTest, SetUpDesc) { ResolveInfo* sym = ResolveInfo::Create("abc"); sym->setIsSymbol(true); // ASSERT_FALSE( sym->isSymbol() ); ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setIsSymbol(false); ASSERT_FALSE( sym->isSymbol() ); // ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setDesc(ResolveInfo::Define); ASSERT_FALSE( sym->isSymbol() ); // ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_TRUE( sym->isDefine() ); ASSERT_FALSE( sym->isUndef() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( ResolveInfo::Define == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setDesc(ResolveInfo::Common); ASSERT_FALSE( sym->isSymbol() ); // ASSERT_TRUE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_FALSE( sym->isUndef() ); ASSERT_TRUE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( ResolveInfo::Common == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setDesc(ResolveInfo::Indirect); ASSERT_FALSE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_FALSE( sym->isUndef() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_TRUE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( ResolveInfo::Indirect == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); sym->setDesc(ResolveInfo::Undefined); ASSERT_FALSE( sym->isSymbol() ); ASSERT_TRUE( sym->isGlobal() ); ASSERT_FALSE( sym->isWeak() ); ASSERT_FALSE( sym->isLocal() ); ASSERT_FALSE( sym->isDyn() ); ASSERT_TRUE( sym->isUndef() ); ASSERT_FALSE( sym->isDefine() ); ASSERT_FALSE( sym->isCommon() ); ASSERT_FALSE( sym->isIndirect() ); ASSERT_TRUE( ResolveInfo::NoType == sym->type()); ASSERT_TRUE( 0 == sym->desc() ); ASSERT_TRUE( 0 == sym->binding() ); ASSERT_TRUE( 0 == sym->other() ); }