summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-01-22 16:53:01 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-01-22 16:53:01 +0000
commitabe21bdf8e3c7be93c9236c3eec47756e14582bb (patch)
tree957ab78d01784aa3d52722f949adcfd059dbaaae
parent1eafc0458f4bb4547fe78c62b78312ad4f719c38 (diff)
downloadsrc-test-abe21bdf8e3c7be93c9236c3eec47756e14582bb.tar.gz
src-test-abe21bdf8e3c7be93c9236c3eec47756e14582bb.zip
Notes
-rw-r--r--ELF/SymbolTable.cpp18
-rw-r--r--ELF/SymbolTable.h1
-rw-r--r--ELF/Symbols.cpp7
-rw-r--r--ELF/Symbols.h1
-rw-r--r--ELF/SyntheticSections.cpp4
-rw-r--r--ELF/Writer.cpp4
-rw-r--r--test/ELF/Inputs/resolution-end.s2
-rw-r--r--test/ELF/gc-sections-shared.s9
-rw-r--r--test/ELF/init-fini.s17
-rw-r--r--test/ELF/resolution-end.s39
-rw-r--r--test/ELF/version-script-hide-so-symbol.s28
11 files changed, 104 insertions, 26 deletions
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
index 6afe3dde9babb..ce257933c2677 100644
--- a/ELF/SymbolTable.cpp
+++ b/ELF/SymbolTable.cpp
@@ -140,7 +140,7 @@ template <class ELFT>
DefinedRegular<ELFT> *SymbolTable<ELFT>::addIgnored(StringRef Name,
uint8_t Visibility) {
SymbolBody *S = find(Name);
- if (!S || !S->isUndefined())
+ if (!S || S->isInCurrentDSO())
return nullptr;
return addAbsolute(Name, Visibility);
}
@@ -283,7 +283,7 @@ static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding) {
if (WasInserted)
return 1;
SymbolBody *Body = S->body();
- if (Body->isLazy() || Body->isUndefined() || Body->isShared())
+ if (Body->isLazy() || !Body->isInCurrentDSO())
return 1;
if (Binding == STB_WEAK)
return -1;
@@ -426,12 +426,8 @@ void SymbolTable<ELFT>::addShared(SharedFile<ELFT> *F, StringRef Name,
std::tie(S, WasInserted) =
insert(Name, Sym.getType(), STV_DEFAULT, /*CanOmitFromDynSym*/ true, F);
// Make sure we preempt DSO symbols with default visibility.
- if (Sym.getVisibility() == STV_DEFAULT) {
+ if (Sym.getVisibility() == STV_DEFAULT)
S->ExportDynamic = true;
- // Exporting preempting symbols takes precedence over linker scripts.
- if (S->VersionId == VER_NDX_LOCAL)
- S->VersionId = VER_NDX_GLOBAL;
- }
if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
if (!S->isWeak())
@@ -468,6 +464,14 @@ template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
}
template <class ELFT>
+SymbolBody *SymbolTable<ELFT>::findInCurrentDSO(StringRef Name) {
+ if (SymbolBody *S = find(Name))
+ if (S->isInCurrentDSO())
+ return S;
+ return nullptr;
+}
+
+template <class ELFT>
void SymbolTable<ELFT>::addLazyArchive(ArchiveFile *F,
const object::Archive::Symbol Sym) {
Symbol *S;
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
index 1e5a335acc167..f39dbd1e2e18c 100644
--- a/ELF/SymbolTable.h
+++ b/ELF/SymbolTable.h
@@ -82,6 +82,7 @@ public:
void scanVersionScript();
SymbolBody *find(StringRef Name);
+ SymbolBody *findInCurrentDSO(StringRef Name);
void trace(StringRef Name);
void wrap(StringRef Name);
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
index 289bc18487a8e..0fe42be250cf1 100644
--- a/ELF/Symbols.cpp
+++ b/ELF/Symbols.cpp
@@ -203,8 +203,8 @@ void SymbolBody::parseSymbolVersion() {
// Truncate the symbol name so that it doesn't include the version string.
Name = {S.data(), Pos};
- // If this is an undefined or shared symbol it is not a definition.
- if (isUndefined() || isShared())
+ // If this is not in this DSO, it is not a definition.
+ if (!isInCurrentDSO())
return;
// '@@' in a symbol name means the default version.
@@ -299,7 +299,8 @@ uint8_t Symbol::computeBinding() const {
return Binding;
if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
return STB_LOCAL;
- if (VersionId == VER_NDX_LOCAL && !body()->isUndefined())
+ const SymbolBody *Body = body();
+ if (VersionId == VER_NDX_LOCAL && Body->isInCurrentDSO())
return STB_LOCAL;
if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
return STB_GLOBAL;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
index af85dc2b121dc..7acb89ad0718d 100644
--- a/ELF/Symbols.h
+++ b/ELF/Symbols.h
@@ -67,6 +67,7 @@ public:
return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
}
bool isShared() const { return SymbolKind == SharedKind; }
+ bool isInCurrentDSO() const { return !isUndefined() && !isShared(); }
bool isLocal() const { return IsLocal; }
bool isPreemptible() const;
StringRef getName() const { return Name; }
diff --git a/ELF/SyntheticSections.cpp b/ELF/SyntheticSections.cpp
index 5486b38eec105..f09b60b2b4948 100644
--- a/ELF/SyntheticSections.cpp
+++ b/ELF/SyntheticSections.cpp
@@ -883,9 +883,9 @@ template <class ELFT> void DynamicSection<ELFT>::finalize() {
add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize});
}
- if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init))
+ if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Init))
add({DT_INIT, B});
- if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini))
+ if (SymbolBody *B = Symtab<ELFT>::X->findInCurrentDSO(Config->Fini))
add({DT_FINI, B});
bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0;
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
index bddc42e1acf91..4f2f91993f8d2 100644
--- a/ELF/Writer.cpp
+++ b/ELF/Writer.cpp
@@ -641,7 +641,7 @@ static void addOptionalSynthetic(StringRef Name, OutputSectionBase *Sec,
typename ELFT::uint Val,
uint8_t StOther = STV_HIDDEN) {
if (SymbolBody *S = Symtab<ELFT>::X->find(Name))
- if (S->isUndefined() || S->isShared())
+ if (!S->isInCurrentDSO())
Symtab<ELFT>::X->addSynthetic(Name, Sec, Val, StOther);
}
@@ -661,7 +661,7 @@ static Symbol *addOptionalRegular(StringRef Name, InputSectionBase<ELFT> *IS,
SymbolBody *S = Symtab<ELFT>::X->find(Name);
if (!S)
return nullptr;
- if (!S->isUndefined() && !S->isShared())
+ if (S->isInCurrentDSO())
return S->symbol();
return addRegular(Name, IS, Value);
}
diff --git a/test/ELF/Inputs/resolution-end.s b/test/ELF/Inputs/resolution-end.s
new file mode 100644
index 0000000000000..41567c81ef53a
--- /dev/null
+++ b/test/ELF/Inputs/resolution-end.s
@@ -0,0 +1,2 @@
+.data
+ .quad _end
diff --git a/test/ELF/gc-sections-shared.s b/test/ELF/gc-sections-shared.s
index f1ac9cd345d45..a88f2b4434797 100644
--- a/test/ELF/gc-sections-shared.s
+++ b/test/ELF/gc-sections-shared.s
@@ -19,15 +19,6 @@
# CHECK-NEXT: Section: Undefined (0x0)
# CHECK-NEXT: }
# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: bar
-# CHECK-NEXT: Value:
-# CHECK-NEXT: Size:
-# CHECK-NEXT: Binding: Global
-# CHECK-NEXT: Type:
-# CHECK-NEXT: Other:
-# CHECK-NEXT: Section: .text
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
# CHECK-NEXT: Name: bar2
# CHECK-NEXT: Value:
# CHECK-NEXT: Size:
diff --git a/test/ELF/init-fini.s b/test/ELF/init-fini.s
index 4006790666360..37d8b01490770 100644
--- a/test/ELF/init-fini.s
+++ b/test/ELF/init-fini.s
@@ -17,11 +17,22 @@
// RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
-// Should add a dynamic table entry even if a given symbol stay undefined
+// Don't add an entry for undef. The freebsd dynamic linker doesn't
+// check if the value is null. If it is, it will just call the
+// load address.
// RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef
// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s
-// UNDEF: INIT 0x0
-// UNDEF: FINI 0x0
+// UNDEF-NOT: INIT
+// UNDEF-NOT: FINI
+
+// Don't add an entry for shared. For the same reason as undef.
+// RUN: ld.lld -shared %t -o %t.so
+// RUN: echo > %t.s
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t2.o
+// RUN: ld.lld -shared %t2.o %t.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=SHARED %s
+// SHARED-NOT: INIT
+// SHARED-NOT: FINI
// Should not add new entries to the symbol table
// and should not require given symbols to be resolved
diff --git a/test/ELF/resolution-end.s b/test/ELF/resolution-end.s
new file mode 100644
index 0000000000000..72c8e9569fba0
--- /dev/null
+++ b/test/ELF/resolution-end.s
@@ -0,0 +1,39 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-end.s -o %t2.o
+# RUN: ld.lld -shared -o %t2.so %t2.o
+# RUN: ld.lld %t1.o %t2.so -o %t
+# RUN: llvm-readobj -t -s -section-data %t | FileCheck %s
+# REQUIRES: x86
+
+# Test that we resolve _end to the this executable.
+
+# CHECK: Name: .text
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_EXECINSTR
+# 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: 80202000 00000000
+# CHECK-NEXT: )
+
+# CHECK: Symbol {
+# CHECK: Name: _end
+# CHECK-NEXT: Value: 0x202080
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section:
+# CHECK-NEXT: }
+
+.global _start
+_start:
+.quad _end
diff --git a/test/ELF/version-script-hide-so-symbol.s b/test/ELF/version-script-hide-so-symbol.s
new file mode 100644
index 0000000000000..b4f58be06de78
--- /dev/null
+++ b/test/ELF/version-script-hide-so-symbol.s
@@ -0,0 +1,28 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t2.so
+# RUN: echo "{ local: *; };" > %t.script
+# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so
+# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s
+
+# The symbol foo must be hidden. This matches bfd and gold and is
+# required to make it possible for a c++ library to hide its own
+# operator delete.
+
+# CHECK: DynamicSymbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: @ (0)
+# 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: ]
+
+ .global foo
+foo:
+ nop
+