Implement --export-dynamic.

llvm-svn: 248347
This commit is contained in:
Rafael Espindola 2015-09-22 23:38:23 +00:00
parent be61720c4e
commit 05a3dd2cba
8 changed files with 73 additions and 23 deletions

View File

@ -22,6 +22,7 @@ struct Configuration {
bool Shared = false;
bool DiscardAll = false;
bool DiscardLocals = false;
bool ExportDynamic = false;
};
extern Configuration *Config;

View File

@ -88,6 +88,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
if (Args.hasArg(OPT_discard_locals))
Config->DiscardLocals = true;
if (Args.hasArg(OPT_export_dynamic))
Config->ExportDynamic = true;
// Create a list of input files.
std::vector<MemoryBufferRef> Inputs;

View File

@ -27,3 +27,6 @@ def discard_locals : Flag<["-"], "discard-locals">,
def alias_discard_locals: Flag<["-"], "X">,
Alias<discard_locals>;
def export_dynamic : Flag<["--"], "export-dynamic">,
HelpText<"Put symbols in the dynamic symbol table">;

View File

@ -272,6 +272,12 @@ bool lld::elf2::includeInSymtab(const SymbolBody &B) {
return true;
}
bool lld::elf2::includeInDynamicSymtab(const SymbolBody &B) {
if (Config->ExportDynamic || Config->Shared)
return true;
return B.isUsedInDynamicReloc();
}
template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
const OutputSection<ELFT> *Out = nullptr;
const InputSection<ELFT> *Section = nullptr;
@ -315,8 +321,10 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
SymbolBody *Body = Sym->Body;
if (!includeInSymtab(*Body))
continue;
const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
if (StrTabSec.isDynamic() && !includeInDynamicSymtab(*Body))
continue;
const Elf_Sym &InputSym = cast<ELFSymbolBody<ELFT>>(Body)->Sym;
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
ESym->st_name = StrTabSec.getFileOff(Name);

View File

@ -39,6 +39,7 @@ getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
const ObjectFile<ELFT> &File);
bool includeInSymtab(const SymbolBody &B);
bool includeInDynamicSymtab(const SymbolBody &B);
// This represents a section in an output file.
// Different sub classes represent different types of sections. Some contain

View File

@ -57,6 +57,8 @@ public:
bool isLazy() const { return SymbolKind == LazyKind; }
bool isShared() const { return SymbolKind == SharedKind; }
bool isUsedInRegularObj() const { return IsUsedInRegularObj; }
bool isUsedInDynamicReloc() const { return IsUsedInDynamicReloc; }
void setUsedInDynamicReloc() { IsUsedInDynamicReloc = true; }
// Returns the symbol name.
StringRef getName() const { return Name; }
@ -97,12 +99,14 @@ protected:
: SymbolKind(K), IsWeak(IsWeak), MostConstrainingVisibility(Visibility),
Name(Name) {
IsUsedInRegularObj = K != SharedKind && K != LazyKind;
IsUsedInDynamicReloc = 0;
}
const unsigned SymbolKind : 8;
const unsigned IsWeak : 1;
unsigned MostConstrainingVisibility : 2;
unsigned IsUsedInRegularObj : 1;
unsigned IsUsedInDynamicReloc : 1;
unsigned DynamicSymbolTableIndex = 0;
unsigned GotIndex = -1;
unsigned PltIndex = -1;

View File

@ -267,6 +267,7 @@ void Writer<ELFT>::scanRelocs(
continue;
GotSec.addEntry(Body);
}
S->setUsedInDynamicReloc();
RelaDynSec.addReloc({C, RI});
}
}
@ -302,28 +303,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
return Sec;
};
// FIXME: Try to avoid the extra walk over all global symbols.
const SymbolTable &Symtab = SymTabSec.getSymTable();
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
for (auto &P : Symtab.getSymbols()) {
StringRef Name = P.first;
SymbolBody *Body = P.second->Body;
if (Body->isStrongUndefined())
error(Twine("undefined symbol: ") + Name);
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
if (!includeInSymtab(*Body))
continue;
SymTabSec.addSymbol(Name);
// FIXME: This adds way too much to the dynamic symbol table. We only
// need to add the symbols use by dynamic relocations when producing
// an executable (ignoring --export-dynamic).
if (needsDynamicSections())
HashSec.addSymbol(Body);
}
for (const std::unique_ptr<ObjectFileBase> &FileB : Symtab.getObjectFiles()) {
auto &File = cast<ObjectFile<ELFT>>(*FileB);
if (!Config->DiscardAll) {
@ -345,6 +325,24 @@ template <class ELFT> void Writer<ELFT>::createSections() {
}
}
// FIXME: Try to avoid the extra walk over all global symbols.
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
for (auto &P : Symtab.getSymbols()) {
StringRef Name = P.first;
SymbolBody *Body = P.second->Body;
if (Body->isStrongUndefined())
error(Twine("undefined symbol: ") + Name);
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
if (!includeInSymtab(*Body))
continue;
SymTabSec.addSymbol(Name);
if (needsDynamicSections() && includeInDynamicSymtab(*Body))
HashSec.addSymbol(Body);
}
BSSSec = getSection(".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
SymTabSec.setBssSec(BSSSec);
DynSymSec.setBssSec(BSSSec);

View File

@ -2,8 +2,10 @@
// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
// RUN: lld -flavor gnu2 -shared %t2.o -o %t2.so
// RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s
// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar %t.o %t2.so -o %t
// RUN: lld -flavor gnu2 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s
// RUN: lld -flavor gnu2 %t.o %t2.so -o %t2
// RUN: llvm-readobj -dyn-symbols %t2 | FileCheck --check-prefix=DONT_EXPORT %s
// REQUIRES: x86
// Make sure .symtab is properly aligned.
@ -195,6 +197,36 @@
// CHECK-NEXT: }
// CHECK-NEXT: ]
// DONT_EXPORT: DynamicSymbols [
// DONT_EXPORT-NEXT: Symbol {
// DONT_EXPORT-NEXT: Name: @ (0)
// DONT_EXPORT-NEXT: Value: 0x0
// DONT_EXPORT-NEXT: Size: 0
// DONT_EXPORT-NEXT: Binding: Local (0x0)
// DONT_EXPORT-NEXT: Type: None (0x0)
// DONT_EXPORT-NEXT: Other: 0
// DONT_EXPORT-NEXT: Section: Undefined (0x0)
// DONT_EXPORT-NEXT: }
// DONT_EXPORT-NEXT: Symbol {
// DONT_EXPORT-NEXT: Name: bar@
// DONT_EXPORT-NEXT: Value: 0x0
// DONT_EXPORT-NEXT: Size: 0
// DONT_EXPORT-NEXT: Binding: Global
// DONT_EXPORT-NEXT: Type: Function
// DONT_EXPORT-NEXT: Other: 0
// DONT_EXPORT-NEXT: Section: Undefined
// DONT_EXPORT-NEXT: }
// DONT_EXPORT-NEXT: Symbol {
// DONT_EXPORT-NEXT: Name: zed@
// DONT_EXPORT-NEXT: Value: 0x0
// DONT_EXPORT-NEXT: Size: 0
// DONT_EXPORT-NEXT: Binding: Global
// DONT_EXPORT-NEXT: Type: None
// DONT_EXPORT-NEXT: Other: 0
// DONT_EXPORT-NEXT: Section: Undefinedx
// DONT_EXPORT-NEXT: }
// DONT_EXPORT-NEXT: ]
// CHECK: DynamicSection [
// CHECK-NEXT: Tag Type Name/Value
// CHECK-NEXT: 0x00000011 REL [[RELADDR]]