[llvm] [MC] Explicitly request executable stacks (PR #93478)

Roger Ferrer Ibáñez via llvm-commits llvm-commits at lists.llvm.org
Mon May 27 06:54:28 PDT 2024


https://github.com/rofirrim created https://github.com/llvm/llvm-project/pull/93478

We are working on Fortran applications and some of them rely on passing a pointer to an internal (aka nested) function that uses the enclosing context (e.g., a variable of the enclosing function). [Flang uses trampolines](https://flang.llvm.org/docs/InternalProcedureTrampolines.html) which rely on `llvm.init.trampoline` and `llvm.adjust.trampoline`. Those rely on having an executable stack.

This change is a preliminary step to support trampolines on RISC-V.

According to GNU ld's manual

> If an input file does not have a .note.GNU-stack section present then
> the default behaviour is target specific.

We currently disable explicit stacks by default. But when we do need them, we instead rely on the default of them being enabled. This is not true for all the architectures. In special for RISC-V where executable stacks are disabled by default.

This changes to always emit the note.GNU-stack section.

The updated test belongs to X86 because at this point RISC-V still does not support trampolines. This will come in a later change.

>From b05ea625459fdd3f39e407c76c460e973ede6222 Mon Sep 17 00:00:00 2001
From: Roger Ferrer Ibanez <roger.ferrer at bsc.es>
Date: Mon, 27 May 2024 09:22:37 +0000
Subject: [PATCH] [MC] Explicitly request executable stacks

According to GNU ld's manual

> If an input file does not have a .note.GNU-stack section present then
> the default behaviour is target specific.

We currently disable explicit stacks by default. But when we do need
them we rely on the default of them being enabled. This is not true for
all the architectures. In special for RISC-V where executable stacks are
disabled by default.

This changes to always emit the note.GNU-stack section.

The updated test belongs to X86 because at this point RISC-V still does
not support trampolines. This will come in a later patch.
---
 llvm/include/llvm/MC/MCAsmInfo.h               |  7 +++++++
 llvm/include/llvm/MC/MCAsmInfoELF.h            |  1 +
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp     |  8 +++++++-
 llvm/lib/MC/MCAsmInfoELF.cpp                   | 10 ++++++++++
 llvm/test/CodeGen/X86/2011-08-23-Trampoline.ll |  2 ++
 5 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index f9dd6012d5e94..46ba5c4394c71 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -580,6 +580,13 @@ class MCAsmInfo {
     return nullptr;
   }
 
+  /// Targets can implement this method to specify a section to switch to if
+  /// the translation unit does have trampolines that require an executable
+  /// stack.
+  virtual MCSection *getExecutableStackSection(MCContext &Ctx) const {
+    return nullptr;
+  }
+
   /// True if the section is atomized using the symbols in it.
   /// This is false if the section is not atomized at all (most ELF sections) or
   /// if it is atomized based on its contents (MachO' __TEXT,__cstring for
diff --git a/llvm/include/llvm/MC/MCAsmInfoELF.h b/llvm/include/llvm/MC/MCAsmInfoELF.h
index 408d4df76412e..2cfaf75a6facc 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;
 
 protected:
   MCAsmInfoELF();
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index c5755b9bdc8d0..19ebb8462a197 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2532,9 +2532,15 @@ 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");
-  if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty())
+  if (!InitTrampolineIntrinsic || InitTrampolineIntrinsic->use_empty()) {
     if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
       OutStreamer->switchSection(S);
+  } else {
+    // This is platform dependent, so we better explicitly request an executable
+    // stack.
+    if (MCSection *S = MAI->getExecutableStackSection(OutContext))
+      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 7eb89ef6a02b7..860cffb9302dc 100644
--- a/llvm/lib/MC/MCAsmInfoELF.cpp
+++ b/llvm/lib/MC/MCAsmInfoELF.cpp
@@ -28,6 +28,16 @@ MCSection *MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const {
   return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0);
 }
 
+// We use this to effectively force an executable stack
+MCSection *MCAsmInfoELF::getExecutableStackSection(MCContext &Ctx) const {
+  // Solaris doesn't know/doesn't care about .note.GNU-stack sections, so
+  // don't emit them.
+  if (Ctx.getTargetTriple().isOSSolaris())
+    return nullptr;
+  return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS,
+                           ELF::SHF_EXECINSTR);
+}
+
 MCAsmInfoELF::MCAsmInfoELF() {
   HasIdentDirective = true;
   WeakRefDirective = "\t.weak\t";
diff --git a/llvm/test/CodeGen/X86/2011-08-23-Trampoline.ll b/llvm/test/CodeGen/X86/2011-08-23-Trampoline.ll
index b314e5f8452d8..977ee334d2b96 100644
--- a/llvm/test/CodeGen/X86/2011-08-23-Trampoline.ll
+++ b/llvm/test/CodeGen/X86/2011-08-23-Trampoline.ll
@@ -14,3 +14,5 @@ declare void @gnat__perfect_hash_generators__select_char_position__build_identic
 
 declare void @llvm.init.trampoline(ptr, ptr, ptr) nounwind 
 declare ptr @llvm.adjust.trampoline(ptr) nounwind 
+
+; CHECK: .section ".note.GNU-stack","x", at progbits



More information about the llvm-commits mailing list