From b13df6582a6a7802d4e0675a4ae7545c09a766a9 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Tue, 11 Aug 2015 17:33:02 +0000 Subject: [PATCH] Add support for weak symbols. llvm-svn: 244636 --- lld/ELF/InputFiles.cpp | 14 +++++++++++--- lld/ELF/Symbols.cpp | 15 +++++++++++---- lld/ELF/Symbols.h | 14 ++++++++++++-- lld/test/elf2/Inputs/invalid-binding.elf | Bin 0 -> 536 bytes lld/test/elf2/Inputs/local.s | 1 - lld/test/elf2/Inputs/resolution.s | 10 ++++++++++ lld/test/elf2/invalid-elf.test | 4 ++++ lld/test/elf2/{local.s => resolution.s} | 7 ++++++- 8 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 lld/test/elf2/Inputs/invalid-binding.elf delete mode 100644 lld/test/elf2/Inputs/local.s create mode 100644 lld/test/elf2/Inputs/resolution.s rename lld/test/elf2/{local.s => resolution.s} (82%) diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 9dcd2fa..3a11967 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -75,9 +75,17 @@ SymbolBody *elf2::ObjectFile::createSymbolBody(StringRef StringTable, ErrorOr NameOrErr = Sym->getName(StringTable); error(NameOrErr.getError()); StringRef Name = *NameOrErr; - if (Sym->isUndefined()) - return new (Alloc) Undefined(Name); - return new (Alloc) DefinedRegular(Name); + switch (Sym->getBinding()) { + default: + error("unexpected binding"); + case STB_GLOBAL: + if (Sym->isUndefined()) + return new (Alloc) Undefined(Name); + return new (Alloc) DefinedRegular(Name); + case STB_WEAK: + // FIXME: add support for weak undefined + return new (Alloc) DefinedWeak(Name); + } } namespace lld { diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 32bcf8e..0964437 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -21,6 +21,10 @@ template DefinedRegular::DefinedRegular(StringRef Name) : Defined(DefinedRegularKind, Name) {} +template +DefinedWeak::DefinedWeak(StringRef Name) + : Defined(DefinedWeakKind, Name) {} + // Returns 1, 0 or -1 if this symbol should take precedence // over the Other, tie or lose, respectively. int SymbolBody::compare(SymbolBody *Other) { @@ -32,16 +36,14 @@ int SymbolBody::compare(SymbolBody *Other) { return -Other->compare(this); // First handle comparisons between two different kinds. - if (LK != RK) { - assert(LK == DefinedRegularKind); - assert(RK == UndefinedKind); + if (LK != RK) return 1; - } // Now handle the case where the kinds are the same. switch (LK) { case DefinedRegularKind: return 0; + case DefinedWeakKind: case UndefinedKind: return 1; } @@ -54,5 +56,10 @@ template class DefinedRegular; template class DefinedRegular; template class DefinedRegular; template class DefinedRegular; + +template class DefinedWeak; +template class DefinedWeak; +template class DefinedWeak; +template class DefinedWeak; } } diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index 197a30c..18e31da 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -37,8 +37,9 @@ public: enum Kind { DefinedFirst = 0, DefinedRegularKind = 0, - DefinedLast = 0, - UndefinedKind = 1, + DefinedWeakKind = 1, + DefinedLast = 1, + UndefinedKind = 2 }; Kind kind() const { return static_cast(SymbolKind); } @@ -92,6 +93,15 @@ public: } }; +template class DefinedWeak : public Defined { +public: + DefinedWeak(StringRef Name); + + static bool classof(const SymbolBody *S) { + return S->kind() == DefinedWeakKind; + } +}; + // Undefined symbols. class Undefined : public SymbolBody { public: diff --git a/lld/test/elf2/Inputs/invalid-binding.elf b/lld/test/elf2/Inputs/invalid-binding.elf new file mode 100644 index 0000000000000000000000000000000000000000..61b5af9b456c75d8922ef3dae3b7781da9c0bac8 GIT binary patch literal 536 zcmb<-^>JfjWMpQ50!9Wq21XbMiJpPPb^x;-7}&6?gec?zQU(l65Dqe_SCU#$!l0K_ zT+EP`pUGCWvd~Hftcui2Ju0d4J3&K z9FW+^OcrDgkgWj3ApPiWZ~%&71L*qMfr>bQm|Xo5K)qN(pTPkr4gv-c3hYLZJ3)4V J07xGQ003eq5ljF8 literal 0 HcmV?d00001 diff --git a/lld/test/elf2/Inputs/local.s b/lld/test/elf2/Inputs/local.s deleted file mode 100644 index a5c4ffc..0000000 --- a/lld/test/elf2/Inputs/local.s +++ /dev/null @@ -1 +0,0 @@ -local: diff --git a/lld/test/elf2/Inputs/resolution.s b/lld/test/elf2/Inputs/resolution.s new file mode 100644 index 0000000..e3ab048 --- /dev/null +++ b/lld/test/elf2/Inputs/resolution.s @@ -0,0 +1,10 @@ +local: + +.weak foo +foo: + +.weak _start +_start: + +.weak bar +bar: diff --git a/lld/test/elf2/invalid-elf.test b/lld/test/elf2/invalid-elf.test index 95fd671..5b2bea3 100644 --- a/lld/test/elf2/invalid-elf.test +++ b/lld/test/elf2/invalid-elf.test @@ -9,3 +9,7 @@ INVALID-FILE-CLASS: Invalid file class RUN: not lld -flavor gnu2 %p/Inputs/invalid-symtab-sh_info.elf -o %t2 2>&1 | \ RUN: FileCheck --check-prefix=INVALID-SYMTAB-SHINFO %s INVALID-SYMTAB-SHINFO: Invalid sh_info in symbol table + +RUN: not lld -flavor gnu2 %p/Inputs/invalid-binding.elf -o %t2 2>&1 | \ +RUN: FileCheck --check-prefix=INVALID-BINDING %s +INVALID-BINDING: unexpected binding diff --git a/lld/test/elf2/local.s b/lld/test/elf2/resolution.s similarity index 82% rename from lld/test/elf2/local.s rename to lld/test/elf2/resolution.s index 295ff61..a49c7d5 100644 --- a/lld/test/elf2/local.s +++ b/lld/test/elf2/resolution.s @@ -1,5 +1,5 @@ // RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t -// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/local.s -o %t2 +// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/resolution.s -o %t2 // RUN: lld -flavor gnu2 %t %t2 -o %t3 // REQUIRES: x86 @@ -8,3 +8,8 @@ _start: nop local: + +.weak foo +foo: + +.long bar -- 2.7.4