forked from OSchip/llvm-project
Pass symbol attributes instead of ElfSym to Shared symbol ctor.
This change allows us to use less templates for Shared symbol and the functions that deals with shared symbols. llvm-svn: 316841
This commit is contained in:
parent
40f0584f08
commit
7f9694a42d
|
@ -514,11 +514,9 @@ template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
|
|||
}
|
||||
|
||||
template <class ELFT>
|
||||
InputSectionBase *ObjFile<ELFT>::getSection(const Elf_Sym &Sym) const {
|
||||
uint32_t Index = this->getSectionIndex(Sym);
|
||||
InputSectionBase *ObjFile<ELFT>::getSection(uint32_t Index) const {
|
||||
if (Index == 0)
|
||||
return nullptr;
|
||||
|
||||
if (Index >= this->Sections.size())
|
||||
fatal(toString(this) + ": invalid section index: " + Twine(Index));
|
||||
|
||||
|
@ -533,7 +531,7 @@ InputSectionBase *ObjFile<ELFT>::getSection(const Elf_Sym &Sym) const {
|
|||
template <class ELFT>
|
||||
SymbolBody *ObjFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
|
||||
int Binding = Sym->getBinding();
|
||||
InputSectionBase *Sec = getSection(*Sym);
|
||||
InputSectionBase *Sec = getSection(this->getSectionIndex(*Sym));
|
||||
|
||||
uint8_t StOther = Sym->st_other;
|
||||
uint8_t Type = Sym->getType();
|
||||
|
@ -629,14 +627,6 @@ SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName)
|
|||
: ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName),
|
||||
AsNeeded(Config->AsNeeded) {}
|
||||
|
||||
template <class ELFT>
|
||||
const typename ELFT::Shdr *
|
||||
SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const {
|
||||
return check(
|
||||
this->getObj().getSection(&Sym, this->ELFSyms, this->SymtabSHNDX),
|
||||
toString(this));
|
||||
}
|
||||
|
||||
// Partially parse the shared object file so that we can call
|
||||
// getSoName on this object.
|
||||
template <class ELFT> void SharedFile<ELFT>::parseSoName() {
|
||||
|
@ -735,6 +725,10 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
|
|||
const Elf_Versym *Versym = nullptr;
|
||||
std::vector<const Elf_Verdef *> Verdefs = parseVerdefs(Versym);
|
||||
|
||||
ArrayRef<Elf_Shdr> Sections =
|
||||
check(this->getObj().sections(), toString(this));
|
||||
|
||||
// Add symbols to the symbol table.
|
||||
Elf_Sym_Range Syms = this->getGlobalELFSyms();
|
||||
for (const Elf_Sym &Sym : Syms) {
|
||||
unsigned VersymIndex = 0;
|
||||
|
@ -765,15 +759,25 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() {
|
|||
V = Verdefs[VersymIndex];
|
||||
}
|
||||
|
||||
// We do not usually care about alignments of data in shared object
|
||||
// files because the loader takes care of it. However, if we promote a
|
||||
// DSO symbol to point to .bss due to copy relocation, we need to keep
|
||||
// the original alignment requirements. We infer it here.
|
||||
uint32_t Alignment = 1 << countTrailingZeros((uint64_t)Sym.st_value);
|
||||
if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size()) {
|
||||
uint32_t SecAlign = Sections[Sym.st_shndx].sh_addralign;
|
||||
Alignment = std::min(Alignment, SecAlign);
|
||||
}
|
||||
|
||||
if (!Hidden)
|
||||
Symtab->addShared(Name, this, Sym, V);
|
||||
Symtab->addShared(Name, this, Sym, Alignment, V);
|
||||
|
||||
// Also add the symbol with the versioned name to handle undefined symbols
|
||||
// with explicit versions.
|
||||
if (V) {
|
||||
StringRef VerName = this->StringTable.data() + V->getAux()->vda_name;
|
||||
Name = Saver.save(Name + "@" + VerName);
|
||||
Symtab->addShared(Name, this, Sym, V);
|
||||
Symtab->addShared(Name, this, Sym, Alignment, V);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,7 +167,7 @@ public:
|
|||
ObjFile(MemoryBufferRef M, StringRef ArchiveName);
|
||||
void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
|
||||
|
||||
InputSectionBase *getSection(const Elf_Sym &Sym) const;
|
||||
InputSectionBase *getSection(uint32_t Index) const;
|
||||
|
||||
SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
|
||||
if (SymbolIndex >= this->Symbols.size())
|
||||
|
@ -294,7 +294,6 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {
|
|||
public:
|
||||
std::string SoName;
|
||||
|
||||
const Elf_Shdr *getSection(const Elf_Sym &Sym) const;
|
||||
llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; }
|
||||
|
||||
static bool classof(const InputFile *F) {
|
||||
|
|
|
@ -49,7 +49,7 @@ static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,
|
|||
static std::string indent(int Depth) { return std::string(Depth * 8, ' '); }
|
||||
|
||||
// Returns a list of all symbols that we want to print out.
|
||||
template <class ELFT> static std::vector<Defined *> getSymbols() {
|
||||
static std::vector<Defined *> getSymbols() {
|
||||
std::vector<Defined *> V;
|
||||
for (InputFile *File : ObjectFiles) {
|
||||
for (SymbolBody *B : File->getSymbols()) {
|
||||
|
@ -90,13 +90,12 @@ static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
|
|||
// Construct a map from symbols to their stringified representations.
|
||||
// Demangling symbols (which is what toString() does) is slow, so
|
||||
// we do that in batch using parallel-for.
|
||||
template <class ELFT>
|
||||
static DenseMap<Defined *, std::string>
|
||||
getSymbolStrings(ArrayRef<Defined *> Syms) {
|
||||
std::vector<std::string> Str(Syms.size());
|
||||
parallelForEachN(0, Syms.size(), [&](size_t I) {
|
||||
raw_string_ostream OS(Str[I]);
|
||||
writeHeader(OS, Syms[I]->getVA(), Syms[I]->template getSize<ELFT>(), 0);
|
||||
writeHeader(OS, Syms[I]->getVA(), Syms[I]->getSize(), 0);
|
||||
OS << indent(2) << toString(*Syms[I]);
|
||||
});
|
||||
|
||||
|
@ -106,7 +105,7 @@ getSymbolStrings(ArrayRef<Defined *> Syms) {
|
|||
return Ret;
|
||||
}
|
||||
|
||||
template <class ELFT> void elf::writeMapFile() {
|
||||
void elf::writeMapFile() {
|
||||
if (Config->MapFile.empty())
|
||||
return;
|
||||
|
||||
|
@ -119,12 +118,12 @@ template <class ELFT> void elf::writeMapFile() {
|
|||
}
|
||||
|
||||
// Collect symbol info that we want to print out.
|
||||
std::vector<Defined *> Syms = getSymbols<ELFT>();
|
||||
std::vector<Defined *> Syms = getSymbols();
|
||||
SymbolMapTy SectionSyms = getSectionSyms(Syms);
|
||||
DenseMap<Defined *, std::string> SymStr = getSymbolStrings<ELFT>(Syms);
|
||||
DenseMap<Defined *, std::string> SymStr = getSymbolStrings(Syms);
|
||||
|
||||
// Print out the header line.
|
||||
int W = ELFT::Is64Bits ? 16 : 8;
|
||||
int W = Config->Is64 ? 16 : 8;
|
||||
OS << left_justify("Address", W) << ' ' << left_justify("Size", W)
|
||||
<< " Align Out In Symbol\n";
|
||||
|
||||
|
@ -148,8 +147,3 @@ template <class ELFT> void elf::writeMapFile() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
template void elf::writeMapFile<ELF32LE>();
|
||||
template void elf::writeMapFile<ELF32BE>();
|
||||
template void elf::writeMapFile<ELF64LE>();
|
||||
template void elf::writeMapFile<ELF64BE>();
|
||||
|
|
|
@ -10,12 +10,9 @@
|
|||
#ifndef LLD_ELF_MAPFILE_H
|
||||
#define LLD_ELF_MAPFILE_H
|
||||
|
||||
#include <llvm/ADT/ArrayRef.h>
|
||||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
class OutputSection;
|
||||
template <class ELFT> void writeMapFile();
|
||||
void writeMapFile();
|
||||
} // namespace elf
|
||||
} // namespace lld
|
||||
|
||||
|
|
|
@ -445,14 +445,13 @@ static RelExpr fromPlt(RelExpr Expr) {
|
|||
// Returns true if a given shared symbol is in a read-only segment in a DSO.
|
||||
template <class ELFT> static bool isReadOnly(SharedSymbol *SS) {
|
||||
typedef typename ELFT::Phdr Elf_Phdr;
|
||||
uint64_t Value = SS->getValue<ELFT>();
|
||||
|
||||
// Determine if the symbol is read-only by scanning the DSO's program headers.
|
||||
const SharedFile<ELFT> *File = SS->getFile<ELFT>();
|
||||
for (const Elf_Phdr &Phdr : check(File->getObj().program_headers()))
|
||||
if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) &&
|
||||
!(Phdr.p_flags & ELF::PF_W) && Value >= Phdr.p_vaddr &&
|
||||
Value < Phdr.p_vaddr + Phdr.p_memsz)
|
||||
!(Phdr.p_flags & ELF::PF_W) && SS->Value >= Phdr.p_vaddr &&
|
||||
SS->Value < Phdr.p_vaddr + Phdr.p_memsz)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -467,12 +466,10 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) {
|
|||
typedef typename ELFT::Sym Elf_Sym;
|
||||
|
||||
SharedFile<ELFT> *File = SS->getFile<ELFT>();
|
||||
uint64_t Shndx = SS->getShndx<ELFT>();
|
||||
uint64_t Value = SS->getValue<ELFT>();
|
||||
|
||||
std::vector<SharedSymbol *> Ret;
|
||||
for (const Elf_Sym &S : File->getGlobalELFSyms()) {
|
||||
if (S.st_shndx != Shndx || S.st_value != Value)
|
||||
if (S.st_shndx != SS->Shndx || S.st_value != SS->Value)
|
||||
continue;
|
||||
StringRef Name = check(S.getName(File->getStringTable()));
|
||||
SymbolBody *Sym = Symtab->find(Name);
|
||||
|
@ -526,7 +523,7 @@ static std::vector<SharedSymbol *> getSymbolsAt(SharedSymbol *SS) {
|
|||
// define an accessor getV().
|
||||
template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
|
||||
// Copy relocation against zero-sized symbol doesn't make sense.
|
||||
uint64_t SymSize = SS->template getSize<ELFT>();
|
||||
uint64_t SymSize = SS->getSize();
|
||||
if (SymSize == 0)
|
||||
fatal("cannot create a copy relocation for symbol " + toString(*SS));
|
||||
|
||||
|
@ -534,7 +531,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol *SS) {
|
|||
// memory protection by reserving space in the .bss.rel.ro section.
|
||||
bool IsReadOnly = isReadOnly<ELFT>(SS);
|
||||
BssSection *Sec = make<BssSection>(IsReadOnly ? ".bss.rel.ro" : ".bss",
|
||||
SymSize, SS->getAlignment<ELFT>());
|
||||
SymSize, SS->Alignment);
|
||||
if (IsReadOnly)
|
||||
InX::BssRelRo->getParent()->addSection(Sec);
|
||||
else
|
||||
|
@ -1014,7 +1011,7 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {
|
|||
|
||||
// The size is not going to change, so we fold it in here.
|
||||
if (Expr == R_SIZE)
|
||||
Addend += Body.getSize<ELFT>();
|
||||
Addend += Body.getSize();
|
||||
|
||||
// If the produced value is a constant, we just remember to write it
|
||||
// when outputting this section. We also have to do it if the format
|
||||
|
|
|
@ -498,7 +498,7 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type,
|
|||
|
||||
template <typename ELFT>
|
||||
void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
|
||||
const typename ELFT::Sym &Sym,
|
||||
const typename ELFT::Sym &Sym, uint32_t Alignment,
|
||||
const typename ELFT::Verdef *Verdef) {
|
||||
// DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
|
||||
// as the visibility, which will leave the visibility in the symbol table
|
||||
|
@ -516,8 +516,9 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> *File,
|
|||
// in the same DSO.
|
||||
if (WasInserted || ((Body->isUndefined() || Body->isLazy()) &&
|
||||
Body->getVisibility() == STV_DEFAULT)) {
|
||||
replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(), &Sym,
|
||||
Verdef);
|
||||
replaceBody<SharedSymbol>(S, File, Name, Sym.st_other, Sym.getType(),
|
||||
Sym.st_value, Sym.st_size, Alignment,
|
||||
Sym.st_shndx, Verdef);
|
||||
if (!S->isWeak())
|
||||
File->IsUsed = true;
|
||||
}
|
||||
|
@ -881,15 +882,19 @@ template void SymbolTable::addLazyObject<ELF64BE>(StringRef, LazyObjFile &);
|
|||
|
||||
template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> *,
|
||||
const typename ELF32LE::Sym &,
|
||||
uint32_t Alignment,
|
||||
const typename ELF32LE::Verdef *);
|
||||
template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> *,
|
||||
const typename ELF32BE::Sym &,
|
||||
uint32_t Alignment,
|
||||
const typename ELF32BE::Verdef *);
|
||||
template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> *,
|
||||
const typename ELF64LE::Sym &,
|
||||
uint32_t Alignment,
|
||||
const typename ELF64LE::Verdef *);
|
||||
template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> *,
|
||||
const typename ELF64BE::Sym &,
|
||||
uint32_t Alignment,
|
||||
const typename ELF64BE::Verdef *);
|
||||
|
||||
template void SymbolTable::fetchIfLazy<ELF32LE>(StringRef);
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
template <class ELFT>
|
||||
void addShared(StringRef Name, SharedFile<ELFT> *F,
|
||||
const typename ELFT::Sym &Sym,
|
||||
const typename ELFT::Sym &Sym, uint32_t Alignment,
|
||||
const typename ELFT::Verdef *Verdef);
|
||||
|
||||
template <class ELFT>
|
||||
|
|
|
@ -174,13 +174,13 @@ uint64_t SymbolBody::getPltVA() const {
|
|||
PltIndex * Target->PltEntrySize;
|
||||
}
|
||||
|
||||
template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
|
||||
uint64_t SymbolBody::getSize() const {
|
||||
if (const auto *C = dyn_cast<DefinedCommon>(this))
|
||||
return C->Size;
|
||||
if (const auto *DR = dyn_cast<DefinedRegular>(this))
|
||||
return DR->Size;
|
||||
if (const auto *S = dyn_cast<SharedSymbol>(this))
|
||||
return S->getSize<ELFT>();
|
||||
return S->Size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -261,17 +261,6 @@ template <class ELFT> bool DefinedRegular::isMipsPIC() const {
|
|||
(Hdr->e_flags & EF_MIPS_PIC);
|
||||
}
|
||||
|
||||
// If a shared symbol is referred via a copy relocation, its alignment
|
||||
// becomes part of the ABI. This function returns a symbol alignment.
|
||||
// Because symbols don't have alignment attributes, we need to infer that.
|
||||
template <class ELFT> uint32_t SharedSymbol::getAlignment() const {
|
||||
SharedFile<ELFT> *File = getFile<ELFT>();
|
||||
uint32_t SecAlign = File->getSection(getSym<ELFT>())->sh_addralign;
|
||||
uint64_t SymValue = getSym<ELFT>().st_value;
|
||||
uint32_t SymAlign = uint32_t(1) << countTrailingZeros(SymValue);
|
||||
return std::min(SecAlign, SymAlign);
|
||||
}
|
||||
|
||||
InputFile *Lazy::fetch() {
|
||||
if (auto *S = dyn_cast<LazyArchive>(this))
|
||||
return S->fetch();
|
||||
|
@ -346,17 +335,7 @@ std::string lld::toString(const SymbolBody &B) {
|
|||
return B.getName();
|
||||
}
|
||||
|
||||
template uint32_t SymbolBody::template getSize<ELF32LE>() const;
|
||||
template uint32_t SymbolBody::template getSize<ELF32BE>() const;
|
||||
template uint64_t SymbolBody::template getSize<ELF64LE>() const;
|
||||
template uint64_t SymbolBody::template getSize<ELF64BE>() const;
|
||||
|
||||
template bool DefinedRegular::template isMipsPIC<ELF32LE>() const;
|
||||
template bool DefinedRegular::template isMipsPIC<ELF32BE>() const;
|
||||
template bool DefinedRegular::template isMipsPIC<ELF64LE>() const;
|
||||
template bool DefinedRegular::template isMipsPIC<ELF64BE>() const;
|
||||
|
||||
template uint32_t SharedSymbol::template getAlignment<ELF32LE>() const;
|
||||
template uint32_t SharedSymbol::template getAlignment<ELF32BE>() const;
|
||||
template uint32_t SharedSymbol::template getAlignment<ELF64LE>() const;
|
||||
template uint32_t SharedSymbol::template getAlignment<ELF64BE>() const;
|
||||
|
|
|
@ -93,7 +93,7 @@ public:
|
|||
uint64_t getGotPltOffset() const;
|
||||
uint64_t getGotPltVA() const;
|
||||
uint64_t getPltVA() const;
|
||||
template <class ELFT> typename ELFT::uint getSize() const;
|
||||
uint64_t getSize() const;
|
||||
OutputSection *getOutputSection() const;
|
||||
|
||||
uint32_t DynsymIndex = 0;
|
||||
|
@ -218,10 +218,12 @@ class SharedSymbol : public Defined {
|
|||
public:
|
||||
static bool classof(const SymbolBody *S) { return S->kind() == SharedKind; }
|
||||
|
||||
SharedSymbol(StringRef Name, uint8_t StOther, uint8_t Type,
|
||||
const void *ElfSym, const void *Verdef)
|
||||
SharedSymbol(StringRef Name, uint8_t StOther, uint8_t Type, uint64_t Value,
|
||||
uint64_t Size, uint32_t Alignment, uint64_t Shndx,
|
||||
const void *Verdef)
|
||||
: Defined(SharedKind, Name, /*IsLocal=*/false, StOther, Type),
|
||||
Verdef(Verdef), ElfSym(ElfSym) {
|
||||
Verdef(Verdef), Value(Value), Size(Size), Shndx(Shndx),
|
||||
Alignment(Alignment) {
|
||||
// GNU ifunc is a mechanism to allow user-supplied functions to
|
||||
// resolve PLT slot values at load-time. This is contrary to the
|
||||
// regualr symbol resolution scheme in which symbols are resolved just
|
||||
|
@ -246,18 +248,6 @@ public:
|
|||
return cast<SharedFile<ELFT>>(SymbolBody::getFile());
|
||||
}
|
||||
|
||||
template <class ELFT> uint64_t getShndx() const {
|
||||
return getSym<ELFT>().st_shndx;
|
||||
}
|
||||
|
||||
template <class ELFT> uint64_t getValue() const {
|
||||
return getSym<ELFT>().st_value;
|
||||
}
|
||||
|
||||
template <class ELFT> uint64_t getSize() const {
|
||||
return getSym<ELFT>().st_size;
|
||||
}
|
||||
|
||||
template <class ELFT> uint32_t getAlignment() const;
|
||||
|
||||
// This field is a pointer to the symbol's version definition.
|
||||
|
@ -266,12 +256,10 @@ public:
|
|||
// If not null, there is a copy relocation to this section.
|
||||
InputSection *CopyRelSec = nullptr;
|
||||
|
||||
private:
|
||||
template <class ELFT> const typename ELFT::Sym &getSym() const {
|
||||
return *(const typename ELFT::Sym *)ElfSym;
|
||||
}
|
||||
|
||||
const void *ElfSym;
|
||||
uint64_t Value; // st_value
|
||||
uint64_t Size; // st_size
|
||||
uint64_t Shndx; // st_shndx
|
||||
uint32_t Alignment;
|
||||
};
|
||||
|
||||
// This represents a symbol that is not yet in the link, but we know where to
|
||||
|
|
|
@ -82,7 +82,7 @@ template <class ELFT> void elf::createCommonSections() {
|
|||
// don't have to care about DefinedCommon symbols beyond this point.
|
||||
replaceBody<DefinedRegular>(S, Sym->getFile(), Sym->getName(),
|
||||
static_cast<bool>(Sym->isLocal()), Sym->StOther,
|
||||
Sym->Type, 0, Sym->getSize<ELFT>(), Section);
|
||||
Sym->Type, 0, Sym->getSize(), Section);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1615,7 +1615,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
|
|||
if (ESym->st_shndx == SHN_UNDEF)
|
||||
ESym->st_size = 0;
|
||||
else
|
||||
ESym->st_size = Body->getSize<ELFT>();
|
||||
ESym->st_size = Body->getSize();
|
||||
|
||||
// st_value is usually an address of a symbol, but that has a
|
||||
// special meaining for uninstantiated common symbols (this can
|
||||
|
|
|
@ -248,7 +248,7 @@ template <class ELFT> void Writer<ELFT>::run() {
|
|||
return;
|
||||
|
||||
// Handle -Map option.
|
||||
writeMapFile<ELFT>();
|
||||
writeMapFile();
|
||||
if (errorCount())
|
||||
return;
|
||||
|
||||
|
|
Loading…
Reference in New Issue