diff options
-rw-r--r-- | lld/ELF/LTO.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 6 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 6 | ||||
-rw-r--r-- | lld/ELF/Symbols.cpp | 21 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 4 | ||||
-rw-r--r-- | lld/test/ELF/mips-dynamic.s | 4 | ||||
-rw-r--r-- | lld/test/ELF/protected-shared.s | 23 |
7 files changed, 45 insertions, 22 deletions
diff --git a/lld/ELF/LTO.cpp b/lld/ELF/LTO.cpp index a9196567c4c..2fdf94a6c5f 100644 --- a/lld/ELF/LTO.cpp +++ b/lld/ELF/LTO.cpp @@ -116,7 +116,8 @@ void BitcodeCompiler::add(BitcodeFile &F) { // Shared libraries need to be handled slightly differently. // For now, let's be conservative and just never internalize // symbols when creating a shared library. - if (!Config->Shared && !Config->ExportDynamic && !B->isUsedInRegularObj()) + if (!Config->Shared && !Config->ExportDynamic && !B->isUsedInRegularObj() && + !B->MustBeInDynSym) if (!Used.count(GV)) InternalizedSyms.insert(GV->getName()); diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 24258fe40cc..753960447fa 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -138,9 +138,6 @@ template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { ++MipsLocalEntries; return; } - // All preemptible symbols with MIPS GOT entries should be represented - // in the dynamic symbols table. - Sym.MustBeInDynSym = true; } Sym.GotIndex = Entries.size(); Entries.push_back(&Sym); @@ -299,9 +296,6 @@ RelocationSection<ELFT>::RelocationSection(StringRef Name) template <class ELFT> void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) { - SymbolBody *Sym = Reloc.Sym; - if (!Reloc.UseSymVA && Sym) - Sym->MustBeInDynSym = true; Relocs.push_back(Reloc); } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 2348f9a6fb4..c1f01c10da8 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -119,10 +119,12 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { for (SymbolBody *Body : Obj->getNonLocalSymbols()) { Symbol *Sym = insert(Body); Sym->Body->setUsedInRegularObj(); - if (!Sym->Body->isUndefined() && Body->isUndefined()) - continue; + if (Sym->Body->isShared()) + Sym->Body->MustBeInDynSym = true; if (Sym->Body->MustBeInDynSym) Body->MustBeInDynSym = true; + if (!Sym->Body->isUndefined() && Body->isUndefined()) + continue; Sym->Body = Body; } ObjectFiles.emplace_back(Obj); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 9def17c6dbb..a0d07690da6 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -218,6 +218,18 @@ int SymbolBody::compare(SymbolBody *Other) { if (L > R) return -Other->compare(this); + if (isShared() != Other->isShared()) { + SymbolBody *Shared = isShared() ? this : Other; + Shared->MustBeInDynSym = true; + if (Shared->getVisibility() == STV_DEFAULT) { + // We want to export all symbols that exist in the executable and are + // preemptable in DSOs, so that the symbols in the executable can + // preempt symbols in the DSO at runtime. + SymbolBody *NonShared = isShared() ? Other : this; + NonShared->MustBeInDynSym = true; + } + } + if (!isShared() && !Other->isShared()) { uint8_t V = getMinVisibility(getVisibility(), Other->getVisibility()); setVisibility(V); @@ -227,15 +239,6 @@ int SymbolBody::compare(SymbolBody *Other) { if (IsUsedInRegularObj || Other->IsUsedInRegularObj) IsUsedInRegularObj = Other->IsUsedInRegularObj = true; - // We want to export all symbols that exist both in the executable - // and in DSOs, so that the symbols in the executable can interrupt - // symbols in the DSO at runtime. - if (isShared() != Other->isShared()) - if (isa<Defined>(isShared() ? Other : this)) { - IsUsedInRegularObj = Other->IsUsedInRegularObj = true; - MustBeInDynSym = Other->MustBeInDynSym = true; - } - if (L != R) return -1; if (!isDefined() || isShared() || isWeak()) diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b19627e8c03..02627cc9d1f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -826,12 +826,14 @@ template <class ELFT> static bool includeInSymtab(const SymbolBody &B) { } static bool includeInDynsym(const SymbolBody &B) { + if (B.MustBeInDynSym) + return true; uint8_t V = B.getVisibility(); if (V != STV_DEFAULT && V != STV_PROTECTED) return false; if (Config->ExportDynamic || Config->Shared) return true; - return B.MustBeInDynSym; + return false; } // This class knows how to create an output section for a given diff --git a/lld/test/ELF/mips-dynamic.s b/lld/test/ELF/mips-dynamic.s index 7dcc247e536..cc5f233163c 100644 --- a/lld/test/ELF/mips-dynamic.s +++ b/lld/test/ELF/mips-dynamic.s @@ -47,8 +47,8 @@ # EXE-DAG: 0x70000005 MIPS_FLAGS NOTPOT # EXE-DAG: 0x70000006 MIPS_BASE_ADDRESS # EXE-DAG: 0x7000000A MIPS_LOCAL_GOTNO 2 -# EXE-DAG: 0x70000011 MIPS_SYMTABNO 2 -# EXE-DAG: 0x70000013 MIPS_GOTSYM 0x2 +# EXE-DAG: 0x70000011 MIPS_SYMTABNO 3 +# EXE-DAG: 0x70000013 MIPS_GOTSYM 0x3 # EXE-DAG: 0x70000016 MIPS_RLD_MAP [[RLDMAPADDR]] # EXE: ] diff --git a/lld/test/ELF/protected-shared.s b/lld/test/ELF/protected-shared.s index ee931831b30..e1391a1320f 100644 --- a/lld/test/ELF/protected-shared.s +++ b/lld/test/ELF/protected-shared.s @@ -3,7 +3,7 @@ // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/protected-shared.s -o %t2.o // RUN: ld.lld -shared %t2.o -o %t2.so // RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-readobj -t %t | FileCheck %s +// RUN: llvm-readobj -t --dyn-symbols %t | FileCheck %s .global _start _start: @@ -27,3 +27,24 @@ bar: // CHECK-NEXT: Type: None // CHECK-NEXT: Other: 0 // CHECK-NEXT: Section: Undefined + +// CHECK: DynamicSymbols [ +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: @ +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Local (0x0) +// CHECK-NEXT: Type: None (0x0) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined (0x0) +// CHECK-NEXT: } +// CHECK-NEXT: Symbol { +// CHECK-NEXT: Name: foo@ +// CHECK-NEXT: Value: 0x0 +// CHECK-NEXT: Size: 0 +// CHECK-NEXT: Binding: Global +// CHECK-NEXT: Type: None +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: Undefined +// CHECK-NEXT: } +// CHECK-NEXT: ] |