[lld] r247019 - Start adding support for symbols in shared libraries.
Rafael Espindola via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 8 08:50:05 PDT 2015
Author: rafael
Date: Tue Sep 8 10:50:05 2015
New Revision: 247019
URL: http://llvm.org/viewvc/llvm-project?rev=247019&view=rev
Log:
Start adding support for symbols in shared libraries.
Added:
lld/trunk/test/elf2/shared.s
Modified:
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/elf2/Inputs/i686-simple-library.so
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Tue Sep 8 10:50:05 2015
@@ -54,6 +54,24 @@ template <class ELFT> void ELFData<ELFT>
error(EC);
}
+template <class ELFT>
+typename ELFData<ELFT>::Elf_Sym_Range ELFData<ELFT>::getNonLocalSymbols() {
+ if (!Symtab)
+ return Elf_Sym_Range(nullptr, nullptr);
+
+ ErrorOr<StringRef> StringTableOrErr =
+ ELFObj->getStringTableForSymtab(*Symtab);
+ error(StringTableOrErr.getError());
+ StringTable = *StringTableOrErr;
+
+ Elf_Sym_Range Syms = ELFObj->symbols(Symtab);
+ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+ uint32_t FirstNonLocal = Symtab->sh_info;
+ if (FirstNonLocal > NumSymbols)
+ error("Invalid sh_info in symbol table");
+ return llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
+}
+
template <class ELFT> void elf2::ObjectFile<ELFT>::parse() {
this->openELF(MB);
@@ -69,7 +87,7 @@ template <class ELFT> void elf2::ObjectF
for (const Elf_Shdr &Sec : this->ELFObj->sections()) {
switch (Sec.sh_type) {
case SHT_SYMTAB:
- Symtab = &Sec;
+ this->Symtab = &Sec;
break;
case SHT_SYMTAB_SHNDX: {
ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable =
@@ -101,20 +119,11 @@ template <class ELFT> void elf2::ObjectF
}
template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
- ErrorOr<StringRef> StringTableOrErr =
- this->ELFObj->getStringTableForSymtab(*Symtab);
- error(StringTableOrErr.getError());
- StringRef StringTable = *StringTableOrErr;
-
- Elf_Sym_Range Syms = this->ELFObj->symbols(Symtab);
+ Elf_Sym_Range Syms = this->getNonLocalSymbols();
uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
- uint32_t FirstNonLocal = Symtab->sh_info;
- if (FirstNonLocal > NumSymbols)
- error("Invalid sh_info in symbol table");
- Syms = llvm::make_range(Syms.begin() + FirstNonLocal, Syms.end());
- SymbolBodies.reserve(NumSymbols - FirstNonLocal);
+ SymbolBodies.reserve(NumSymbols);
for (const Elf_Sym &Sym : Syms)
- SymbolBodies.push_back(createSymbolBody(StringTable, &Sym));
+ SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
}
template <class ELFT>
@@ -133,8 +142,8 @@ SymbolBody *elf2::ObjectFile<ELFT>::crea
case SHN_COMMON:
return new (Alloc) DefinedCommon<ELFT>(Name, *Sym);
case SHN_XINDEX:
- SecIndex =
- this->ELFObj->getExtendedSymbolTableIndex(Sym, Symtab, SymtabSHNDX);
+ SecIndex = this->ELFObj->getExtendedSymbolTableIndex(Sym, this->Symtab,
+ SymtabSHNDX);
break;
}
@@ -181,7 +190,30 @@ MemoryBufferRef ArchiveFile::getMember(c
return *Ret;
}
-template <class ELFT> void SharedFile<ELFT>::parse() { this->openELF(MB); }
+template <class ELFT> void SharedFile<ELFT>::parse() {
+ this->openELF(MB);
+
+ for (const Elf_Shdr &Sec : this->ELFObj->sections()) {
+ if (Sec.sh_type == SHT_DYNSYM) {
+ this->Symtab = &Sec;
+ break;
+ }
+ }
+
+ Elf_Sym_Range Syms = this->getNonLocalSymbols();
+ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+ SymbolBodies.reserve(NumSymbols);
+ for (const Elf_Sym &Sym : Syms) {
+ if (Sym.isUndefined())
+ continue;
+
+ ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
+ error(NameOrErr.getError());
+ StringRef Name = *NameOrErr;
+
+ SymbolBodies.emplace_back(Name, Sym);
+ }
+}
namespace lld {
namespace elf2 {
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Tue Sep 8 10:50:05 2015
@@ -95,12 +95,18 @@ template <class ELFT> static ELFKind get
template <class ELFT> class ELFData {
public:
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
llvm::object::ELFFile<ELFT> *getObj() const { return ELFObj.get(); }
uint16_t getEMachine() const { return getObj()->getHeader()->e_machine; }
protected:
std::unique_ptr<llvm::object::ELFFile<ELFT>> ELFObj;
+ const Elf_Shdr *Symtab = nullptr;
+ StringRef StringTable;
+ Elf_Sym_Range getNonLocalSymbols();
void openELF(MemoryBufferRef MB);
};
@@ -126,7 +132,7 @@ public:
ArrayRef<SectionChunk<ELFT> *> getChunks() { return Chunks; }
SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
- uint32_t FirstNonLocal = Symtab->sh_info;
+ uint32_t FirstNonLocal = this->Symtab->sh_info;
if (SymbolIndex < FirstNonLocal)
return nullptr;
return SymbolBodies[SymbolIndex - FirstNonLocal]->getReplacement();
@@ -141,7 +147,6 @@ private:
// List of all chunks defined by this file.
std::vector<SectionChunk<ELFT> *> Chunks;
- const Elf_Shdr *Symtab = nullptr;
ArrayRef<Elf_Word> SymtabSHNDX;
};
@@ -174,7 +179,17 @@ public:
template <class ELFT>
class SharedFile : public SharedFileBase, public ELFData<ELFT> {
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range;
+
+ std::vector<SharedSymbol<ELFT>> SymbolBodies;
+
public:
+ llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() {
+ return SymbolBodies;
+ }
+
static bool classof(const InputFile *F) {
return F->kind() == SharedKind &&
cast<ELFFileBase>(F)->getELFKind() == getStaticELFKind<ELFT>();
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Tue Sep 8 10:50:05 2015
@@ -51,8 +51,11 @@ template <class ELFT> void SymbolTable::
resolve<ELFT>(Body);
}
- if (auto *S = dyn_cast<SharedFileBase>(File))
+ if (auto *S = dyn_cast<SharedFile<ELFT>>(File)) {
SharedFiles.emplace_back(S);
+ for (SharedSymbol<ELFT> &Body : S->getSharedSymbols())
+ resolve<ELFT>(&Body);
+ }
}
void SymbolTable::addELFFile(ELFFileBase *File) {
Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Tue Sep 8 10:50:05 2015
@@ -45,6 +45,9 @@ template <class ELFT> int SymbolBody::co
MostConstrainingVisibility = getMinVisibility(LV, RV);
Other->MostConstrainingVisibility = MostConstrainingVisibility;
+ IsUsedInRegularObj |= Other->IsUsedInRegularObj;
+ Other->IsUsedInRegularObj |= IsUsedInRegularObj;
+
if (L != R)
return -1;
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Tue Sep 8 10:50:05 2015
@@ -41,9 +41,10 @@ public:
DefinedRegularKind = 0,
DefinedAbsoluteKind = 1,
DefinedCommonKind = 2,
- DefinedLast = 2,
- UndefinedKind = 3,
- LazyKind = 4,
+ SharedKind = 3,
+ DefinedLast = 3,
+ UndefinedKind = 4,
+ LazyKind = 5,
};
Kind kind() const { return static_cast<Kind>(SymbolKind); }
@@ -54,6 +55,8 @@ public:
bool isStrongUndefined() const { return !IsWeak && isUndefined(); }
bool isCommon() const { return SymbolKind == DefinedCommonKind; }
bool isLazy() const { return SymbolKind == LazyKind; }
+ bool isShared() const { return SymbolKind == SharedKind; }
+ bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
// Returns the symbol name.
StringRef getName() const { return Name; }
@@ -79,12 +82,15 @@ public:
protected:
SymbolBody(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility)
: SymbolKind(K), IsWeak(IsWeak), MostConstrainingVisibility(Visibility),
- Name(Name) {}
+ Name(Name) {
+ IsUsedInRegularObj = K != SharedKind && K != LazyKind;
+ }
protected:
const unsigned SymbolKind : 8;
const unsigned IsWeak : 1;
unsigned MostConstrainingVisibility : 2;
+ unsigned IsUsedInRegularObj : 1;
StringRef Name;
Symbol *Backref = nullptr;
};
@@ -202,6 +208,19 @@ public:
template <class ELFT>
typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Synthetic;
+template <class ELFT> class SharedSymbol : public ELFSymbolBody<ELFT> {
+ typedef ELFSymbolBody<ELFT> Base;
+ typedef typename Base::Elf_Sym Elf_Sym;
+
+public:
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == Base::SharedKind;
+ }
+
+ SharedSymbol(StringRef Name, const Elf_Sym &Sym)
+ : ELFSymbolBody<ELFT>(Base::SharedKind, Name, Sym) {}
+};
+
// This class represents a symbol defined in an archive file. It is
// created from an archive file header, and it knows how to load an
// object file from an archive to replace itself with a defined
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Tue Sep 8 10:50:05 2015
@@ -297,6 +297,17 @@ static int compareSym(const typename ELF
return AN - BN;
}
+static bool includeInSymtab(const SymbolBody &B) {
+ if (B.isLazy())
+ return false;
+ if (!B.isUsedInRegularObj())
+ return false;
+ uint8_t V = B.getMostConstrainingVisibility();
+ if (V != STV_DEFAULT && V != STV_PROTECTED)
+ return false;
+ return true;
+}
+
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
uint8_t *BufStart = Buf;
@@ -305,14 +316,10 @@ template <class ELFT> void SymbolTableSe
StringRef Name = P.first;
Symbol *Sym = P.second;
SymbolBody *Body = Sym->Body;
- if (Body->isLazy())
+ if (!includeInSymtab(*Body))
continue;
const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
- uint8_t V = Body->getMostConstrainingVisibility();
- if (V != STV_DEFAULT && V != STV_PROTECTED)
- continue;
-
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
ESym->st_name = Builder.getOffset(Name);
@@ -330,6 +337,7 @@ template <class ELFT> void SymbolTableSe
if (!Body->isWeak())
error(Twine("undefined symbol: ") + Name);
case SymbolBody::DefinedAbsoluteKind:
+ case SymbolBody::SharedKind:
break;
case SymbolBody::LazyKind:
llvm_unreachable("Lazy symbol got to output symbol table!");
@@ -458,12 +466,9 @@ template <class ELFT> void Writer<ELFT>:
for (auto &P : Symtab.getSymbols()) {
StringRef Name = P.first;
SymbolBody *Body = P.second->Body;
- if (Body->isLazy())
- continue;
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
- uint8_t V = Body->getMostConstrainingVisibility();
- if (V != STV_DEFAULT && V != STV_PROTECTED)
+ if (!includeInSymtab(*Body))
continue;
NumVisible++;
Builder.add(Name);
Modified: lld/trunk/test/elf2/Inputs/i686-simple-library.so
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/i686-simple-library.so?rev=247019&r1=247018&r2=247019&view=diff
==============================================================================
Binary files lld/trunk/test/elf2/Inputs/i686-simple-library.so (original) and lld/trunk/test/elf2/Inputs/i686-simple-library.so Tue Sep 8 10:50:05 2015 differ
Added: lld/trunk/test/elf2/shared.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/shared.s?rev=247019&view=auto
==============================================================================
--- lld/trunk/test/elf2/shared.s (added)
+++ lld/trunk/test/elf2/shared.s Tue Sep 8 10:50:05 2015
@@ -0,0 +1,38 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: lld -flavor gnu2 %t.o %p/Inputs/i686-simple-library.so -o %t
+// RUN: llvm-readobj -t %t | FileCheck %s
+// REQUIRES: x86
+
+// CHECK: Symbols [
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name:
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: bar
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Function
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+.long bar
More information about the llvm-commits
mailing list