static PLTEntry& helper_get_PLT_and_init(Relocation& pReloc, X86RelocationFactory& pParent) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); X86GNULDBackend& ld_backend = pParent.getTarget(); bool exist; PLTEntry& plt_entry = *ld_backend.getPLT().getPLTEntry(*rsym, exist); if (!exist) { // If we first get this PLT entry, we should initialize it. if (rsym->reserved() & X86GNULDBackend::ReservePLT) { GOTEntry& gotplt_entry = *ld_backend.getPLT().getGOTPLTEntry(*rsym, exist); // Initialize corresponding dynamic relocation. Relocation& rel_entry = *ld_backend.getRelPLT().getEntry(*rsym, true, exist); assert(!exist && "PLT entry not exist, but DynRel entry exist!"); rel_entry.setType(llvm::ELF::R_386_JUMP_SLOT); rel_entry.targetRef().assign(gotplt_entry); rel_entry.setSymInfo(rsym); } else { llvm::report_fatal_error("No PLT entry reserved for PLT type relocation!"); } } return plt_entry; }
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 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 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; } } }
/// 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; }
void HexagonRelocator::addCopyReloc(ResolveInfo& pSym, HexagonLDBackend& pTarget) { Relocation& rel_entry = *pTarget.getRelaDyn().create(); rel_entry.setType(pTarget.getCopyRelType()); assert(pSym.outSymbol()->hasFragRef()); rel_entry.targetRef().assign(*pSym.outSymbol()->fragRef()); rel_entry.setSymInfo(&pSym); }
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))); }
static bool isSymCtorOrDtor(const ResolveInfo& pSym) { // We can always fold ctors and dtors since accessing function pointer in C++ // is forbidden. llvm::StringRef name(pSym.name(), pSym.nameSize()); if (!name.startswith("_ZZ") && !name.startswith("_ZN")) { return false; } return isCtorOrDtor(pSym.name(), pSym.nameSize()); }
// 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; }
// 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; }
//===----------------------------------------------------------------------===// // Category SymbolCategory::Category::Type SymbolCategory::Category::categorize(const ResolveInfo& pInfo) { if (ResolveInfo::File == pInfo.type()) return Category::File; if (ResolveInfo::Local == pInfo.binding()) return Category::Local; if (ResolveInfo::Common == pInfo.desc()) return Category::Common; if (ResolveInfo::Default == pInfo.visibility() || ResolveInfo::Protected == pInfo.visibility()) return Category::Dynamic; return Category::Regular; }
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; } }
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 DebugString::applyOffset(Relocation& pReloc, TargetLDBackend& pBackend) { // get the refered string ResolveInfo* info = pReloc.symInfo(); // the symbol should point to the first region fragment in the debug // string section, get the input .debut_str region llvm::StringRef d_str; if (info->outSymbol()->fragRef()->frag()->getKind() == Fragment::Region) { RegionFragment* frag = llvm::cast<RegionFragment>(info->outSymbol()->fragRef()->frag()); d_str = frag->getRegion(); } uint32_t offset = pBackend.getRelocator()->getDebugStringOffset(pReloc); const char* str = d_str.data() + offset; // apply the relocation pBackend.getRelocator()->applyDebugStringOffset(pReloc, m_StringTable.getOutputOffset(llvm::StringRef(str, string_length(str)))); }
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); }
// 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; }
static GOTEntry& helper_get_GOT_and_init(Relocation& pReloc, const MCLDInfo& pLDInfo, X86RelocationFactory& pParent) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); X86GNULDBackend& ld_backend = pParent.getTarget(); bool exist; GOTEntry& got_entry = *ld_backend.getGOT().getEntry(*rsym, exist); if (!exist) { // If we first get this GOT entry, we should initialize it. if (rsym->reserved() & X86GNULDBackend::ReserveGOT) { // No corresponding dynamic relocation, initialize to the symbol value. got_entry.setContent(pReloc.symValue()); } else if (rsym->reserved() & X86GNULDBackend::GOTRel) { // Initialize corresponding dynamic relocation. Relocation& rel_entry = *ld_backend.getRelDyn().getEntry(*rsym, true, exist); assert(!exist && "GOT entry not exist, but DynRel entry exist!"); if(helper_use_relative_reloc(*rsym, pLDInfo, pParent)) { // Initialize got entry to target symbol address got_entry.setContent(pReloc.symValue()); rel_entry.setType(llvm::ELF::R_386_RELATIVE); rel_entry.setSymInfo(0); } else { got_entry.setContent(0); rel_entry.setType(llvm::ELF::R_386_GLOB_DAT); rel_entry.setSymInfo(rsym); } rel_entry.targetRef().assign(got_entry); } else { llvm::report_fatal_error("No GOT entry reserved for GOT type relocation!"); } } return got_entry; }
bool MipsGOT::reserveLocalEntry(ResolveInfo& pInfo) { if (pInfo.type() != ResolveInfo::Section) { if (m_InputLocalSymbols.count(&pInfo)) return false; if (m_MergedLocalSymbols.count(&pInfo)) { m_InputLocalSymbols.insert(&pInfo); return false; } } if (isGOTFull()) split(); if (pInfo.type() != ResolveInfo::Section) m_InputLocalSymbols.insert(&pInfo); ++m_MultipartList.back().m_LocalNum; return true; }
// 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::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); }
bool MipsGOT::reserveGlobalEntry(ResolveInfo& pInfo) { if (m_InputGlobalSymbols.count(&pInfo)) return false; if (m_MergedGlobalSymbols.count(&pInfo)) { m_InputGlobalSymbols[&pInfo] = false; return false; } if (isGOTFull()) split(); m_InputGlobalSymbols[&pInfo] = true; ++m_MultipartList.back().m_GlobalNum; if (!(pInfo.reserved() & MipsRelocator::ReserveGot)) { m_SymbolOrderMap[pInfo.outSymbol()] = m_SymbolOrderMap.size(); pInfo.setReserved(pInfo.reserved() | MipsRelocator::ReserveGot); } return true; }
bool ARMGNULDBackend::isSymbolPreemptible(const ResolveInfo& pSym, const MCLDInfo& pLDInfo, const Output& pOutput) const { if(pSym.other() != ResolveInfo::Default) return false; if(Output::DynObj != pOutput.type()) return false; if(pLDInfo.options().Bsymbolic()) return false; return true; }
/// createSymbol - create a symbol ResolveInfo* StrSymPool::createSymbol(const llvm::StringRef& pName, bool pIsDyn, ResolveInfo::Type pType, ResolveInfo::Desc pDesc, ResolveInfo::Binding pBinding, ResolveInfo::SizeType pSize, ResolveInfo::Visibility pVisibility) { ResolveInfo* result = m_Table.getEntryFactory().produce(pName); result->setIsSymbol(true); result->setSource(pIsDyn); result->setType(pType); result->setDesc(pDesc); result->setBinding(pBinding); result->setVisibility(pVisibility); result->setSize(pSize); return result; }
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 }
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 Resolver::Resolve() { for (int i = 1; i <= g_GlobalVars->maxClients; i++) { auto &record = arr_infos[i]; if (!record.m_bActive) continue; C_BasePlayer *player = C_BasePlayer::GetPlayerByIndex(i); if (!player || !player->IsAlive() || player->IsDormant() || player == g_LocalPlayer) continue; if (record.m_flVelocity == 0.f && player->m_vecVelocity().Length2D() != 0.f) { Math::VectorAngles(player->m_vecVelocity(), record.m_angDirectionFirstMoving); record.m_nCorrectedFakewalkIdx = 0; } auto firedShots = g_LocalPlayer->m_iShotsFired(); if (g_Options.debug_fliponkey) { float_t new_yaw = player->m_flLowerBodyYawTarget(); if (g_InputSystem->IsButtonDown(g_Options.debug_flipkey)) new_yaw += 180.f; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; return; } if (g_Options.hvh_resolver_override && g_InputSystem->IsButtonDown(g_Options.hvh_resolver_override_key)) { Override(); //needs an improvement sometimes f****d up xD Global::resolverModes[player->EntIndex()] = "Overriding"; return; } AnimationLayer curBalanceLayer, prevBalanceLayer; ResolveInfo curtickrecord; curtickrecord.SaveRecord(player); if ((player->m_fFlags() & FL_ONGROUND) && (IsFakewalking(player, curtickrecord) || (player->m_vecVelocity().Length2D() > 0.1f && player->m_vecVelocity().Length2D() < 45.f && !(player->m_fFlags() & FL_DUCKING)))) //Fakewalk, shiftwalk check // We have to rework the fakewalk resolving, it sucks :D { float_t new_yaw = ResolveFakewalk(player, curtickrecord); new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; Global::resolverModes[player->EntIndex()] = "Fakewalking"; continue; } if (IsEntityMoving(player)) { float_t new_yaw = player->m_flLowerBodyYawTarget(); new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; record.m_flStandingTime = player->m_flSimulationTime(); record.m_flMovingLBY = player->m_flLowerBodyYawTarget(); record.m_bIsMoving = true; Global::resolverModes[player->EntIndex()] = "Moving"; continue; } if (IsAdjustingBalance(player, curtickrecord, &curBalanceLayer)) { if (fabsf(LBYDelta(curtickrecord)) > 35.f) { float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; Global::resolverModes[player->EntIndex()] = "Fakehead (delta > 35)"; } if (IsAdjustingBalance(player, record, &prevBalanceLayer)) { if ((prevBalanceLayer.m_flCycle != curBalanceLayer.m_flCycle) || curBalanceLayer.m_flWeight == 1.f) { float flAnimTime = curBalanceLayer.m_flCycle, flSimTime = player->m_flSimulationTime(); if (flAnimTime < 0.01f && prevBalanceLayer.m_flCycle > 0.01f && g_Options.rage_lagcompensation && CMBacktracking::Get().IsTickValid(TIME_TO_TICKS(flSimTime - flAnimTime))) { CMBacktracking::Get().SetOverwriteTick(player, QAngle(player->m_angEyeAngles().pitch, player->m_flLowerBodyYawTarget(), 0), (flSimTime - flAnimTime), 2); } float_t new_yaw = player->m_flLowerBodyYawTarget(); new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; Global::resolverModes[player->EntIndex()] = "Breaking LBY"; continue; } else if (curBalanceLayer.m_flWeight == 0.f && (prevBalanceLayer.m_flCycle > 0.92f && curBalanceLayer.m_flCycle > 0.92f)) // breaking lby with delta < 120 { if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving) { record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget(); float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; record.m_bIsMoving = false; Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)"; continue; } if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f) { record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget(); float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; record.m_bIsMoving = false; Global::resolverModes[player->EntIndex()] = "LBY delta < 35"; continue; } } } else { float_t new_yaw = player->m_flLowerBodyYawTarget(); new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; Global::resolverModes[player->EntIndex()] = "Other"; continue; } } if (player->m_flSimulationTime() >= record.m_flStandingTime + 0.22f && record.m_bIsMoving) { record.m_flLbyDelta = record.m_flLowerBodyYawTarget - player->m_flLowerBodyYawTarget(); float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; record.m_bIsMoving = false; Global::resolverModes[player->EntIndex()] = "Breaking LBY (delta < 120)"; continue; } if (player->m_flSimulationTime() >= record.m_flStandingTime + 1.32f && std::fabsf(record.m_flLbyDelta) < 35.f) { record.m_flLbyDelta = record.m_flMovingLBY - player->m_flLowerBodyYawTarget(); float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; record.m_bIsMoving = false; Global::resolverModes[player->EntIndex()] = "LBY delta < 35"; continue; } float_t new_yaw = player->m_flLowerBodyYawTarget() + record.m_flLbyDelta; new_yaw = Math::ClampYaw(new_yaw); player->m_angEyeAngles().yaw = new_yaw; } }
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() ); }
/// readSections - read all regular sections. bool ELFObjectReader::readSections(Input& pInput) { // handle sections LDContext::sect_iterator section, sectEnd = pInput.context()->sectEnd(); for (section = pInput.context()->sectBegin(); section != sectEnd; ++section) { // ignore the section if the LDSection* in input context is NULL if (NULL == *section) continue; switch((*section)->kind()) { /** group sections **/ case LDFileFormat::Group: { assert(NULL != (*section)->getLink()); ResolveInfo* signature = m_pELFReader->readSignature(pInput, *(*section)->getLink(), (*section)->getInfo()); bool exist = false; if (0 == signature->nameSize() && ResolveInfo::Section == signature->type()) { // if the signature is a section symbol in input object, we use the // section name as group signature. signatures().insert((*section)->name(), exist); } else { signatures().insert(signature->name(), exist); } if (exist) { // if this is not the first time we see this group signature, then // ignore all the members in this group (set Ignore) llvm::StringRef region = pInput.memArea()->request( pInput.fileOffset() + (*section)->offset(), (*section)->size()); const llvm::ELF::Elf32_Word* value = reinterpret_cast<const llvm::ELF::Elf32_Word*>(region.begin()); size_t size = region.size() / sizeof(llvm::ELF::Elf32_Word); if (llvm::ELF::GRP_COMDAT == *value) { for (size_t index = 1; index < size; ++index) { pInput.context()->getSection(value[index])->setKind(LDFileFormat::Ignore); } } } ResolveInfo::Destroy(signature); break; } /** linkonce sections **/ case LDFileFormat::LinkOnce: { bool exist = false; // .gnu.linkonce + "." + type + "." + name llvm::StringRef name(llvm::StringRef((*section)->name()).drop_front(14)); signatures().insert(name.split(".").second, exist); if (!exist) { if (name.startswith("wi")) { (*section)->setKind(LDFileFormat::Debug); if (m_Config.options().stripDebug()) (*section)->setKind(LDFileFormat::Ignore); else { SectionData* sd = IRBuilder::CreateSectionData(**section); if (!m_pELFReader->readRegularSection(pInput, *sd)) fatal(diag::err_cannot_read_section) << (*section)->name(); } } else { (*section)->setKind(LDFileFormat::Regular); SectionData* sd = IRBuilder::CreateSectionData(**section); if (!m_pELFReader->readRegularSection(pInput, *sd)) fatal(diag::err_cannot_read_section) << (*section)->name(); } } else { (*section)->setKind(LDFileFormat::Ignore); } break; } /** relocation sections **/ case LDFileFormat::Relocation: { assert(NULL != (*section)->getLink()); size_t link_index = (*section)->getLink()->index(); LDSection* link_sect = pInput.context()->getSection(link_index); if (NULL == link_sect || LDFileFormat::Ignore == link_sect->kind()) { // Relocation sections of group members should also be part of the // group. Thus, if the associated member sections are ignored, the // related relocations should be also ignored. (*section)->setKind(LDFileFormat::Ignore); } break; } /** normal sections **/ // FIXME: support Version Kind case LDFileFormat::Version: // FIXME: support GCCExceptTable Kind case LDFileFormat::GCCExceptTable: /** Fall through **/ case LDFileFormat::Regular: case LDFileFormat::Note: case LDFileFormat::MetaData: { SectionData* sd = IRBuilder::CreateSectionData(**section); if (!m_pELFReader->readRegularSection(pInput, *sd)) fatal(diag::err_cannot_read_section) << (*section)->name(); break; } case LDFileFormat::Debug: { if (m_Config.options().stripDebug()) { (*section)->setKind(LDFileFormat::Ignore); } else { SectionData* sd = IRBuilder::CreateSectionData(**section); if (!m_pELFReader->readRegularSection(pInput, *sd)) { fatal(diag::err_cannot_read_section) << (*section)->name(); } } break; } case LDFileFormat::EhFrame: { EhFrame* eh_frame = IRBuilder::CreateEhFrame(**section); if (m_ReadFlag & ParseEhFrame) { if (!m_pEhFrameReader->read<32, true>(pInput, *eh_frame)) { // if we failed to parse a .eh_frame, we should not parse the rest // .eh_frame. m_ReadFlag ^= ParseEhFrame; } } else { if (!m_pELFReader->readRegularSection(pInput, *eh_frame->getSectionData())) { fatal(diag::err_cannot_read_section) << (*section)->name(); } } break; } /** target dependent sections **/ case LDFileFormat::Target: { SectionData* sd = IRBuilder::CreateSectionData(**section); if (!m_Backend.readSection(pInput, *sd)) { fatal(diag::err_cannot_read_target_section) << (*section)->name(); } break; } /** BSS sections **/ case LDFileFormat::BSS: { IRBuilder::CreateBSS(**section); break; } // ignore case LDFileFormat::Null: case LDFileFormat::NamePool: case LDFileFormat::Ignore: case LDFileFormat::StackNote: continue; // warning case LDFileFormat::EhFrameHdr: default: { warning(diag::warn_illegal_input_section) << (*section)->name() << pInput.name() << pInput.path(); break; } } } // end of for all sections return true; }
void ARMGNULDBackend::scanLocalReloc(Relocation& pReloc, const LDSymbol& pInputSym, MCLinker& pLinker, const MCLDInfo& pLDInfo, const Output& pOutput) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); updateAddend(pReloc, pInputSym, pLinker.getLayout()); 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_ABS32_NOI: { // 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(isPIC(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_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: { // Update value keep in relocation place if we meet a section symbol if(rsym->type() == ResolveInfo::Section) { pReloc.target() = pLinker.getLayout().getOutputOffset( *pInputSym.fragRef()) + pReloc.target(); } // If building PIC object (shared library or PIC executable), // a dynamic relocation for this location is needed. // Reserve an entry in .rel.dyn if(isPIC(pLDInfo, pOutput)) { 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_GOTOFF32: case llvm::ELF::R_ARM_GOTOFF12: { // A GOT section is needed if(NULL == m_pGOT) createARMGOT(pLinker, pOutput); 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_PREL: { // A GOT entry is needed for these relocation type. // 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 PIC object, a dynamic relocation with // type RELATIVE is needed to relocate this GOT entry. // Reserve an entry in .rel.dyn if(isPIC(pLDInfo, pOutput)) { // 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_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(".'")); } 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 }