From b84f7d17f84030092880857544e13d26a2507c62 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 3 Feb 2025 10:00:10 +0100 Subject: [PATCH] Revert "[ELF] Refine isExported/isPreemptible condition" This reverts commit 994cea3f0a2d0caf4d66321ad5a06ab330144d89. Try to fix the bolt test failures in pre-merge checks. --- lld/ELF/Config.h | 2 ++ lld/ELF/Driver.cpp | 11 +++++++++-- lld/ELF/Symbols.cpp | 4 +--- lld/ELF/SyntheticSections.cpp | 4 ++-- lld/ELF/Writer.cpp | 7 +++---- lld/test/ELF/executable-undefined-ignoreall.s | 6 ++---- lld/test/ELF/ppc32-weak-undef-call.s | 6 +++--- lld/test/ELF/ppc64-undefined-weak.s | 16 ++++++++-------- lld/test/ELF/riscv-gp.s | 13 +++++-------- lld/test/ELF/weak-undef-lib.s | 2 +- lld/test/ELF/weak-undef-no-dynamic-linker.s | 7 ++++--- lld/test/ELF/weak-undef-rw.s | 16 ++++++++-------- 12 files changed, 48 insertions(+), 46 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 3cdb400e423f..a1ac0973bcc4 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -298,6 +298,7 @@ struct Config { bool gdbIndex; bool gnuHash = false; bool gnuUnique; + bool hasDynSymTab; bool ignoreDataAddressEquality; bool ignoreFunctionAddressEquality; bool ltoCSProfileGenerate; @@ -311,6 +312,7 @@ 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 2835b86d05e9..a14d3629f6ee 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -781,8 +781,11 @@ 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) + if (arg->getOption().getID() == OPT_no_dynamic_linker) { + // --no-dynamic-linker suppresses undefined weak symbols in .dynsym + ctx.arg.noDynamicLinker = true; return ""; + } return arg->getValue(); } @@ -2945,8 +2948,12 @@ template 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.hasDynsym = !ctx.sharedFiles.empty() || ctx.arg.isPic; + ctx.arg.hasDynSymTab = ctx.hasDynsym || 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 80b069142800..890877cb1bc0 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -360,9 +360,7 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) { // Symbol themselves might know their versions because symbols // can contain versions in the form of @. // 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); @@ -373,7 +371,7 @@ void elf::parseVersionAndComputeIsPreemptible(Ctx &ctx) { continue; } if (!sym->isDefined() && !sym->isCommon()) { - sym->isPreemptible = maybePreemptible && computeIsPreemptible(ctx, *sym); + sym->isPreemptible = 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 b03c4282ab1a..ffa6e3c008c4 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -4740,7 +4740,7 @@ template void elf::createSyntheticSections(Ctx &ctx) { // Add MIPS-specific sections. if (ctx.arg.emachine == EM_MIPS) { - if (!ctx.arg.shared && ctx.hasDynsym) { + if (!ctx.arg.shared && ctx.arg.hasDynSymTab) { ctx.in.mipsRldMap = std::make_unique(ctx); add(*ctx.in.mipsRldMap); } @@ -4803,7 +4803,7 @@ template void elf::createSyntheticSections(Ctx &ctx) { part.relaDyn = std::make_unique>( ctx, relaDynName, ctx.arg.zCombreloc, threadCount); - if (ctx.hasDynsym) { + if (ctx.arg.hasDynSymTab) { add(*part.dynSymTab); part.verSym = std::make_unique(ctx); diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 7e3a920df19e..49077055e84f 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -285,7 +285,6 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) { llvm::TimeTraceScope timeScope("Demote symbols"); DenseMap> sectionIndexMap; bool hasDynsym = ctx.hasDynsym; - bool maybePreemptible = ctx.sharedFiles.size() || ctx.arg.shared; for (Symbol *sym : ctx.symtab->getSymbols()) { if (auto *d = dyn_cast(sym)) { if (d->section && !d->section->isLive()) @@ -302,8 +301,7 @@ static void demoteSymbolsAndComputeIsPreemptible(Ctx &ctx) { } if (hasDynsym) - sym->isPreemptible = maybePreemptible && - (sym->isUndefined() || sym->isExported) && + sym->isPreemptible = (sym->isUndefined() || sym->isExported) && computeIsPreemptible(ctx, *sym); } } @@ -1944,7 +1942,8 @@ template void Writer::finalizeSections() { // computeBinding might localize a linker-synthesized hidden symbol // (e.g. __global_pointer$) that was considered exported. - if ((sym->isExported || sym->isPreemptible) && !sym->isLocal()) { + if (ctx.hasDynsym && (sym->isUndefined() || sym->isExported) && + !sym->isLocal()) { ctx.partitions[sym->partition - 1].dynSymTab->addSymbol(sym); if (auto *file = dyn_cast(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 1f83b1b61830..073b22bd8454 100644 --- a/lld/test/ELF/executable-undefined-ignoreall.s +++ b/lld/test/ELF/executable-undefined-ignoreall.s @@ -1,13 +1,11 @@ # REQUIRES: x86 -## In dynamic linking, --unresolved-symbols=ignore-all behaves similar to -shared: +## --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 %ta.so -o %t --unresolved-symbols=ignore-all -pie +# RUN: ld.lld %t.o -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 1ad280a49c03..dfb45e5fe18c 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=STATIC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PDE %s # RUN: ld.lld -pie %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=STATIC %s +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=PIC %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). -# STATIC: bl {{.*}} <.text> +# PDE: bl 0x100100b4 ## 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 e9168020b216..7b1be5e36dd3 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=STATIC +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE # RUN: ld.lld -pie %t.o -o %t -# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=STATIC +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIC # 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=STATIC +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE ## 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. -# STATIC-LABEL: <_start>: -# STATIC-NEXT: bl {{.*}} <_start> -# STATIC-NEXT: nop -# STATIC-NEXT: bl {{.*}} <_start+0x8> -# STATIC-NEXT: nop +# PDE-LABEL: <_start>: +# PDE-NEXT: bl {{.*}} <_start> +# PDE-NEXT: nop +# PDE-NEXT: bl {{.*}} <_start+0x8> +# PDE-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 2f715e1470f2..a30f5e9fbc62 100644 --- a/lld/test/ELF/riscv-gp.s +++ b/lld/test/ELF/riscv-gp.s @@ -14,20 +14,17 @@ # 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=STATICE +# RUN: llvm-readelf -s %t.64e | FileCheck %s --check-prefix=STATICPIE -# STATICE: '.dynsym' -# STATICE: __global_pointer$ -# STATICE: '.symtab' -# STATICE: __global_pointer$ +# STATICPIE: '.dynsym' +# STATICPIE-NOT: __global_pointer$ +# STATICPIE: '.symtab' +# STATICPIE: __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 0ff1bc755f07..a554e1d5a2f8 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-readelf --dyn-syms %t | FileCheck %s --check-prefix=STATICPIE +# RUN: llvm-readobj --dyn-syms %t | FileCheck %s # 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 11abd5351af9..fa6936e1ef39 100644 --- a/lld/test/ELF/weak-undef-no-dynamic-linker.s +++ b/lld/test/ELF/weak-undef-no-dynamic-linker.s @@ -1,12 +1,13 @@ # 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 --check-prefix=NO %s +# RUN: llvm-readobj --dyn-syms %t | FileCheck %s # RUN: ld.lld -pie --no-dynamic-linker %t.o -o %t # RUN: llvm-readobj --dyn-syms %t | FileCheck --check-prefix=NO %s -## With static PIE (whether or not --no-dynamic-linker is specified), don't -## emit undefined weak symbols to .dynsym . This suppresses relocations. +## With --no-dynamic-linker, don't emit undefined weak symbols to .dynsym . +## This will suppress a relocation. +# CHECK: Name: foo # 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 c5cf1bdcaba6..ec3e4ce73489 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=STATIC +# RUN: llvm-readelf -r --hex-dump=.data %t | FileCheck %s --check-prefix=NOPIC # RUN: ld.lld %t.o -o %t.pie -pie -# RUN: llvm-readelf -r --hex-dump=.data %t.pie | FileCheck %s --check-prefix=STATIC +# RUN: llvm-readobj -r %t.pie | FileCheck %s --check-prefix=PIC # 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 static linking and produce dynamic relocations -## for dynamic linking (-shared or at least one input DSO). +## We choose to resolve them statically for -no-pie and produce dynamic relocations +## for -pie and -shared. ## ## Note: Some ports of GNU ld support -z nodynamic-undefined-weak that we don't ## implement. -# STATIC: no relocations -# STATIC: Hex dump of section '.data': -# STATIC-NEXT: {{.*}} 00000000 00000000 . -# STATIC-EMPTY: +# NOPIC: no relocations +# NOPIC: Hex dump of section '.data': +# NOPIC-NEXT: {{.*}} 00000000 00000000 +# NOPIC-EMPTY: # PIC: .rela.dyn { # PIC-NEXT: R_X86_64_64 foobar 0x0