Add support for weak symbols.
llvm-svn: 244636
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 @@
ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
error(NameOrErr.getError());
StringRef Name = *NameOrErr;
- if (Sym->isUndefined())
- return new (Alloc) Undefined(Name);
- return new (Alloc) DefinedRegular<ELFT>(Name);
+ switch (Sym->getBinding()) {
+ default:
+ error("unexpected binding");
+ case STB_GLOBAL:
+ if (Sym->isUndefined())
+ return new (Alloc) Undefined(Name);
+ return new (Alloc) DefinedRegular<ELFT>(Name);
+ case STB_WEAK:
+ // FIXME: add support for weak undefined
+ return new (Alloc) DefinedWeak<ELFT>(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 @@
DefinedRegular<ELFT>::DefinedRegular(StringRef Name)
: Defined(DefinedRegularKind, Name) {}
+template <class ELFT>
+DefinedWeak<ELFT>::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 @@
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<llvm::object::ELF32BE>;
template class DefinedRegular<llvm::object::ELF64LE>;
template class DefinedRegular<llvm::object::ELF64BE>;
+
+template class DefinedWeak<llvm::object::ELF32LE>;
+template class DefinedWeak<llvm::object::ELF32BE>;
+template class DefinedWeak<llvm::object::ELF64LE>;
+template class DefinedWeak<llvm::object::ELF64BE>;
}
}
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 @@
enum Kind {
DefinedFirst = 0,
DefinedRegularKind = 0,
- DefinedLast = 0,
- UndefinedKind = 1,
+ DefinedWeakKind = 1,
+ DefinedLast = 1,
+ UndefinedKind = 2
};
Kind kind() const { return static_cast<Kind>(SymbolKind); }
@@ -92,6 +93,15 @@
}
};
+template <class ELFT> 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 0000000..61b5af9
--- /dev/null
+++ b/lld/test/elf2/Inputs/invalid-binding.elf
Binary files differ
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 @@
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 81%
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 @@
nop
local:
+
+.weak foo
+foo:
+
+.long bar