https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/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. `initSections` has 20+ uses. The parameter cleanup will be deferred to a subsequent change. Fixes https://github.com/llvm/llvm-project/issues/186004 >From 679ac726c8deb258ff87b182101671f4b37eebf7 Mon Sep 17 00:00:00 2001 From: Fangrui Song <[email protected]> Date: Sat, 21 Mar 2026 12:05:18 -0700 Subject: [PATCH] [MC,clang] Fix -Wa,--noexecstack not emitting .note.GNU-stack 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. `initSections` has 20+ uses. The parameter cleanup will be deferred to a subsequent change. Fixes https://github.com/llvm/llvm-project/issues/186004 --- clang/test/Misc/noexecstack.c | 17 +++++++++++++++++ clang/tools/driver/cc1as_main.cpp | 1 + llvm/lib/MC/MCELFStreamer.cpp | 12 ++++++++---- llvm/test/MC/ELF/noexec.s | 17 ----------------- llvm/test/MC/ELF/noexecstack.s | 5 +++++ llvm/tools/llvm-mc/llvm-mc.cpp | 8 ++------ 6 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 clang/test/Misc/noexecstack.c delete mode 100644 llvm/test/MC/ELF/noexec.s create mode 100644 llvm/test/MC/ELF/noexecstack.s diff --git a/clang/test/Misc/noexecstack.c b/clang/test/Misc/noexecstack.c new file mode 100644 index 0000000000000..ced0f6bd4611c --- /dev/null +++ b/clang/test/Misc/noexecstack.c @@ -0,0 +1,17 @@ +// 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 + +// 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 + +// 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..d9b934dddc326 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,12 @@ void MCELFStreamer::finalizeCGProfile() { } void MCELFStreamer::finishImpl() { + // Emit .note.GNU-stack, similar to AsmPrinter::doFinalization. + if (const MCTargetOptions *TO = getContext().getTargetOptions()) + if (TO->MCNoExecStack) + switchSection(getContext().getAsmInfo()->getStackSection(getContext(), + /*Exec=*/false)); + // 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..43dc9b8d62c73 --- /dev/null +++ b/llvm/test/MC/ELF/noexecstack.s @@ -0,0 +1,5 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64 %s -no-exec-stack -o - | llvm-readelf -S - | FileCheck %s + +# 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 +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
