bool ARMGNULDBackend::isSymbolNeedsDynRel(const ResolveInfo& pSym, const Output& pOutput, bool isAbsReloc) const { if(pSym.isUndef() && (Output::Exec == pOutput.type())) return false; if(pSym.isAbsolute()) return false; if(Output::DynObj == pOutput.type() && isAbsReloc) return true; if(pSym.isDyn() || pSym.isUndef()) return true; return false; }
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); }
/// helper_use_relative_reloc - Check if symbol can use relocation /// R_HEX_RELATIVE static bool helper_use_relative_reloc(const ResolveInfo& pSym, const HexagonRelocator& pFactory) { // if symbol is dynamic or undefine or preemptible if (pSym.isDyn() || pSym.isUndef() || pFactory.getTarget().isSymbolPreemptible(pSym)) return false; return true; }
bool ARMGNULDBackend::isSymbolNeedsPLT(const ResolveInfo& pSym, const MCLDInfo& pLDInfo, const Output& pOutput) const { return (Output::DynObj == pOutput.type() && ResolveInfo::Function == pSym.type() && (pSym.isDyn() || pSym.isUndef() || isSymbolPreemptible(pSym, pLDInfo, pOutput))); }
// Check if symbol can use relocation R_386_RELATIVE static bool helper_use_relative_reloc(const ResolveInfo& pSym, const MCLDInfo& pLDInfo, const X86RelocationFactory& pFactory) { // if symbol is dynamic or undefine or preemptible if(pSym.isDyn() || pSym.isUndef() || pFactory.getTarget().isSymbolPreemptible(pSym, pLDInfo, pLDInfo.output())) return false; return true; }
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); }
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() ); }
void ARMGNULDBackend::scanGlobalReloc(Relocation& pReloc, const LDSymbol& pInputSym, MCLinker& pLinker, const MCLDInfo& pLDInfo, const Output& pOutput) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); switch(pReloc.type()) { // Set R_ARM_TARGET1 to R_ARM_ABS32 // Ref: GNU gold 1.11 arm.cc, line 9892 case llvm::ELF::R_ARM_TARGET1: pReloc.setType(llvm::ELF::R_ARM_ABS32); case llvm::ELF::R_ARM_ABS32: case llvm::ELF::R_ARM_ABS16: case llvm::ELF::R_ARM_ABS12: case llvm::ELF::R_ARM_THM_ABS5: case llvm::ELF::R_ARM_ABS8: case llvm::ELF::R_ARM_BASE_ABS: case llvm::ELF::R_ARM_MOVW_ABS_NC: case llvm::ELF::R_ARM_MOVT_ABS: case llvm::ELF::R_ARM_THM_MOVW_ABS_NC: case llvm::ELF::R_ARM_THM_MOVT_ABS: case llvm::ELF::R_ARM_ABS32_NOI: { // Absolute relocation type, symbol may needs PLT entry or // dynamic relocation entry if(isSymbolNeedsPLT(*rsym, pLDInfo, pOutput)) { // create plt for this symbol if it does not have one if(!(rsym->reserved() & 0x8u)){ // Create .got section if it doesn't exist if(NULL == m_pGOT) createARMGOT(pLinker, pOutput); // create .plt and .rel.plt if not exist if(NULL == m_pPLT) createARMPLTandRelPLT(pLinker, pOutput); // Symbol needs PLT entry, we need to reserve a PLT entry // and the corresponding GOT and dynamic relocation entry // in .got and .rel.plt. (GOT entry will be reserved simultaneously // when calling ARMPLT->reserveEntry()) m_pPLT->reserveEntry(); m_pRelPLT->reserveEntry(*m_pRelocFactory); // set PLT bit rsym->setReserved(rsym->reserved() | 0x8u); } } if(isSymbolNeedsDynRel(*rsym, pOutput, true)) { checkValidReloc(pReloc, pLDInfo, pOutput); // symbol needs dynamic relocation entry, reserve an entry in .rel.dyn // create .rel.dyn section if not exist if(NULL == m_pRelDyn) createARMRelDyn(pLinker, pOutput); m_pRelDyn->reserveEntry(*m_pRelocFactory); // set Rel bit rsym->setReserved(rsym->reserved() | 0x1u); } return; } case llvm::ELF::R_ARM_GOTOFF32: case llvm::ELF::R_ARM_GOTOFF12: { // A GOT section is needed if(NULL == m_pGOT) createARMGOT(pLinker, pOutput); return; } case llvm::ELF::R_ARM_BASE_PREL: // FIXME: Currently we only support R_ARM_BASE_PREL against // symbol _GLOBAL_OFFSET_TABLE_ if(rsym != m_pGOTSymbol->resolveInfo()) { llvm::report_fatal_error(llvm::Twine("Do not support relocation '") + llvm::Twine("R_ARM_BASE_PREL' against symbol '") + llvm::Twine(rsym->name()) + llvm::Twine(".'")); } case llvm::ELF::R_ARM_REL32: case llvm::ELF::R_ARM_LDR_PC_G0: case llvm::ELF::R_ARM_SBREL32: case llvm::ELF::R_ARM_THM_PC8: case llvm::ELF::R_ARM_MOVW_PREL_NC: case llvm::ELF::R_ARM_MOVT_PREL: case llvm::ELF::R_ARM_THM_MOVW_PREL_NC: case llvm::ELF::R_ARM_THM_MOVT_PREL: case llvm::ELF::R_ARM_THM_ALU_PREL_11_0: case llvm::ELF::R_ARM_THM_PC12: case llvm::ELF::R_ARM_REL32_NOI: case llvm::ELF::R_ARM_ALU_PC_G0_NC: case llvm::ELF::R_ARM_ALU_PC_G0: case llvm::ELF::R_ARM_ALU_PC_G1_NC: case llvm::ELF::R_ARM_ALU_PC_G1: case llvm::ELF::R_ARM_ALU_PC_G2: case llvm::ELF::R_ARM_LDR_PC_G1: case llvm::ELF::R_ARM_LDR_PC_G2: case llvm::ELF::R_ARM_LDRS_PC_G0: case llvm::ELF::R_ARM_LDRS_PC_G1: case llvm::ELF::R_ARM_LDRS_PC_G2: case llvm::ELF::R_ARM_LDC_PC_G0: case llvm::ELF::R_ARM_LDC_PC_G1: case llvm::ELF::R_ARM_LDC_PC_G2: case llvm::ELF::R_ARM_ALU_SB_G0_NC: case llvm::ELF::R_ARM_ALU_SB_G0: case llvm::ELF::R_ARM_ALU_SB_G1_NC: case llvm::ELF::R_ARM_ALU_SB_G1: case llvm::ELF::R_ARM_ALU_SB_G2: case llvm::ELF::R_ARM_LDR_SB_G0: case llvm::ELF::R_ARM_LDR_SB_G1: case llvm::ELF::R_ARM_LDR_SB_G2: case llvm::ELF::R_ARM_LDRS_SB_G0: case llvm::ELF::R_ARM_LDRS_SB_G1: case llvm::ELF::R_ARM_LDRS_SB_G2: case llvm::ELF::R_ARM_LDC_SB_G0: case llvm::ELF::R_ARM_LDC_SB_G1: case llvm::ELF::R_ARM_LDC_SB_G2: case llvm::ELF::R_ARM_MOVW_BREL_NC: case llvm::ELF::R_ARM_MOVT_BREL: case llvm::ELF::R_ARM_MOVW_BREL: case llvm::ELF::R_ARM_THM_MOVW_BREL_NC: case llvm::ELF::R_ARM_THM_MOVT_BREL: case llvm::ELF::R_ARM_THM_MOVW_BREL: { // Relative addressing relocation, may needs dynamic relocation if(isSymbolNeedsDynRel(*rsym, pOutput, false)) { checkValidReloc(pReloc, pLDInfo, pOutput); // create .rel.dyn section if not exist if(NULL == m_pRelDyn) createARMRelDyn(pLinker, pOutput); m_pRelDyn->reserveEntry(*m_pRelocFactory); // set Rel bit rsym->setReserved(rsym->reserved() | 0x1u); } return; } case llvm::ELF::R_ARM_THM_CALL: case llvm::ELF::R_ARM_PLT32: case llvm::ELF::R_ARM_CALL: case llvm::ELF::R_ARM_JUMP24: case llvm::ELF::R_ARM_THM_JUMP24: case llvm::ELF::R_ARM_SBREL31: case llvm::ELF::R_ARM_PREL31: case llvm::ELF::R_ARM_THM_JUMP19: case llvm::ELF::R_ARM_THM_JUMP6: case llvm::ELF::R_ARM_THM_JUMP11: case llvm::ELF::R_ARM_THM_JUMP8: { // These are branch relocation (except PREL31) // A PLT entry is needed when building shared library // return if we already create plt for this symbol if(rsym->reserved() & 0x8u) return; // if symbol is defined in the ouput file and it's not // preemptible, no need plt if(rsym->isDefine() && !rsym->isDyn() && !isSymbolPreemptible(*rsym, pLDInfo, pOutput)) { return; } // Create .got section if it doesn't exist if(NULL == m_pGOT) createARMGOT(pLinker, pOutput); // create .plt and .rel.plt if not exist if(NULL == m_pPLT) createARMPLTandRelPLT(pLinker, pOutput); // Symbol needs PLT entry, we need to reserve a PLT entry // and the corresponding GOT and dynamic relocation entry // in .got and .rel.plt. (GOT entry will be reserved simultaneously // when calling ARMPLT->reserveEntry()) m_pPLT->reserveEntry(); m_pRelPLT->reserveEntry(*m_pRelocFactory); // set PLT bit rsym->setReserved(rsym->reserved() | 0x8u); return; } // Set R_ARM_TARGET2 to R_ARM_GOT_PREL // Ref: GNU gold 1.11 arm.cc, line 9892 case llvm::ELF::R_ARM_TARGET2: pReloc.setType(llvm::ELF::R_ARM_GOT_PREL); case llvm::ELF::R_ARM_GOT_BREL: case llvm::ELF::R_ARM_GOT_ABS: case llvm::ELF::R_ARM_GOT_PREL: { // Symbol needs GOT entry, reserve entry in .got // return if we already create GOT for this symbol if(rsym->reserved() & 0x6u) return; if(NULL == m_pGOT) createARMGOT(pLinker, pOutput); m_pGOT->reserveEntry(); // If building shared object or the symbol is undefined, a dynamic // relocation is needed to relocate this GOT entry. Reserve an // entry in .rel.dyn if(Output::DynObj == pOutput.type() || rsym->isUndef() || rsym->isDyn()) { // create .rel.dyn section if not exist if(NULL == m_pRelDyn) createARMRelDyn(pLinker, pOutput); m_pRelDyn->reserveEntry(*m_pRelocFactory); // set GOTRel bit rsym->setReserved(rsym->reserved() | 0x4u); return; } // set GOT bit rsym->setReserved(rsym->reserved() | 0x2u); return; } 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_RELATIVE: { // These are relocation type for dynamic linker, shold not // appear in object file. llvm::report_fatal_error(llvm::Twine("Unexpected reloc ") + llvm::Twine((int)pReloc.type()) + llvm::Twine(" in object file")); break; } default: { break; } } // end switch }