Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -127,6 +127,7 @@ bool GdbIndex; bool GnuHash; bool HasDynamicList = false; + bool HasDynSymTab; bool ICF; bool MipsN32Abi = false; bool NoGnuUnique; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1009,6 +1009,15 @@ for (InputFile *F : Files) Symtab->addFile(F); + // Now that we have every file, we can decide if we will need a + // dynamic symbol table. + // We need one if we were asked to export dynamic symbols or if we are + // producing a shared library. + // We also need one if any shared libraries are used and for pie executables + // (probably because the dynamic linker needs it). + Config->HasDynSymTab = !SharedFile::Instances.empty() || Config->Pic || + Config->ExportDynamic; + // Some symbols (such as __ehdr_start) are defined lazily only when there // are undefined symbols for them, so we add these to trigger that logic. for (StringRef Sym : Script->Opt.ReferencedSymbols) Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -568,8 +568,17 @@ if (IsWrite || isStaticLinkTimeConstant(Expr, Type, Body, S, RelOff)) return Expr; - // This relocation would require the dynamic linker to write a value to read - // only memory. We can hack around it if we are producing an executable and + // If we got here we know that this relocation would require the dynamic + // linker to write a value to read only memory. + + // If the relocation is to a weak undef, give up on it and produce a + // non preemptible 0. + if (Body.isUndefWeak()) { + Body.IsPreemptible = false; + return Expr; + } + + // We can hack around it if we are producing an executable and // the refered symbol can be preemepted to refer to the executable. if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) { error("can't create dynamic relocation " + toString(Type) + " against " + Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -344,10 +344,10 @@ } bool Symbol::includeInDynsym() const { + if (!Config->HasDynSymTab) + return false; if (computeBinding() == STB_LOCAL) return false; - if (body()->isUndefWeak()) - return Config->Shared; if (!body()->isInCurrentDSO()) return true; return ExportDynamic; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -299,10 +299,8 @@ Add(InX::BssRelRo); // Add MIPS-specific sections. - bool HasDynSymTab = !SharedFile::Instances.empty() || Config->Pic || - Config->ExportDynamic; if (Config->EMachine == EM_MIPS) { - if (!Config->Shared && HasDynSymTab) { + if (!Config->Shared && Config->HasDynSymTab) { InX::MipsRldMap = make(); Add(InX::MipsRldMap); } @@ -314,7 +312,7 @@ Add(Sec); } - if (HasDynSymTab) { + if (Config->HasDynSymTab) { InX::DynSymTab = make>(*InX::DynStrTab); Add(InX::DynSymTab); Index: test/ELF/no-inhibit-exec.s =================================================================== --- test/ELF/no-inhibit-exec.s +++ test/ELF/no-inhibit-exec.s @@ -7,7 +7,7 @@ # CHECK: Disassembly of section .text: # CHECK-NEXT: _start -# CHECK-NEXT: 201000: {{.*}} callq 0 +# CHECK-NEXT: 201000: {{.*}} callq -2101253 # RELOC: Relocations [ # RELOC-NEXT: ] Index: test/ELF/pie-weak.s =================================================================== --- test/ELF/pie-weak.s +++ test/ELF/pie-weak.s @@ -5,6 +5,9 @@ # RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s # RELOCS: Relocations [ +# RELOCS-NEXT: Section ({{.*}}) .rela.dyn { +# RELOCS-NEXT: R_X86_64_GLOB_DAT foo 0x0 +# RELOCS-NEXT: } # RELOCS-NEXT: ] .weak foo @@ -12,6 +15,6 @@ .globl _start _start: # DISASM: _start: -# DISASM-NEXT: 1000: 48 8b 05 69 10 00 00 movq 4201(%rip), %rax +# DISASM-NEXT: 1000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax # ^ .got - (.text + 7) mov foo@gotpcrel(%rip), %rax Index: test/ELF/relocation-relative-weak.s =================================================================== --- test/ELF/relocation-relative-weak.s +++ test/ELF/relocation-relative-weak.s @@ -4,6 +4,7 @@ # RUN: llvm-readobj -dyn-relocations %t | FileCheck %s # CHECK: Dynamic Relocations { +# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT w 0x0 # CHECK-NEXT: } .globl _start Index: test/ELF/weak-undef-export.s =================================================================== --- test/ELF/weak-undef-export.s +++ test/ELF/weak-undef-export.s @@ -16,6 +16,15 @@ # CHECK-NEXT: Other: 0 # CHECK-NEXT: Section: Undefined (0x0) # CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo@ (1) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak (0x2) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } # CHECK-NEXT: ] .weak foo Index: test/ELF/weak-undef-val.s =================================================================== --- /dev/null +++ test/ELF/weak-undef-val.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t --export-dynamic +# RUN: llvm-readobj -s -section-data %t | FileCheck %s + +# CHECK: Name: .text +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x201000 +# CHECK-NEXT: Offset: +# CHECK-NEXT: Size: +# CHECK-NEXT: Link: +# CHECK-NEXT: Info: +# CHECK-NEXT: AddressAlignment: +# CHECK-NEXT: EntrySize: +# CHECK-NEXT: SectionData ( +# CHECK-NEXT: 0000: 00F0DFFF | +# CHECK-NEXT: ) + + .global _start +_start: + .weak foobar + .long foobar - . Index: test/ELF/weak-undef.s =================================================================== --- test/ELF/weak-undef.s +++ test/ELF/weak-undef.s @@ -13,6 +13,15 @@ # 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: Weak +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } # CHECK-NEXT: ] .weak foo