Author: Fangrui Song Date: 2026-03-22T16:58:31Z New Revision: 34bc5d580b73c0ca79653bb03e5c50419be2c634
URL: https://github.com/llvm/llvm-project/commit/34bc5d580b73c0ca79653bb03e5c50419be2c634 DIFF: https://github.com/llvm/llvm-project/commit/34bc5d580b73c0ca79653bb03e5c50419be2c634.diff LOG: [MC,clang] Fix -Wa,--noexecstack not emitting .note.GNU-stack (#187880) AsmPrinter (clang -c a.c) and AsmParser (clang -c a.s, llvm-mc -filetype=obj a.s) have different ways to emit .note.GNU-stack section. 913c5b4d1fff removed a redundant initSections call from cc1as, but that was the only place where NoExecStack was consumed for the assembler path. Unify the .note.GNU-stack emission in MCELFStreamer::finishImpl, making the `initSections` parameter redundant. Add a -filetype=obj test for Solaris (see https://reviews.llvm.org/D159179), which doesn't use .note.GNU-stack `initSections` has 20+ uses. The parameter cleanup will be deferred to a subsequent change. Fixes https://github.com/llvm/llvm-project/issues/186004 Added: clang/test/Misc/noexecstack.c llvm/test/MC/ELF/noexecstack.s Modified: clang/tools/driver/cc1as_main.cpp llvm/lib/MC/MCELFStreamer.cpp llvm/tools/llvm-mc/llvm-mc.cpp Removed: llvm/test/MC/ELF/noexec.s ################################################################################ diff --git a/clang/test/Misc/noexecstack.c b/clang/test/Misc/noexecstack.c new file mode 100644 index 0000000000000..1af0c76d0207e --- /dev/null +++ b/clang/test/Misc/noexecstack.c @@ -0,0 +1,22 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -cc1 -triple x86_64 %s -emit-obj -o %t.o -mnoexecstack +// RUN: llvm-readelf -S %t.o | FileCheck %s + +// RUN: %clang -cc1 -triple x86_64 %s -S -o %t.s +// RUN: FileCheck --check-prefix=ASM %s < %t.s +// RUN: %clang -cc1as -triple x86_64 %t.s -filetype obj -mnoexecstack -o %t.o +// RUN: llvm-readelf -S %t.o | FileCheck %s +/// Without -mnoexecstack on a .s that lacks .note.GNU-stack, the section should be absent. +// RUN: echo "nop" | %clang -cc1as -triple x86_64 - -filetype obj -o %t.o +// RUN: llvm-readelf -S %t.o | FileCheck --check-prefix=NOSTACK %s + +// CHECK: .text PROGBITS 0000000000000000 {{[0-9a-f]+}} 000001 00 AX 0 0 16 +// CHECK: .note.GNU-stack PROGBITS 0000000000000000 {{[0-9a-f]+}} 000000 00 0 0 1 + +// NOSTACK-NOT: .note.GNU-stack + +// ASM: .text +// ASM: .section ".note.GNU-stack","",@progbits +// ASM-NOT: ".note.GNU-stack" + +void f() {} diff --git a/clang/tools/driver/cc1as_main.cpp b/clang/tools/driver/cc1as_main.cpp index c6cdd46a41f37..d6911e46b57e1 100644 --- a/clang/tools/driver/cc1as_main.cpp +++ b/clang/tools/driver/cc1as_main.cpp @@ -473,6 +473,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, MCOptions.ImplicitMapSyms = Opts.ImplicitMapsyms; MCOptions.X86RelaxRelocations = Opts.X86RelaxRelocations; MCOptions.X86Sse2Avx = Opts.X86Sse2Avx; + MCOptions.MCNoExecStack = Opts.NoExecStack; MCOptions.CompressDebugSections = Opts.CompressDebugSections; MCOptions.AsSecureLogFile = Opts.AsSecureLogFile; diff --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp index ac5568f00df48..2adb8901d69df 100644 --- a/llvm/lib/MC/MCELFStreamer.cpp +++ b/llvm/lib/MC/MCELFStreamer.cpp @@ -29,6 +29,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" @@ -48,14 +49,11 @@ ELFObjectWriter &MCELFStreamer::getWriter() { return static_cast<ELFObjectWriter &>(getAssembler().getWriter()); } -void MCELFStreamer::initSections(bool NoExecStack, const MCSubtargetInfo &STI) { +void MCELFStreamer::initSections(bool, const MCSubtargetInfo &STI) { MCContext &Ctx = getContext(); switchSection(Ctx.getObjectFileInfo()->getTextSection()); emitCodeAlignment(Align(Ctx.getObjectFileInfo()->getTextSectionAlignment()), &STI); - - if (NoExecStack) - switchSection(Ctx.getAsmInfo()->getStackSection(Ctx, /*Exec=*/false)); } void MCELFStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { @@ -359,6 +357,15 @@ void MCELFStreamer::finalizeCGProfile() { } void MCELFStreamer::finishImpl() { + // Emit .note.GNU-stack, similar to AsmPrinter::doFinalization. + MCContext &Ctx = getContext(); + if (const MCTargetOptions *TO = Ctx.getTargetOptions()) { + auto *StackSec = Ctx.getAsmInfo()->getStackSection(Ctx, + /*Exec=*/false); + if (StackSec && TO->MCNoExecStack) + switchSection(StackSec); + } + // Emit the .gnu attributes section if any attributes have been added. if (!GNUAttributes.empty()) { MCSection *DummyAttributeSection = nullptr; diff --git a/llvm/test/MC/ELF/noexec.s b/llvm/test/MC/ELF/noexec.s deleted file mode 100644 index a9ae5b24b4291..0000000000000 --- a/llvm/test/MC/ELF/noexec.s +++ /dev/null @@ -1,17 +0,0 @@ -// RUN: llvm-mc -no-exec-stack -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -S - | FileCheck %s - -// CHECK: Section { -// CHECK: Index: -// CHECK: Name: .note.GNU-stack -// CHECK-NEXT: Type: SHT_PROGBITS -// CHECK-NEXT: Flags [ -// CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x40 -// CHECK-NEXT: Size: 0 -// CHECK-NEXT: Link: 0 -// CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 1 -// CHECK-NEXT: EntrySize: 0 -// CHECK-NEXT: } -nop diff --git a/llvm/test/MC/ELF/noexecstack.s b/llvm/test/MC/ELF/noexecstack.s new file mode 100644 index 0000000000000..08fecb7bec780 --- /dev/null +++ b/llvm/test/MC/ELF/noexecstack.s @@ -0,0 +1,11 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64 %s -no-exec-stack | llvm-readelf -S - | FileCheck %s +# RUN: llvm-mc -filetype=obj -triple x86_64 %s | llvm-readelf -S - | FileCheck %s --check-prefix=NOSTACK + +## Solaris doesn't use .note.GNU-stack at all. +# RUN: llvm-mc -filetype=obj -triple x86_64-solaris %s | llvm-readelf -S - | FileCheck %s --check-prefix=NOSTACK + +# CHECK: .text PROGBITS 0000000000000000 {{[0-9a-f]+}} 000001 00 AX 0 0 4 +# CHECK: .note.GNU-stack PROGBITS 0000000000000000 {{[0-9a-f]+}} 000000 00 0 0 1 + +# NOSTACK-NOT: .note.GNU-stack +nop diff --git a/llvm/tools/llvm-mc/llvm-mc.cpp b/llvm/tools/llvm-mc/llvm-mc.cpp index be5d524886978..3763ce0ea974c 100644 --- a/llvm/tools/llvm-mc/llvm-mc.cpp +++ b/llvm/tools/llvm-mc/llvm-mc.cpp @@ -410,6 +410,7 @@ int main(int argc, char **argv) { MCOptions.CompressDebugSections = CompressDebugSections.getValue(); MCOptions.ShowMCInst = ShowInst; MCOptions.AsmVerbose = true; + MCOptions.MCNoExecStack = NoExecStack; MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory; MCOptions.InstPrinterOptions = InstPrinterOptions; @@ -631,10 +632,8 @@ int main(int argc, char **argv) { std::move(CE), std::move(MAB))); Triple T(TripleName); - if (T.isLFI()) { - Str->initSections(NoExecStack, *STI); + if (T.isLFI()) initializeLFIMCStreamer(*Str.get(), Ctx, T); - } } else if (FileType == OFT_Null) { Str.reset(TheTarget->createNullStreamer(Ctx)); } else { @@ -652,9 +651,6 @@ int main(int argc, char **argv) { DwoOut ? MAB->createDwoObjectWriter(*OS, DwoOut->os()) : MAB->createObjectWriter(*OS), std::unique_ptr<MCCodeEmitter>(CE), *STI)); - if (NoExecStack) - Str->switchSection( - Ctx.getAsmInfo()->getStackSection(Ctx, /*Exec=*/false)); Str->emitVersionForTarget(TheTriple, VersionTuple(), nullptr, VersionTuple()); } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
