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"); }
// Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. // Used to implement --wrap. template <class ELFT> void SymbolTable<ELFT>::wrap(StringRef Name) { SymbolBody *B = find(Name); if (!B) return; StringSaver Saver(Alloc); Symbol *Sym = B->symbol(); Symbol *Real = addUndefined(Saver.save("__real_" + Name)); Symbol *Wrap = addUndefined(Saver.save("__wrap_" + Name)); // We rename symbols by replacing the old symbol's SymbolBody with the new // symbol's SymbolBody. This causes all SymbolBody pointers referring to the // old symbol to instead refer to the new symbol. memcpy(Real->Body.buffer, Sym->Body.buffer, sizeof(Sym->Body)); memcpy(Sym->Body.buffer, Wrap->Body.buffer, sizeof(Wrap->Body)); }
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"); }