[llvm] [MC] Make .note.GNU-stack explicit for the trampoline case (PR #151754)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 1 12:25:05 PDT 2025
https://github.com/ssijaric-nv created https://github.com/llvm/llvm-project/pull/151754
In the presence of trampolines, the .note.GNU-stack section is not emitted. The
absence of .note.GNU-stack results in the stack marked executable by some
linkers. But others require an explict .note.GNU-stack section.
The GNU ld 2.43 on x86 machines, for example, issues the following:
missing .note.GNU-stack section implies executable stack
NOTE: This behaviour is deprecated and will be removed in a future version of the linker
On one of the ARM machines, the absence of .note.GNU-stack results in the stack
marked as non-executable:
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
This change just emits the explicit .note.GNU-stack and marks it executable if required.
>From da46d525ff8c67888444992565edcdf8263c595a Mon Sep 17 00:00:00 2001
From: Sanjin Sijaric <ssijaric at nvidia.com>
Date: Mon, 30 Jun 2025 12:02:49 -0700
Subject: [PATCH] [MC] Make .note.GNU-stack explicit for the trampoline case
In the presence of trampolines, the .note.GNU-stack section is not emitted. The
absence of .note.GNU-stack results in the stack marked executable by some
linkers. But others require an explict .note.GNU-stack section.
The GNU ld 2.43 on x86 machines, for example, issues the following:
missing .note.GNU-stack section implies executable stack
NOTE: This behaviour is deprecated and will be removed in a future version of the linker
On one of the ARM machines, the absence of .note.GNU-stack results in the stack
marked as non-executable:
STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**4
filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw-
This change just emits the explicit .note.GNU-stack and marks it executable.
---
llvm/include/llvm/MC/MCAsmInfo.h | 6 ++++++
llvm/include/llvm/MC/MCAsmInfoELF.h | 1 +
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 8 ++++++--
llvm/lib/MC/MCAsmInfoELF.cpp | 7 +++++++
llvm/test/CodeGen/AArch64/trampoline.ll | 1 +
llvm/test/CodeGen/RISCV/rv64-trampoline.ll | 1 +
6 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index 6c12cd347901a..1e87ce23b158b 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -471,6 +471,12 @@ class LLVM_ABI MCAsmInfo {
return nullptr;
}
+ /// Targets can implement this method to specify a section to switch to if the
+ /// translation has trampolines that require an executable stack.
+ virtual MCSection *getExecutableStackSection(MCContext &Ctx) const {
+ return nullptr;
+ }
+
virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym,
unsigned Encoding,
MCStreamer &Streamer) const;
diff --git a/llvm/include/llvm/MC/MCAsmInfoELF.h b/llvm/include/llvm/MC/MCAsmInfoELF.h
index c05e4ad78ecd1..c5dff900227fd 100644
--- a/llvm/include/llvm/MC/MCAsmInfoELF.h
+++ b/llvm/include/llvm/MC/MCAsmInfoELF.h
@@ -16,6 +16,7 @@ namespace llvm {
class MCAsmInfoELF : public MCAsmInfo {
virtual void anchor();
MCSection *getNonexecutableStackSection(MCContext &Ctx) const final;
+ MCSection *getExecutableStackSection(MCContext &Ctx) const final;
void printSwitchToSection(const MCSection &, uint32_t, const Triple &,
raw_ostream &) const final;
bool useCodeAlign(const MCSection &Sec) const final;
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 1641c3eb535a9..cb697cd64d199 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2840,9 +2840,13 @@ bool AsmPrinter::doFinalization(Module &M) {
// If we don't have any trampolines, then we don't require stack memory
// to be executable. Some targets have a directive to declare this.
Function *InitTrampolineIntrinsic = M.getFunction("llvm.init.trampoline");
+ MCSection *S = nullptr;
if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
- if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
- OutStreamer->switchSection(S);
+ S = MAI->getNonexecutableStackSection(OutContext);
+ else
+ S = MAI->getExecutableStackSection(OutContext);
+ if (S)
+ OutStreamer->switchSection(S);
if (TM.Options.EmitAddrsig) {
// Emit address-significance attributes for all globals.
diff --git a/llvm/lib/MC/MCAsmInfoELF.cpp b/llvm/lib/MC/MCAsmInfoELF.cpp
index cdae9d7860f33..3d0271699d8de 100644
--- a/llvm/lib/MC/MCAsmInfoELF.cpp
+++ b/llvm/lib/MC/MCAsmInfoELF.cpp
@@ -35,6 +35,13 @@ MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const {
return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0);
}
+MCSection *MCAsmInfoELF::getExecutableStackSection(MCContext &Ctx) const {
+ MCSectionELF *section =
+ static_cast<MCSectionELF *>(getNonexecutableStackSection(Ctx));
+ section->setFlags(section->getFlags() | ELF::SHF_EXECINSTR);
+ return section;
+}
+
bool MCAsmInfoELF::useCodeAlign(const MCSection &Sec) const {
return static_cast<const MCSectionELF &>(Sec).getFlags() & ELF::SHF_EXECINSTR;
}
diff --git a/llvm/test/CodeGen/AArch64/trampoline.ll b/llvm/test/CodeGen/AArch64/trampoline.ll
index 0e682704afbf8..6689425bf5832 100644
--- a/llvm/test/CodeGen/AArch64/trampoline.ll
+++ b/llvm/test/CodeGen/AArch64/trampoline.ll
@@ -263,3 +263,4 @@ define i64 @func2() {
%fp = call ptr @llvm.adjust.trampoline(ptr @trampg)
ret i64 0
}
+; CHECK-LINUX: .section ".note.GNU-stack","x", at progbits
diff --git a/llvm/test/CodeGen/RISCV/rv64-trampoline.ll b/llvm/test/CodeGen/RISCV/rv64-trampoline.ll
index 34d46579518ea..69c905002032d 100644
--- a/llvm/test/CodeGen/RISCV/rv64-trampoline.ll
+++ b/llvm/test/CodeGen/RISCV/rv64-trampoline.ll
@@ -71,6 +71,7 @@ define i64 @test0(i64 %n, ptr %p) nounwind {
; RV64-LINUX-NEXT: ld ra, 56(sp) # 8-byte Folded Reload
; RV64-LINUX-NEXT: addi sp, sp, 64
; RV64-LINUX-NEXT: ret
+; RV64-LINUX: .section ".note.GNU-stack","x", at progbits
%alloca = alloca [32 x i8], align 8
call void @llvm.init.trampoline(ptr %alloca, ptr @f, ptr %p)
%tramp = call ptr @llvm.adjust.trampoline(ptr %alloca)
More information about the llvm-commits
mailing list