[llvm] b5e71d7 - Add section type to support CFI jump table relaxation.

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 18 10:48:45 PDT 2025


Author: Peter Collingbourne
Date: 2025-07-18T10:48:42-07:00
New Revision: b5e71d727b6624c160c9186b52d73bdb635770ed

URL: https://github.com/llvm/llvm-project/commit/b5e71d727b6624c160c9186b52d73bdb635770ed
DIFF: https://github.com/llvm/llvm-project/commit/b5e71d727b6624c160c9186b52d73bdb635770ed.diff

LOG: Add section type to support CFI jump table relaxation.

For context see main pull request: #147424.

Reviewers: MaskRay

Reviewed By: MaskRay

Pull Request: https://github.com/llvm/llvm-project/pull/149259

Added: 
    

Modified: 
    llvm/docs/Extensions.rst
    llvm/include/llvm/BinaryFormat/ELF.h
    llvm/lib/MC/MCParser/ELFAsmParser.cpp
    llvm/lib/MC/MCSectionELF.cpp
    llvm/lib/Object/ELF.cpp
    llvm/test/MC/AsmParser/llvm_section_types.s

Removed: 
    


################################################################################
diff  --git a/llvm/docs/Extensions.rst b/llvm/docs/Extensions.rst
index bad72c6ca8295..d8fb87b6998ad 100644
--- a/llvm/docs/Extensions.rst
+++ b/llvm/docs/Extensions.rst
@@ -581,6 +581,26 @@ This section stores pairs of (jump table address, number of entries).
 This information is useful for tools that need to statically reconstruct
 the control flow of executables.
 
+``SHT_LLVM_CFI_JUMP_TABLE`` Section (CFI jump table)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+This section contains the instructions that make up a `CFI jump table`_.
+It is expected to be ``SHF_ALLOC`` and may be laid out like a normal
+section. The ``SHT_LLVM_CFI_JUMP_TABLE`` section type gives the linker
+permission to modify the section in ways that would not normally be
+permitted, in order to optimize calls via the jump table.
+
+Each ``sh_entsize`` sized slice of a section of this type containing
+exactly one relocation may be considered to be a jump table entry
+that branches to the target of the relocation. This allows the linker
+to replace the jump table entry with the function body if it is small
+enough, or if the function is the last function in the jump table.
+
+A section of this type does not have to be placed according to its
+name. The linker may place the section in whichever output section it
+sees fit (generally the section that would provide the best locality).
+
+.. _CFI jump table: https://clang.llvm.org/docs/ControlFlowIntegrityDesign.html#forward-edge-cfi-for-indirect-function-calls
+
 CodeView-Dependent
 ------------------
 

diff  --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h
index 6bf2e177b5d40..e4f82ad96a084 100644
--- a/llvm/include/llvm/BinaryFormat/ELF.h
+++ b/llvm/include/llvm/BinaryFormat/ELF.h
@@ -1159,6 +1159,7 @@ enum : unsigned {
   SHT_LLVM_OFFLOADING = 0x6fff4c0b,         // LLVM device offloading data.
   SHT_LLVM_LTO = 0x6fff4c0c,                // .llvm.lto for fat LTO.
   SHT_LLVM_JT_SIZES = 0x6fff4c0d,           // LLVM jump tables sizes.
+  SHT_LLVM_CFI_JUMP_TABLE = 0x6fff4c0e,     // LLVM CFI jump table.
   // Android's experimental support for SHT_RELR sections.
   // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512
   SHT_ANDROID_RELR = 0x6fffff00,   // Relocation entries; only offsets.

diff  --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index ec8b40261a6ca..c7c3df330fc94 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -571,7 +571,7 @@ bool ELFAsmParser::parseSectionArguments(bool IsPush, SMLoc loc) {
         return TokError("expected end of directive");
     }
 
-    if (Mergeable)
+    if (Mergeable || TypeName == "llvm_cfi_jump_table")
       if (parseMergeSize(Size))
         return true;
     if (Flags & ELF::SHF_LINK_ORDER)
@@ -637,6 +637,8 @@ bool ELFAsmParser::parseSectionArguments(bool IsPush, SMLoc loc) {
       Type = ELF::SHT_LLVM_LTO;
     else if (TypeName == "llvm_jt_sizes")
       Type = ELF::SHT_LLVM_JT_SIZES;
+    else if (TypeName == "llvm_cfi_jump_table")
+      Type = ELF::SHT_LLVM_CFI_JUMP_TABLE;
     else if (TypeName.getAsInteger(0, Type))
       return TokError("unknown section type");
   }

diff  --git a/llvm/lib/MC/MCSectionELF.cpp b/llvm/lib/MC/MCSectionELF.cpp
index cc7cdf2fe4d1a..299fe40706e3a 100644
--- a/llvm/lib/MC/MCSectionELF.cpp
+++ b/llvm/lib/MC/MCSectionELF.cpp
@@ -176,11 +176,13 @@ void MCSectionELF::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     OS << "llvm_lto";
   else if (Type == ELF::SHT_LLVM_JT_SIZES)
     OS << "llvm_jt_sizes";
+  else if (Type == ELF::SHT_LLVM_CFI_JUMP_TABLE)
+    OS << "llvm_cfi_jump_table";
   else
     OS << "0x" << Twine::utohexstr(Type);
 
   if (EntrySize) {
-    assert(Flags & ELF::SHF_MERGE);
+    assert((Flags & ELF::SHF_MERGE) || Type == ELF::SHT_LLVM_CFI_JUMP_TABLE);
     OS << "," << EntrySize;
   }
 

diff  --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index af073f6a1a917..788c6020a7f99 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -321,6 +321,7 @@ StringRef llvm::object::getELFSectionTypeName(uint32_t Machine, unsigned Type) {
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_OFFLOADING);
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LTO);
     STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_JT_SIZES)
+    STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CFI_JUMP_TABLE)
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_SFRAME);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
     STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);

diff  --git a/llvm/test/MC/AsmParser/llvm_section_types.s b/llvm/test/MC/AsmParser/llvm_section_types.s
index 147b1499d2b88..83e5db0256647 100644
--- a/llvm/test/MC/AsmParser/llvm_section_types.s
+++ b/llvm/test/MC/AsmParser/llvm_section_types.s
@@ -1,22 +1,34 @@
-## Verify that LLVM-specific section types are correctly inferred from assembly input.
+## Verify that LLVM-specific section types are correctly inferred from assembly input and printed.
+# RUN: llvm-mc -triple i386-pc-linux %s | FileCheck --check-prefix=ASM %s
 # RUN: llvm-mc -triple i386-pc-linux -filetype=obj -o %t %s
 # RUN: llvm-readobj -S %t | FileCheck %s
+# ASM: .section    .section1,"", at llvm_bb_addr_map
 .section    .section1,"", at llvm_bb_addr_map
 .byte 1
+# ASM: .section    .section2,"", at llvm_call_graph_profile
 .section    .section2,"", at llvm_call_graph_profile
 .byte 1
+# ASM: .section    .section3,"", at llvm_odrtab
 .section    .section3,"", at llvm_odrtab
 .byte 1
+# ASM: .section    .section4,"", at llvm_linker_options
 .section    .section4,"", at llvm_linker_options
 .byte 1
+# ASM: .section    .section5,"", at llvm_sympart
 .section    .section5,"", at llvm_sympart
 .byte 1
+# ASM: .section    .section6,"", at llvm_dependent_libraries
 .section    .section6,"", at llvm_dependent_libraries
 .byte 1
+# ASM: .section    .section7,"", at llvm_offloading
 .section    .section7,"", at llvm_offloading
 .byte 1
+# ASM: .section    .section8,"", at llvm_lto
 .section    .section8,"", at llvm_lto
 .byte 1
+# ASM: .section    .section9,"", at llvm_cfi_jump_table,1
+.section    .section9,"", at llvm_cfi_jump_table,1
+.byte 1
 
 # CHECK:        Name: .section1
 # CHECK-NEXT:   Type: SHT_LLVM_BB_ADDR_MAP
@@ -34,3 +46,6 @@
 # CHECK-NEXT:   Type: SHT_LLVM_OFFLOADING
 # CHECK:        Name: .section8
 # CHECK-NEXT:   Type: SHT_LLVM_LTO
+# CHECK:        Name: .section9
+# CHECK-NEXT:   Type: SHT_LLVM_CFI_JUMP_TABLE
+# CHECK:        EntrySize: 1


        


More information about the llvm-commits mailing list