https://github.com/fzakaria updated https://github.com/llvm/llvm-project/pull/174508
>From 31795f8c7bb235ed2aebc625d97ca55ec108454a Mon Sep 17 00:00:00 2001 From: Farid Zakaria <[email protected]> Date: Thu, 8 Jan 2026 11:01:29 -0800 Subject: [PATCH 1/3] [lld] Support large encoding for FDE --- llvm/include/llvm/MC/MCTargetOptions.h | 4 ++++ llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h | 2 ++ llvm/lib/MC/MCObjectFileInfo.cpp | 13 +++++++++---- llvm/lib/MC/MCTargetOptions.cpp | 6 ++---- llvm/lib/MC/MCTargetOptionsCommandFlags.cpp | 9 +++++++++ 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h index 235d58d585b40..da62be369a43c 100644 --- a/llvm/include/llvm/MC/MCTargetOptions.h +++ b/llvm/include/llvm/MC/MCTargetOptions.h @@ -108,6 +108,10 @@ class MCTargetOptions { // Whether or not to use full register names on PowerPC. bool PPCUseFullRegisterNames : 1; + // Use 8-byte pointer size for ELF FDE CFI encoding, regardless of code model. + // Useful when text sections may exceed 2GB even with medium code model + bool LargeFDEEncoding : 1; + LLVM_ABI MCTargetOptions(); /// getABIName - If this returns a non-empty string this represents the diff --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h index 168131b43cca8..beba9f835afeb 100644 --- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -63,6 +63,8 @@ LLVM_ABI bool getX86RelaxRelocations(); LLVM_ABI bool getX86Sse2Avx(); +LLVM_ABI bool getLargeFDEEncoding(); + LLVM_ABI StringRef getABIName(); LLVM_ABI StringRef getAsSecureLogFile(); diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp index 5afe00eee2242..9667d17e63939 100644 --- a/llvm/lib/MC/MCObjectFileInfo.cpp +++ b/llvm/lib/MC/MCObjectFileInfo.cpp @@ -24,6 +24,7 @@ #include "llvm/MC/MCSectionSPIRV.h" #include "llvm/MC/MCSectionWasm.h" #include "llvm/MC/MCSectionXCOFF.h" +#include "llvm/MC/MCTargetOptions.h" #include "llvm/TargetParser/Triple.h" using namespace llvm; @@ -332,7 +333,6 @@ void MCObjectFileInfo::initMachOMCObjectFileInfo(const Triple &T) { TLSExtraDataSection = TLSTLVSection; } - void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { switch (T.getArch()) { case Triple::mips: @@ -354,10 +354,15 @@ void MCObjectFileInfo::initELFMCObjectFileInfo(const Triple &T, bool Large) { case Triple::ppc64le: case Triple::aarch64: case Triple::aarch64_be: - case Triple::x86_64: - FDECFIEncoding = dwarf::DW_EH_PE_pcrel | - (Large ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); + case Triple::x86_64: { + // Check if the user requested large FDE encoding via MCTargetOptions + const MCTargetOptions *TO = Ctx->getTargetOptions(); + bool Use8ByteFDE = Large || (TO && TO->LargeFDEEncoding); + FDECFIEncoding = + dwarf::DW_EH_PE_pcrel | + (Use8ByteFDE ? dwarf::DW_EH_PE_sdata8 : dwarf::DW_EH_PE_sdata4); break; + } case Triple::bpfel: case Triple::bpfeb: FDECFIEncoding = dwarf::DW_EH_PE_sdata8; diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp index be6d19d111620..ff3ce40a555ee 100644 --- a/llvm/lib/MC/MCTargetOptions.cpp +++ b/llvm/lib/MC/MCTargetOptions.cpp @@ -20,11 +20,9 @@ MCTargetOptions::MCTargetOptions() EmitDwarfUnwind(EmitDwarfUnwindType::Default), MCUseDwarfDirectory(DefaultDwarfDirectory), EmitCompactUnwindNonCanonical(false), EmitSFrameUnwind(false), - PPCUseFullRegisterNames(false) {} + PPCUseFullRegisterNames(false), LargeFDEEncoding(false) {} -StringRef MCTargetOptions::getABIName() const { - return ABIName; -} +StringRef MCTargetOptions::getABIName() const { return ABIName; } StringRef MCTargetOptions::getAssemblyLanguage() const { return AssemblyLanguage; diff --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp index 22494fa11eb2a..8ad5ac02cdaa6 100644 --- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp +++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp @@ -59,6 +59,7 @@ MCOPT(bool, Crel) MCOPT(bool, ImplicitMapSyms) MCOPT(bool, X86RelaxRelocations) MCOPT(bool, X86Sse2Avx) +MCOPT(bool, LargeFDEEncoding) MCSTROPT(ABIName) MCSTROPT(AsSecureLogFile) @@ -168,6 +169,13 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() { "instructions with VEX prefix")); MCBINDOPT(X86Sse2Avx); + static cl::opt<bool> LargeFDEEncoding( + "large-fde-encoding", + cl::desc("Use 8-byte pointer size for ELF FDE CFI encoding, useful " + "when text sections may exceed 2GB even with medium code"), + cl::init(false)); + MCBINDOPT(LargeFDEEncoding); + static cl::opt<std::string> ABIName( "target-abi", cl::desc("The name of the ABI to be targeted from the backend."), @@ -199,6 +207,7 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() { Options.ImplicitMapSyms = getImplicitMapSyms(); Options.X86RelaxRelocations = getX86RelaxRelocations(); Options.X86Sse2Avx = getX86Sse2Avx(); + Options.LargeFDEEncoding = getLargeFDEEncoding(); Options.EmitDwarfUnwind = getEmitDwarfUnwind(); Options.EmitCompactUnwindNonCanonical = getEmitCompactUnwindNonCanonical(); Options.EmitSFrameUnwind = getEmitSFrameUnwind(); >From 40a70b62aa63c5d791fe360a642737c8a787999d Mon Sep 17 00:00:00 2001 From: Farid Zakaria <[email protected]> Date: Thu, 8 Jan 2026 11:01:29 -0800 Subject: [PATCH 2/3] Expose large encoding option to clang --- clang/include/clang/Basic/CodeGenOptions.def | 3 +++ clang/include/clang/Options/Options.td | 5 +++++ clang/lib/CodeGen/BackendUtil.cpp | 1 + clang/lib/Driver/ToolChains/Clang.cpp | 3 +++ 4 files changed, 12 insertions(+) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index a6b1acdcf5ea9..d9a4ac4acb7a4 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -120,6 +120,9 @@ CODEGENOPT(StackSizeSection , 1, 0, Benign) ///< Set when -fstack-size-section ///< Set when -femit-compact-unwind-non-canonical is enabled. CODEGENOPT(EmitCompactUnwindNonCanonical, 1, 0, Benign) +///< Set when -flarge-fde-encoding is enabled. +CODEGENOPT(LargeFDEEncoding, 1, 0, Benign) + ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0, Benign) diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index f336542992993..4d5eaf5f71111 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -4791,6 +4791,11 @@ defm emit_compact_unwind_non_canonical : BoolFOption<"emit-compact-unwind-non-ca PosFlag<SetTrue, [], [ClangOption, CC1Option, CC1AsOption], "Try emitting Compact-Unwind for non-canonical entries. Maybe overridden by other constraints">, NegFlag<SetFalse>>; +defm large_fde_encoding : BoolFOption<"large-fde-encoding", + CodeGenOpts<"LargeFDEEncoding">, DefaultFalse, + PosFlag<SetTrue, [], [ClangOption, CC1Option, CC1AsOption], + "Use 8-byte pointers for ELF FDE CFI encoding. Useful when text sections may exceed 2GB">, + NegFlag<SetFalse>>; def g_Flag : Flag<["-"], "g">, Group<g_Group>, Visibility<[ClangOption, CLOption, DXCOption, FlangOption]>, HelpText<"Generate source-level debug information">; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 26794a9cbc11d..c11abd850e2a3 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -488,6 +488,7 @@ static bool initTargetOptions(const CompilerInstance &CI, Options.MCOptions.EmitDwarfUnwind = CodeGenOpts.getEmitDwarfUnwind(); Options.MCOptions.EmitCompactUnwindNonCanonical = CodeGenOpts.EmitCompactUnwindNonCanonical; + Options.MCOptions.LargeFDEEncoding = CodeGenOpts.LargeFDEEncoding; Options.MCOptions.MCRelaxAll = CodeGenOpts.RelaxAll; Options.MCOptions.MCSaveTempLabels = CodeGenOpts.SaveTempLabels; Options.MCOptions.MCUseDwarfDirectory = diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a0c98bcea85e6..b3c0856f693aa 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5640,6 +5640,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_merge_all_constants, false)) CmdArgs.push_back("-fmerge-all-constants"); + Args.addOptInFlag(CmdArgs, options::OPT_flarge_fde_encoding, + options::OPT_fno_large_fde_encoding); + Args.addOptOutFlag(CmdArgs, options::OPT_fdelete_null_pointer_checks, options::OPT_fno_delete_null_pointer_checks); >From d73ceb0c71635db641c12a2e63c39cd5d931876c Mon Sep 17 00:00:00 2001 From: Farid Zakaria <[email protected]> Date: Thu, 8 Jan 2026 11:01:29 -0800 Subject: [PATCH 3/3] Create test for large encoding of FDE --- clang/test/Driver/flarge-fde-encoding.c | 10 +++++ lld/test/ELF/eh-frame-large-fde-encoding.s | 45 ++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 clang/test/Driver/flarge-fde-encoding.c create mode 100644 lld/test/ELF/eh-frame-large-fde-encoding.s diff --git a/clang/test/Driver/flarge-fde-encoding.c b/clang/test/Driver/flarge-fde-encoding.c new file mode 100644 index 0000000000000..48742b8dce4ba --- /dev/null +++ b/clang/test/Driver/flarge-fde-encoding.c @@ -0,0 +1,10 @@ +// REQUIRES: x86-registered-target +// RUN: %clang -### -c --target=x86_64-linux-gnu -flarge-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=POS +// RUN: %clang -### -c --target=x86_64-linux-gnu -fno-large-fde-encoding %s 2>&1 | FileCheck %s --check-prefix=NEG +// RUN: %clang -### -c --target=x86_64-linux-gnu %s 2>&1 | FileCheck %s --check-prefix=DEFAULT + +// POS: "-flarge-fde-encoding" +// NEG-NOT: "-flarge-fde-encoding" +// DEFAULT-NOT: "-flarge-fde-encoding" + +int dummy; diff --git a/lld/test/ELF/eh-frame-large-fde-encoding.s b/lld/test/ELF/eh-frame-large-fde-encoding.s new file mode 100644 index 0000000000000..e374de8444e67 --- /dev/null +++ b/lld/test/ELF/eh-frame-large-fde-encoding.s @@ -0,0 +1,45 @@ +# REQUIRES: x86 + +## Test that demonstrates FDE encoding overflow when .eh_frame is placed +## far from .text, and the fix using 8-byte (sdata8) FDE encoding. +## +## With the default 4-byte FDE encoding (sdata4), a PC-relative offset +## to .text can overflow if .eh_frame is placed more than 2GB away. +## Using -large-fde-encoding (or mcmodel=large) switches to 8-byte +## FDE encoding which can address the full 64-bit address space. + +# RUN: rm -rf %t && split-file %s %t + +## Test 1: With default sdata4 encoding, placing .eh_frame far from .text +## causes an overflow error. +# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu --large-fde-encoding=false \ +# RUN: %t/test.s -o %t/test-small.o +# RUN: not ld.lld %t/test-small.o -T %t/far.lds -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=OVERFLOW + +## Test 2: With sdata8 encoding via -large-fde-encoding, no overflow. +# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -large-fde-encoding \ +# RUN: %t/test.s -o %t/test-large.o +# RUN: ld.lld %t/test-large.o -T %t/far.lds -o %t/out + +# OVERFLOW: ld.lld: error: <internal>:(.eh_frame+0x{{[0-9a-fA-F]+}}): relocation R_X86_64_PC32 out of range + +#--- test.s +.text +.globl _start +.type _start, @function +_start: + .cfi_startproc + ret + .cfi_endproc + +#--- far.lds +SECTIONS { + ## Place .text at a low address + . = 0x1000; + .text : { *(.text) } + + ## Place .eh_frame more than 2GB away to trigger overflow with sdata4 + . = 0x100001000; + .eh_frame : { *(.eh_frame) } +} _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
