Author: Fangrui Song Date: 2025-02-17T16:14:33-08:00 New Revision: 9bcc825ee491a85c2f7b1573d6a3abf6d5cf0c8a
URL: https://github.com/llvm/llvm-project/commit/9bcc825ee491a85c2f7b1573d6a3abf6d5cf0c8a DIFF: https://github.com/llvm/llvm-project/commit/9bcc825ee491a85c2f7b1573d6a3abf6d5cf0c8a.diff LOG: [ELF] Refine isExported/isPreemptible condition Reland 994cea3f0a2d0caf4d66321ad5a06ab330144d89 after bolt tests no longer rely on -pie --unresolved-symbols=ignore-all with no input DSO generating PLT entries. --- Commit f10441ad003236ef3b9e5415a571d2be0c0ce5ce , while dropping a special case for isUndefWeak and --no-dynamic-linking, made --export-dynamic ineffective when -pie is used without any input DSO. This change restores --export-dynamic and unifies -pie and -pie --no-dynamic-linker when there is no input DSO. * -pie with no input DSO suppresses undefined symbols in .dynsym. Previously this only appied to -pie --no-dynamic-linker. * As a side effect, -pie with no input DSO suppresses PLT. (cherry picked from commit 52fc6ffcda0895c0c7b976ad1f5cb5a282b571d2) Added: Modified: lld/ELF/Config.h lld/ELF/Driver.cpp lld/ELF/Symbols.cpp lld/ELF/SyntheticSections.cpp lld/ELF/Writer.cpp lld/test/ELF/executable-undefined-ignoreall.s lld/test/ELF/ppc32-weak-undef-call.s lld/test/ELF/ppc64-undefined-weak.s lld/test/ELF/riscv-gp.s lld/test/ELF/weak-undef-lib.s lld/test/ELF/weak-undef-no-dynamic-linker.s lld/test/ELF/weak-undef-rw.s Removed: ################################################################################ diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 98e52b52ea46a..9826ed0517337 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -292,7 +292,6 @@ struct Config { bool gdbIndex; bool gnuHash = false; bool gnuUnique; - bool hasDynSymTab; bool ignoreDataAddressEquality; bool ignoreFunctionAddressEquality; bool ltoCSProfileGenerate; @@ -306,7 +305,6 @@ struct Config { bool mipsN32Abi = false; bool mmapOutputFile; bool nmagic; - bool noDynamicLinker = false; bool noinhibitExec; bool nostdlib; bool oFormatBinary; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 391140bce7394..a1e9ecae08557 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -781,11 +781,8 @@ static StringRef getDynamicLinker(Ctx &ctx, opt::InputArgList &args) { auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker); if (!arg) return ""; - if (arg->getOption().getID() == OPT_no_dynamic_linker) { - // --no-dynamic-linker suppresses undefined weak symbols in .dynsym - ctx.arg.noDynamicLinker = true; + if (arg->getOption().getID() == OPT_no_dynamic_linker) return ""; - } return arg->getValue(); } @@ -2921,12 +2918,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) { parseFiles(ctx, files); - // Dynamic linking is used if there is an input DSO, - // or -shared or non-static pie is specified. - ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.shared || - (ctx.arg.pie && !ctx.arg.noDynamicLinker); // Create dynamic sections for dynamic linking and static PIE. - ctx.arg.hasDynSymTab = ctx.hasDynsym || ctx.arg.isPic; + ctx.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic; // If an entry symbol is in a static archive, pull out that file now. if (Symbol *sym = ctx.symtab->find(ctx.arg.entry)) diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 890877cb1bc04..80b0691428007 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -360,7 +360,9 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) { // Symbol themselves might know their versions because symbols // can contain versions in the form of <name>@<version>. // Let them parse and update their names to exclude version suffix. + // In addition, compute isExported and isPreemptible. bool hasDynsym = ctx.hasDynsym; + bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared; for (Symbol *sym : ctx.symtab->getSymbols()) { if (sym->hasVersionSuffix) sym->parseSymbolVersion(ctx); @@ -371,7 +373,7 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) { continue; } if (!sym->isDefined() && !sym->isCommon()) { - sym->isPreemptible = computeIsPreemptible(ctx, *sym); + sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym); } else if (ctx.arg.exportDynamic && (sym->isUsedInRegularObj || !sym->ltoCanOmit)) { sym->isExported = true; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index ffa6e3c008c48..b03c4282ab1aa 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4740,7 +4740,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) { // Add MIPS-specific sections. if (ctx.arg.emachine == EM_MIPS) { - if (!ctx.arg.shared && ctx.arg.hasDynSymTab) { + if (!ctx.arg.shared && ctx.hasDynsym) { ctx.in.mipsRldMap = std::make_unique<MipsRldMapSection>(ctx); add(*ctx.in.mipsRldMap); } @@ -4803,7 +4803,7 @@ template <class ELFT> void elf::createSyntheticSections(Ctx &ctx) { part.relaDyn = std::make_unique<RelocationSection<ELFT>>( ctx, relaDynName, ctx.arg.zCombreloc, threadCount); - if (ctx.arg.hasDynSymTab) { + if (ctx.hasDynsym) { add(*part.dynSymTab); part.verSym = std::make_unique<VersionTableSection>(ctx); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3ba1cdbce572b..0db922b07aabf 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -284,6 +284,7 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) { llvm::TimeTraceScope timeScope("Demote symbols"); DenseMap<InputFile *, DenseMap<SectionBase *, size_t>> sectionIndexMap; bool hasDynsym = ctx.hasDynsym; + bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared; for (Symbol *sym : ctx.symtab->getSymbols()) { if (auto *d = dyn_cast<Defined>(sym)) { if (d->section && !d->section->isLive()) @@ -300,7 +301,8 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) { } if (hasDynsym) - sym->isPreemptible = (sym->isUndefined() || sym->isExported) && + sym->isPreemptible = maybePreemptible && + (sym->isUndefined() || sym->isExported) && computeIsPreemptible(ctx, *sym); } } @@ -1929,10 +1931,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (ctx.in.symTab) ctx.in.symTab->addSymbol(sym); - // computeBinding might localize a linker-synthesized hidden symbol - // (e.g. __global_pointer$) that was considered exported. - if (ctx.hasDynsym && (sym->isUndefined() || sym->isExported) && - !sym->isLocal()) { + // computeBinding might localize a symbol that was considered exported + // but then synthesized as hidden (e.g. _DYNAMIC). + if ((sym->isExported || sym->isPreemptible) && !sym->isLocal()) { ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym); if (auto *file = dyn_cast<SharedFile>(sym->file)) if (file->isNeeded && !sym->isUndefined()) diff --git a/lld/test/ELF/executable-undefined-ignoreall.s b/lld/test/ELF/executable-undefined-ignoreall.s index 073b22bd84543..1f83b1b61830a 100644 --- a/lld/test/ELF/executable-undefined-ignoreall.s +++ b/lld/test/ELF/executable-undefined-ignoreall.s @@ -1,11 +1,13 @@ # REQUIRES: x86 -## --unresolved-symbols=ignore-all behaves similar to -shared: +## In dynamic linking, --unresolved-symbols=ignore-all behaves similar to -shared: ## for PLT relocations to undefined symbols, produce dynamic relocations if we ## emit .dynsym. +# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/shared.s -o %ta.o +# RUN: ld.lld -shared -soname=ta %ta.o -o %ta.so # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o -# RUN: ld.lld %t.o -o %t --unresolved-symbols=ignore-all -pie +# RUN: ld.lld %t.o %ta.so -o %t --unresolved-symbols=ignore-all -pie # RUN: llvm-readobj -r %t | FileCheck %s # CHECK: Relocations [ diff --git a/lld/test/ELF/ppc32-weak-undef-call.s b/lld/test/ELF/ppc32-weak-undef-call.s index dfb45e5fe18cf..1ad280a49c038 100644 --- a/lld/test/ELF/ppc32-weak-undef-call.s +++ b/lld/test/ELF/ppc32-weak-undef-call.s @@ -1,15 +1,15 @@ # REQUIRES: ppc # RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o # RUN: ld.lld %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PDE %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s # RUN: ld.lld -pie %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s # RUN: ld.lld -shared %t.o -o %t # RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %s ## It does not really matter how we fixup it, but we cannot overflow and ## should not generate a call stub (this would waste space). -# PDE: bl 0x100100b4 +# STATIC: bl {{.*}} <.text> ## With -pie or -shared, create a call stub. ld.bfd produces bl .+0 # PIC: bl 0x[[PLT:[0-9a-f]+]] diff --git a/lld/test/ELF/ppc64-undefined-weak.s b/lld/test/ELF/ppc64-undefined-weak.s index 7b1be5e36dd32..e9168020b216f 100644 --- a/lld/test/ELF/ppc64-undefined-weak.s +++ b/lld/test/ELF/ppc64-undefined-weak.s @@ -2,25 +2,25 @@ # RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o # RUN: ld.lld %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC # RUN: ld.lld -pie %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIC +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC # RUN: ld.lld -shared %t.o -o %t.so # RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s --check-prefix=PIC # RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o # RUN: ld.lld %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC ## Branches to an undefined weak symbol need a thunk iff a dynamic relocation is ## produced. undefweak2 is hidden and does not need a dynamic relocation, so we ## suppress the thunk. undefweak1 needs a thunk iff -pie or -shared. -# PDE-LABEL: <_start>: -# PDE-NEXT: bl {{.*}} <_start> -# PDE-NEXT: nop -# PDE-NEXT: bl {{.*}} <_start+0x8> -# PDE-NEXT: nop +# STATIC-LABEL: <_start>: +# STATIC-NEXT: bl {{.*}} <_start> +# STATIC-NEXT: nop +# STATIC-NEXT: bl {{.*}} <_start+0x8> +# STATIC-NEXT: nop # PIC-LABEL: <_start>: # PIC-NEXT: bl {{.*}} <__plt_undefweak1> diff --git a/lld/test/ELF/riscv-gp.s b/lld/test/ELF/riscv-gp.s index a30f5e9fbc625..2f715e1470f2d 100644 --- a/lld/test/ELF/riscv-gp.s +++ b/lld/test/ELF/riscv-gp.s @@ -14,17 +14,20 @@ # SEC32: {{0*}}000039c0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$ # SEC64: [ [[#SDATA:]]] .sdata PROGBITS {{0*}}000032e0 +# SEC64: '.dynsym' +# SEC64-NOT: __global_pointer$ +# SEC64: '.symtab' # SEC64: {{0*}}00003ae0 0 NOTYPE GLOBAL DEFAULT [[#SDATA]] __global_pointer$ # ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol '__global_pointer$'; recompile with -fPIC # RUN: ld.lld -pie --no-dynamic-linker --export-dynamic %t.64.o -o %t.64e -# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICPIE +# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICE -# STATICPIE: '.dynsym' -# STATICPIE-NOT: __global_pointer$ -# STATICPIE: '.symtab' -# STATICPIE: __global_pointer$ +# STATICE: '.dynsym' +# STATICE: __global_pointer$ +# STATICE: '.symtab' +# STATICE: __global_pointer$ ## -r mode does not define __global_pointer$. # RUN: ld.lld -r %t.64.o -o %t.64.ro diff --git a/lld/test/ELF/weak-undef-lib.s b/lld/test/ELF/weak-undef-lib.s index a554e1d5a2f89..0ff1bc755f075 100644 --- a/lld/test/ELF/weak-undef-lib.s +++ b/lld/test/ELF/weak-undef-lib.s @@ -7,7 +7,7 @@ # RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s # RUN: ld.lld -pie -o %t %t1.o --start-lib %t2.o -# RUN: llvm-readobj --dyn-syms %t | FileCheck %s +# RUN: llvm-readelf --dyn-syms %t | FileCheck %s --check-prefix=STATICPIE # CHECK: Name: foo # CHECK-NEXT: Value: 0x0 diff --git a/lld/test/ELF/weak-undef-no-dynamic-linker.s b/lld/test/ELF/weak-undef-no-dynamic-linker.s index fa6936e1ef393..11abd5351af9d 100644 --- a/lld/test/ELF/weak-undef-no-dynamic-linker.s +++ b/lld/test/ELF/weak-undef-no-dynamic-linker.s @@ -1,13 +1,12 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o # RUN: ld.lld -pie %t.o -o %t -# RUN: llvm-readobj --dyn-syms %t | FileCheck %s +# RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s # RUN: ld.lld -pie --no-dynamic-linker %t.o -o %t # RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s -## With --no-dynamic-linker, don't emit undefined weak symbols to .dynsym . -## This will suppress a relocation. -# CHECK: Name: foo +## With static PIE (whether or not --no-dynamic-linker is specified), don't +## emit undefined weak symbols to .dynsym . This suppresses relocations. # NO-NOT: Name: foo .weak foo diff --git a/lld/test/ELF/weak-undef-rw.s b/lld/test/ELF/weak-undef-rw.s index ec3e4ce734895..c5cf1bdcaba68 100644 --- a/lld/test/ELF/weak-undef-rw.s +++ b/lld/test/ELF/weak-undef-rw.s @@ -1,23 +1,23 @@ # 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-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=NOPIC +# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=STATIC # RUN: ld.lld %t.o -o %t.pie -pie -# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=PIC +# RUN: llvm-readelf -r --hex-dump=.data %t.pie | FileCheck %s --check-prefix=STATIC # RUN: ld.lld %t.o -o %t.so -shared # RUN: llvm-readobj -r %t.so | FileCheck %s --check-prefix=PIC ## gABI leaves the behavior of weak undefined references implementation defined. -## We choose to resolve them statically for -no-pie and produce dynamic relocations -## for -pie and -shared. +## We choose to resolve them statically for static linking and produce dynamic relocations +## for dynamic linking (-shared or at least one input DSO). ## ## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't ## implement. -# NOPIC: no relocations -# NOPIC: Hex dump of section '.data': -# NOPIC-NEXT: {{.*}} 00000000 00000000 -# NOPIC-EMPTY: +# STATIC: no relocations +# STATIC: Hex dump of section '.data': +# STATIC-NEXT: {{.*}} 00000000 00000000 . +# STATIC-EMPTY: # PIC: .rela.dyn { # PIC-NEXT: R_X86_64_64 foobar 0x0 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits