static typename ELFT::uint getSymVA(const SymbolBody &Body, typename ELFT::uint &Addend) { typedef typename ELFT::uint uintX_t; switch (Body.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast<DefinedSynthetic<ELFT>>(Body); const OutputSectionBase<ELFT> *Sec = D.Section; if (!Sec) return D.Value; if (D.Value == DefinedSynthetic<ELFT>::SectionEnd) return Sec->getVA() + Sec->getSize(); return Sec->getVA() + D.Value; } case SymbolBody::DefinedRegularKind: { auto &D = cast<DefinedRegular<ELFT>>(Body); InputSectionBase<ELFT> *SC = D.Section; // According to the ELF spec reference to a local symbol from outside // the group are not allowed. Unfortunately .eh_frame breaks that rule // and must be treated specially. For now we just replace the symbol with // 0. if (SC == &InputSection<ELFT>::Discarded) return 0; // This is an absolute symbol. if (!SC) return D.Value; uintX_t Offset = D.Value; if (D.isSection()) { Offset += Addend; Addend = 0; } uintX_t VA = SC->OutSec->getVA() + SC->getOffset(Offset); if (D.isTls()) return VA - Out<ELFT>::TlsPhdr->p_vaddr; return VA; } case SymbolBody::DefinedCommonKind: return Out<ELFT>::Bss->getVA() + cast<DefinedCommon>(Body).OffsetInBss; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(Body); if (!SS.NeedsCopyOrPltAddr) return 0; if (SS.isFunc()) return Body.getPltVA<ELFT>(); return Out<ELFT>::Bss->getVA() + SS.OffsetInBss; } case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); return 0; case SymbolBody::DefinedBitcodeKind: llvm_unreachable("should have been replaced"); } llvm_unreachable("invalid symbol kind"); }
void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { InputSectionBase *Sec = getRelocatedSection(); for (const RelTy &Rel : Rels) { RelType Type = Rel.getType(Config->IsMips64EL); Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel); auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf); Buf += sizeof(RelTy); if (Config->IsRela) P->r_addend = getAddend<ELFT>(Rel); // Output section VA is zero for -r, so r_offset is an offset within the // section, but for --emit-relocs it is an virtual address. P->r_offset = Sec->getOutputSection()->Addr + Sec->getOffset(Rel.r_offset); P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type, Config->IsMips64EL); if (Sym.Type == STT_SECTION) { // We combine multiple section symbols into only one per // section. This means we have to update the addend. That is // trivial for Elf_Rela, but for Elf_Rel we have to write to the // section data. We do that by adding to the Relocation vector. // .eh_frame is horribly special and can reference discarded sections. To // avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which // hopefully creates a frame that is ignored at runtime. auto *D = dyn_cast<Defined>(&Sym); if (!D) { error("STT_SECTION symbol should be defined"); continue; } SectionBase *Section = D->Section; if (Section == &InputSection::Discarded) { P->setSymbolAndType(0, 0, false); continue; } if (Config->IsRela) { P->r_addend = Sym.getVA(getAddend<ELFT>(Rel)) - Section->getOutputSection()->Addr; } else if (Config->Relocatable) { const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset; Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Target->getImplicitAddend(BufLoc, Type), &Sym}); } } } }
void InputSection<ELFT>::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { InputSectionBase<ELFT> *RelocatedSection = getRelocatedSection(); for (const RelTy &Rel : Rels) { uint32_t Type = Rel.getType(Config->Mips64EL); SymbolBody &Body = this->File->getRelocTargetSym(Rel); RelTy *P = reinterpret_cast<RelTy *>(Buf); Buf += sizeof(RelTy); P->r_offset = RelocatedSection->getOffset(Rel.r_offset); P->setSymbolAndType(Body.DynsymIndex, Type, Config->Mips64EL); } }
void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &S, const Elf_Shdr &RelSec) { ELFFile<ELFT> &EObj = S.getFile()->getObj(); if (RelSec.sh_type == SHT_RELA) scanRelocs(S, EObj.relas(&RelSec)); else scanRelocs(S, EObj.rels(&RelSec)); }
template <class ELFT> void OutputSection::finalize() { if (Type == SHT_NOBITS) for (BaseCommand *Base : SectionCommands) if (isa<ByteCommand>(Base)) Type = SHT_PROGBITS; std::vector<InputSection *> V = getInputSections(this); InputSection *First = V.empty() ? nullptr : V[0]; if (Flags & SHF_LINK_ORDER) { // We must preserve the link order dependency of sections with the // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, // all InputSections in the OutputSection have the same dependency. if (auto *D = First->getLinkOrderDep()) Link = D->getParent()->SectionIndex; } if (Type == SHT_GROUP) { finalizeShtGroup<ELFT>(this, First); return; } if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL)) return; if (isa<SyntheticSection>(First)) return; Link = In.SymTab->getParent()->SectionIndex; // sh_info for SHT_REL[A] sections should contain the section header index of // the section to which the relocation applies. InputSectionBase *S = First->getRelocatedSection(); Info = S->getOutputSection()->SectionIndex; Flags |= SHF_INFO_LINK; }
void Writer<ELFT>::scanRelocs( InputSectionBase<ELFT> &C, iterator_range<const Elf_Rel_Impl<ELFT, isRela> *> Rels) { typedef Elf_Rel_Impl<ELFT, isRela> RelType; const ObjectFile<ELFT> &File = *C.getFile(); for (const RelType &RI : Rels) { uint32_t SymIndex = RI.getSymbol(Config->Mips64EL); SymbolBody *Body = File.getSymbolBody(SymIndex); uint32_t Type = RI.getType(Config->Mips64EL); if (Target->isTlsLocalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, nullptr)) continue; if (Out<ELFT>::LocalModuleTlsIndexOffset == uint32_t(-1)) { Out<ELFT>::LocalModuleTlsIndexOffset = Out<ELFT>::Got->addLocalModuleTlsIndex(); Out<ELFT>::RelaDyn->addReloc({&C, &RI}); } continue; } // Set "used" bit for --as-needed. if (Body && Body->isUndefined() && !Body->isWeak()) if (auto *S = dyn_cast<SharedSymbol<ELFT>>(Body->repl())) S->File->IsUsed = true; if (Body) Body = Body->repl(); if (Body && Body->isTLS() && Target->isTlsGlobalDynamicReloc(Type)) { if (Target->isTlsOptimized(Type, Body)) continue; if (Body->isInGot()) continue; Out<ELFT>::Got->addDynTlsEntry(Body); Out<ELFT>::RelaDyn->addReloc({&C, &RI}); Out<ELFT>::RelaDyn->addReloc({nullptr, nullptr}); Body->setUsedInDynamicReloc(); continue; } if (Body && Body->isTLS() && !Target->isTlsDynReloc(Type)) continue; bool NeedsGot = false; bool NeedsPlt = false; if (Body) { if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) { if (E->needsCopy()) continue; if (Target->relocNeedsCopy(Type, *Body)) E->OffsetInBSS = 0; } NeedsPlt = Target->relocNeedsPlt(Type, *Body); if (NeedsPlt) { if (Body->isInPlt()) continue; Out<ELFT>::Plt->addEntry(Body); } NeedsGot = Target->relocNeedsGot(Type, *Body); if (NeedsGot) { if (NeedsPlt && Target->supportsLazyRelocations()) { Out<ELFT>::GotPlt->addEntry(Body); } else { if (Body->isInGot()) continue; Out<ELFT>::Got->addEntry(Body); } } } if (Config->EMachine == EM_MIPS && NeedsGot) { // MIPS ABI has special rules to process GOT entries // and doesn't require relocation entries for them. // See "Global Offset Table" in Chapter 5 in the following document // for detailed description: // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf Body->setUsedInDynamicReloc(); continue; } bool CBP = canBePreempted(Body, NeedsGot); if (!CBP && (!Config->Shared || Target->isRelRelative(Type))) continue; if (CBP) Body->setUsedInDynamicReloc(); if (NeedsPlt && Target->supportsLazyRelocations()) Out<ELFT>::RelaPlt->addReloc({&C, &RI}); else Out<ELFT>::RelaDyn->addReloc({&C, &RI}); } }
std::string lld::verboseToString(Symbol *B, uint64_t SymOffset) { std::string Msg; if (B->isLocal()) Msg += "local "; if (B->isWeak()) Msg += "weak "; if (B->isShared()) Msg += "shared "; // else if (B->isDefined()) // Msg += "defined "; if (B->Type == STT_COMMON) Msg += "common "; else if (B->Type == STT_TLS) Msg += "TLS "; if (B->isSection()) Msg += "section "; else if (B->isTls()) Msg += "tls "; else if (B->isFunc()) Msg += "function "; else if (B->isGnuIFunc()) Msg += "gnu ifunc "; else if (B->isObject()) Msg += "object "; else if (B->isFile()) Msg += "file "; else if (B->isUndefined()) Msg += "<undefined> "; else Msg += "<unknown kind> "; if (B->isInGot()) Msg += "(in GOT) "; if (B->isInPlt()) Msg += "(in PLT) "; Defined* DR = dyn_cast<Defined>(B); InputSectionBase* IS = nullptr; if (DR && DR->Section) { SymOffset = DR->isSection() ? SymOffset : DR->Section->getOffset(DR->Value); IS = dyn_cast<InputSectionBase>(DR->Section); } std::string Name = toString(*B); if (Name.empty()) { if (DR && DR->Section) { if (IS) { Name = IS->getLocation<ELFT>(SymOffset); } else { Name = (DR->Section->Name + "+0x" + utohexstr(SymOffset)).str(); } } else if (OutputSection* OS = B->getOutputSection()) { Name = (OS->Name + "+(unknown offset)").str(); } } if (Name.empty()) { Name = "<unknown symbol>"; } Msg += Name; if (!B->isUndefined()) { std::string Src = IS ? IS->getSrcMsg(*B, SymOffset) : toString(B->File); if (IS) Src += " (" + IS->getObjMsg(SymOffset) + ")"; Msg += "\n>>> defined in " + Src; } return Msg; }
static typename ELFT::uint getSymVA(const SymbolBody &Body, typename ELFT::uint &Addend) { typedef typename ELFT::uint uintX_t; switch (Body.kind()) { case SymbolBody::DefinedSyntheticKind: { auto &D = cast<DefinedSynthetic>(Body); const OutputSectionBase *Sec = D.Section; if (!Sec) return D.Value; if (D.Value == uintX_t(-1)) return Sec->Addr + Sec->Size; return Sec->Addr + D.Value; } case SymbolBody::DefinedRegularKind: { auto &D = cast<DefinedRegular<ELFT>>(Body); InputSectionBase<ELFT> *IS = D.Section; // According to the ELF spec reference to a local symbol from outside // the group are not allowed. Unfortunately .eh_frame breaks that rule // and must be treated specially. For now we just replace the symbol with // 0. if (IS == &InputSection<ELFT>::Discarded) return 0; // This is an absolute symbol. if (!IS) return D.Value; uintX_t Offset = D.Value; if (D.isSection()) { Offset += Addend; Addend = 0; } uintX_t VA = (IS->OutSec ? IS->OutSec->Addr : 0) + IS->getOffset(Offset); if (D.isTls() && !Config->Relocatable) { if (!Out<ELFT>::TlsPhdr) fatal(toString(D.File) + " has a STT_TLS symbol but doesn't have a PT_TLS section"); return VA - Out<ELFT>::TlsPhdr->p_vaddr; } return VA; } case SymbolBody::DefinedCommonKind: if (!Config->DefineCommon) return 0; return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff + cast<DefinedCommon>(Body).Offset; case SymbolBody::SharedKind: { auto &SS = cast<SharedSymbol<ELFT>>(Body); if (!SS.NeedsCopyOrPltAddr) return 0; if (SS.isFunc()) return Body.getPltVA<ELFT>(); return SS.getBssSectionForCopy()->Addr + SS.CopyOffset; } case SymbolBody::UndefinedKind: return 0; case SymbolBody::LazyArchiveKind: case SymbolBody::LazyObjectKind: assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer"); return 0; } llvm_unreachable("invalid symbol kind"); }