[ELF2] Add support for -discard-none.

Differential Revision:	http://reviews.llvm.org/D13083

llvm-svn: 248499
This commit is contained in:
Davide Italiano 2015-09-24 15:08:23 +00:00
parent e0f09fac78
commit d75d3b94fd
7 changed files with 78 additions and 2 deletions

View File

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

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_discard_none))
Config->DiscardNone = true;
if (Args.hasArg(OPT_export_dynamic))
Config->ExportDynamic = true;

View File

@ -28,6 +28,9 @@ def discard_locals : Flag<["-"], "discard-locals">,
def alias_discard_locals: Flag<["-"], "X">,
Alias<discard_locals>;
def discard_none : Flag<["-"], "discard-none">,
HelpText<"Keep all symbols in the symbol table">;
//===----------------------------------------------------------------------===//
/// Ignored options
//===----------------------------------------------------------------------===//

View File

@ -272,6 +272,15 @@ bool lld::elf2::includeInSymtab(const SymbolBody &B) {
return true;
}
template <class ELFT>
bool SymbolTableSection<ELFT>::shouldKeepInSymtab(StringRef SymName) {
if (Config->DiscardNone)
return true;
// ELF defines dynamic locals as symbols which name starts with ".L".
return !(Config->DiscardLocals && SymName.startswith(".L"));
}
bool lld::elf2::includeInDynamicSymtab(const SymbolBody &B) {
if (Config->ExportDynamic || Config->Shared)
return true;
@ -294,7 +303,7 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
uint32_t SecIndex = Sym.st_shndx;
ErrorOr<StringRef> SymName = Sym.getName(File.getStringTable());
if (Config->DiscardLocals && SymName->startswith(".L"))
if (SymName && !shouldKeepInSymtab(*SymName))
continue;
ESym->st_name = (SymName) ? StrTabSec.getFileOff(*SymName) : 0;
ESym->st_size = Sym.st_size;

View File

@ -186,6 +186,8 @@ public:
++NumLocals;
}
bool shouldKeepInSymtab(StringRef Name);
StringTableSection<ELFT::Is64Bits> &getStrTabSec() const { return StrTabSec; }
unsigned getNumSymbols() const { return NumVisible + 1; }

View File

@ -336,7 +336,7 @@ template <class ELFT> void Writer<ELFT>::createSections() {
Elf_Sym_Range Syms = File.getLocalSymbols();
for (const Elf_Sym &Sym : Syms) {
ErrorOr<StringRef> SymName = Sym.getName(File.getStringTable());
if (SymName && !(Config->DiscardLocals && SymName->startswith(".L")))
if (SymName && SymTabSec.shouldKeepInSymtab(*SymName))
SymTabSec.addSymbol(*SymName, true);
}
}

View File

@ -0,0 +1,58 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t
// RUN: lld -flavor gnu2 -discard-none -shared %t -o %t2
// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s
// REQUIRES: x86
.text
.Lmyvar:
.Lmyothervar:
// CHECK: Section {
// CHECK: Name: .strtab
// CHECK-NEXT: Type: SHT_STRTAB
// CHECK-NEXT: Flags [
// CHECK-NEXT: ]
// CHECK-NEXT: Address:
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size:
// CHECK-NEXT: Link:
// CHECK-NEXT: Info:
// CHECK-NEXT: AddressAlignment:
// CHECK-NEXT: EntrySize:
// CHECK-NEXT: SectionData (
// CHECK-NEXT: 0000: 002E7465 7874002E 62737300 2E64796E |..text..bss..dyn|
// CHECK-NEXT: 0010: 73747200 2E4C6D79 76617200 2E4C6D79 |str..Lmyvar..Lmy|
// CHECK-NEXT: 0020: 6F746865 72766172 002E6479 6E73796D |othervar..dynsym|
// CHECK-NEXT: 0030: 002E6861 7368002E 64796E61 6D696300 |..hash..dynamic.|
// CHECK-NEXT: 0040: 2E737472 74616200 2E73796D 74616200 |.strtab..symtab.|
// CHECK-NEXT: 0050: 2E646174 6100 |.data.|
// CHECK-NEXT: )
// CHECK-NEXT: }
// CHECK: 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: .Lmyothervar
// CHECK-NEXT: Value: 0x1000
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }
// CHECK-NEXT: Symbol {
// CHECK-NEXT: Name: .Lmyvar
// CHECK-NEXT: Value: 0x1000
// CHECK-NEXT: Size: 0
// CHECK-NEXT: Binding: Local
// CHECK-NEXT: Type: None
// CHECK-NEXT: Other: 0
// CHECK-NEXT: Section: .text
// CHECK-NEXT: }