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; } }
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); }
// 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 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_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; }
// Get an relocation entry in .rel.dyn and set its type to pType, // its FragmentRef to pReloc->targetFrag() and its ResolveInfo to pReloc->symInfo() static void helper_DynRel(Relocation& pReloc, X86RelocationFactory::Type pType, X86RelocationFactory& pParent) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); X86GNULDBackend& ld_backend = pParent.getTarget(); bool exist; Relocation& rel_entry = *ld_backend.getRelDyn().getEntry(*rsym, false, exist); rel_entry.setType(pType); rel_entry.targetRef() = pReloc.targetRef(); if(pType == llvm::ELF::R_386_RELATIVE) rel_entry.setSymInfo(0); else rel_entry.setSymInfo(rsym); }
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); }
void HexagonRelocator::scanGlobalReloc(Relocation& pReloc, IRBuilder& pBuilder, Module& pModule, LDSection& pSection) { // rsym - The relocation target symbol ResolveInfo* rsym = pReloc.symInfo(); HexagonLDBackend& ld_backend = getTarget(); 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 (ld_backend.symbolNeedsPLT(*rsym)) { // create PLT for this symbol if it does not have. if (!(rsym->reserved() & ReservePLT)) { helper_PLT_init(pReloc, *this); rsym->setReserved(rsym->reserved() | ReservePLT); } } if (ld_backend.symbolNeedsDynRel( *rsym, (rsym->reserved() & ReservePLT), true)) { if (ld_backend.symbolNeedsCopyReloc(pReloc, *rsym)) { LDSymbol& cpy_sym = defineSymbolforCopyReloc(pBuilder, *rsym, ld_backend); addCopyReloc(*cpy_sym.resolveInfo(), ld_backend); } else { 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); rsym->setReserved(rsym->reserved() | ReserveRel); ld_backend.checkAndSetHasTextRel(*pSection.getLink()); } } return; case llvm::ELF::R_HEX_GOTREL_LO16: case llvm::ELF::R_HEX_GOTREL_HI16: case llvm::ELF::R_HEX_GOTREL_32: case llvm::ELF::R_HEX_GOTREL_32_6_X: case llvm::ELF::R_HEX_GOTREL_16_X: case llvm::ELF::R_HEX_GOTREL_11_X: // This assumes that GOT exists return; case llvm::ELF::R_HEX_GOT_LO16: case llvm::ELF::R_HEX_GOT_HI16: case llvm::ELF::R_HEX_GOT_32: case llvm::ELF::R_HEX_GOT_16: case llvm::ELF::R_HEX_GOT_32_6_X: case llvm::ELF::R_HEX_GOT_16_X: case llvm::ELF::R_HEX_GOT_11_X: // Symbol needs GOT entry, reserve entry in .got // return if we already create GOT for this symbol if (rsym->reserved() & ReserveGOT) return; // If the GOT is used in statically linked binaries, // the GOT entry is enough and no relocation is needed. if (config().isCodeStatic()) helper_GOT_init(pReloc, false, *this); else helper_GOT_init(pReloc, true, *this); // set GOT bit rsym->setReserved(rsym->reserved() | ReserveGOT); return; case llvm::ELF::R_HEX_B22_PCREL: case llvm::ELF::R_HEX_B15_PCREL: case llvm::ELF::R_HEX_B7_PCREL: case llvm::ELF::R_HEX_B13_PCREL: case llvm::ELF::R_HEX_B9_PCREL: case llvm::ELF::R_HEX_B32_PCREL_X: case llvm::ELF::R_HEX_B22_PCREL_X: case llvm::ELF::R_HEX_B15_PCREL_X: case llvm::ELF::R_HEX_B13_PCREL_X: case llvm::ELF::R_HEX_B9_PCREL_X: case llvm::ELF::R_HEX_B7_PCREL_X: case llvm::ELF::R_HEX_32_PCREL: case llvm::ELF::R_HEX_6_PCREL_X: case llvm::ELF::R_HEX_PLT_B22_PCREL: if (rsym->reserved() & ReservePLT) return; if (ld_backend.symbolNeedsPLT(*rsym) || pReloc.type() == llvm::ELF::R_HEX_PLT_B22_PCREL) { helper_PLT_init(pReloc, *this); rsym->setReserved(rsym->reserved() | ReservePLT); } return; default: break; } // end of switch }