Skip to content

Conversation

pcc
Copy link
Contributor

@pcc pcc commented Jul 17, 2025

Use !elf_section_properties metadata to set the type and entry size to
the correct values, and set the preferred alignment to the entry size
to enable last jump table entry placement.

Created using spr 1.3.6-beta.1
@llvmbot
Copy link
Member

llvmbot commented Jul 17, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Peter Collingbourne (pcc)

Changes

TODO:

  • Update tests.

Full diff: https://github.com/llvm/llvm-project/pull/149261.diff

2 Files Affected:

  • (modified) compiler-rt/test/cfi/mfcall.cpp (+2-2)
  • (modified) llvm/lib/Transforms/IPO/LowerTypeTests.cpp (+21-9)
diff --git a/compiler-rt/test/cfi/mfcall.cpp b/compiler-rt/test/cfi/mfcall.cpp
index d4666df8d5333..f95251f5adb44 100644
--- a/compiler-rt/test/cfi/mfcall.cpp
+++ b/compiler-rt/test/cfi/mfcall.cpp
@@ -63,12 +63,12 @@ int main(int argc, char **argv) {
   switch (argv[1][0]) {
     case 'a':
       // A: runtime error: control flow integrity check for type 'int (S::*)()' failed during non-virtual pointer to member function call
-      // A: note: S::f1() defined here
+      // A: note: S::f1() {{.*}}defined here
       (s.*bitcast<S_int>(&S::f1))();
       break;
     case 'b':
       // B: runtime error: control flow integrity check for type 'int (T::*)()' failed during non-virtual pointer to member function call
-      // B: note: S::f2() defined here
+      // B: note: S::f2() {{.*}}defined here
       (t.*bitcast<T_int>(&S::f2))();
       break;
     case 'c':
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index 86e1ebf937dbe..8b21d81bc9678 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -30,6 +30,8 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/TypeMetadataUtils.h"
 #include "llvm/Analysis/ValueTracking.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Constant.h"
@@ -73,6 +75,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Triple.h"
 #include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/CrossDSOCFI.h"
 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <algorithm>
@@ -498,6 +501,10 @@ class LowerTypeTestsModule {
   GlobalVariable *GlobalAnnotation;
   DenseSet<Value *> FunctionAnnotations;
 
+  // Cross-DSO CFI emits jumptable entries for exported functions as well as
+  // address taken functions in case they are address taken in other modules.
+  bool CrossDsoCfi = M.getModuleFlag("Cross-DSO CFI") != nullptr;
+
   bool shouldExportConstantsAsAbsoluteSymbols();
   uint8_t *exportTypeId(StringRef TypeId, const TypeIdLowering &TIL);
   TypeIdLowering importTypeId(StringRef TypeId);
@@ -1527,10 +1534,19 @@ Triple::ArchType LowerTypeTestsModule::selectJumpTableArmEncoding(
 void LowerTypeTestsModule::createJumpTable(
     Function *F, ArrayRef<GlobalTypeMember *> Functions,
     Triple::ArchType JumpTableArch) {
-  std::string AsmStr, ConstraintStr;
-  raw_string_ostream AsmOS(AsmStr), ConstraintOS(ConstraintStr);
-  SmallVector<Value *, 16> AsmArgs;
-  AsmArgs.reserve(Functions.size() * 2);
+  unsigned JumpTableEntrySize = getJumpTableEntrySize(JumpTableArch);
+  // Give the jumptable section this type in order to enable jumptable
+  // relaxation. Only do this if cross-DSO CFI is disabled because jumptable
+  // relaxation violates cross-DSO CFI's restrictions on the ordering of the
+  // jumptable relative to other sections.
+  if (!CrossDsoCfi)
+    F->setMetadata(LLVMContext::MD_elf_section_properties,
+                   MDNode::get(F->getContext(),
+                               ArrayRef<Metadata *>{
+                                   ConstantAsMetadata::get(ConstantInt::get(
+                                       Int64Ty, ELF::SHT_LLVM_CFI_JUMP_TABLE)),
+                                   ConstantAsMetadata::get(ConstantInt::get(
+                                       Int64Ty, JumpTableEntrySize))}));
 
   BasicBlock *BB = BasicBlock::Create(M.getContext(), "entry", F);
   IRBuilder<> IRB(BB);
@@ -1552,7 +1568,7 @@ void LowerTypeTestsModule::createJumpTable(
   IRB.CreateUnreachable();
 
   // Align the whole table by entry size.
-  F->setAlignment(Align(getJumpTableEntrySize(JumpTableArch)));
+  F->setAlignment(Align(JumpTableEntrySize));
   // Skip prologue.
   // Disabled on win32 due to https://llvm.org/bugs/show_bug.cgi?id=28641#c3.
   // Luckily, this function does not get any prologue even without the
@@ -2119,10 +2135,6 @@ bool LowerTypeTestsModule::lower() {
   unsigned CurUniqueId = 0;
   SmallVector<MDNode *, 2> Types;
 
-  // Cross-DSO CFI emits jumptable entries for exported functions as well as
-  // address taken functions in case they are address taken in other modules.
-  const bool CrossDsoCfi = M.getModuleFlag("Cross-DSO CFI") != nullptr;
-
   struct ExportedFunctionInfo {
     CfiFunctionLinkage Linkage;
     MDNode *FuncMD; // {name, linkage, type[, type...]}

Created using spr 1.3.6-beta.1
@pcc pcc changed the title [WIP] LowerTypeTests: Start using !elf_section_properties metadata to mark CFI jump table sections. LowerTypeTests: Start using !elf_section_properties metadata to mark CFI jump table sections. Jul 18, 2025
pcc added 4 commits August 26, 2025 19:21
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
…ing overaligned

Created using spr 1.3.6-beta.1
@pcc pcc changed the title LowerTypeTests: Start using !elf_section_properties metadata to mark CFI jump table sections. LowerTypeTests: Mark CFI jump table sections as eligible for relaxation. Aug 28, 2025
pcc added 3 commits August 29, 2025 13:13
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
Created using spr 1.3.6-beta.1
@pcc
Copy link
Contributor Author

pcc commented Oct 6, 2025

Ping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants