Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
99f06f2
[LFI] [AArch64] Add aarch64_lfi architecture
zyedidia Aug 18, 2025
08019fe
[LFI] Add LFILinux Clang toolchain
zyedidia Aug 19, 2025
cb92ceb
[LFI] [AArch64] Machinery for LFI MC rewriter
zyedidia Aug 19, 2025
8c37241
[LFI] Apply LFI rewriter to .s files in clang cc1as/llvm-mc
zyedidia Aug 19, 2025
6f62734
[LFI] [AArch64] LFI rewrites for indirect branches
zyedidia Aug 19, 2025
5151a9a
[LFI] [AArch64] Rewrites for stack manipulation and returns
zyedidia Aug 19, 2025
003d56d
[LFI] [AArch64] Rewrites for syscalls and TLS
zyedidia Aug 20, 2025
a3c0161
[LFI] [AArch64] Use .scratch register if available
zyedidia Aug 20, 2025
006dfb6
[LFI] [AArch64] Rewrites for LR modifications
zyedidia Aug 20, 2025
5e4cc70
[LFI] [AArch64] Rewrites for loads/stores
zyedidia Aug 20, 2025
309c571
[LFI] [AArch64] Rewrites for basic pre/post indexed load/stores
zyedidia Aug 20, 2025
905fd5a
[LFI] [AArch64] Assertion fixes for MRS/MSR
zyedidia Aug 21, 2025
2b4b00b
[LFI] [Compiler-RT] Update CMake for aarch64_lfi support
zyedidia Aug 21, 2025
c76e3b3
[LFI] Add .no_expand/.expand directives
zyedidia Aug 21, 2025
2844130
[LFI] Make sure rewriter is enabled by default
zyedidia Aug 21, 2025
0c514ef
[LFI] [Compiler-RT] Disable use of LFI reserved regs
zyedidia Aug 21, 2025
91c1f45
[LFI] [AArch64] Delete uses of reserved regs by default
zyedidia Aug 21, 2025
455ddb4
[LFI] Switch to +lfi-stores and +lfi-jumps feature
zyedidia Aug 21, 2025
d4933b4
[LFI] [AArch64] Add +lfi-tls-reg feature
zyedidia Aug 22, 2025
684253e
[LFI] [AArch64] Handle special case pre/post index
zyedidia Aug 22, 2025
fac255b
[LFI] Remove unnecessary auto-sandboxing flag
zyedidia Aug 23, 2025
5e3ae1d
[LFI] Apply clang-format to new files
zyedidia Aug 23, 2025
7a00571
[LFI] [AArch64] Add rewrites for LSE atomics
zyedidia Aug 24, 2025
bdbb526
[LFI] [X86] Add x86-64 LFI target
zyedidia Sep 11, 2025
1cf1f41
[LFI] [X86] Reserve registers and align blocks
zyedidia Sep 11, 2025
3112dfc
[LFI] [X86] Add stub X86MCLFIExpander
zyedidia Sep 11, 2025
1875187
[LFI] [X86] Enable 32-byte bundling
zyedidia Sep 11, 2025
81fedaf
[LFI] [X86] Add rewrites for control flow
zyedidia Sep 11, 2025
1d6f601
[LFI] [X86] Add string instruction rewrites
zyedidia Sep 11, 2025
7a8c889
[LFI] [X86] Add rewrites for stack modifications
zyedidia Sep 11, 2025
e7f6de0
[LFI] [X86] Rewrites for system calls
zyedidia Sep 12, 2025
5a02be8
[LFI] [X86] Rewrites for TLS reads
zyedidia Sep 12, 2025
b18dda4
[LFI] [X86] Autoformat
zyedidia Sep 12, 2025
5268301
[LFI] [X86] Rewrites for loads/stores
zyedidia Sep 12, 2025
9cb11c5
[LFI] [X86] Fixes for TLS rewrites
zyedidia Sep 12, 2025
935badf
[LFI] [X86] Disable TCO with more than 6 args
zyedidia Sep 15, 2025
8f00794
[LFI] [X86] Updates for building runtime libraries
zyedidia Sep 15, 2025
aa32def
[LFI] [X86] Disable TCO only for vararg 6-arg functions
zyedidia Sep 18, 2025
7b37660
[LFI] [X86] Warn or error for reserved register modification
zyedidia Sep 22, 2025
a09000f
[LFI] [X86] Add support for +lfi-stores and +lfi-jumps
zyedidia Sep 25, 2025
3458f34
[LFI] [AArch64] Don't expand stack mod for +lfi-jumps
zyedidia Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,10 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__aarch64__");
}

if (getTriple().isAArch64LFI()) {
Builder.defineMacro("__LFI__");
}

// Inline assembly supports AArch64 flag outputs.
Builder.defineMacro("__GCC_ASM_FLAG_OUTPUTS__");

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,10 @@ void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
DefineStd(Builder, "i386", Opts);
}

if (getTriple().isX8664LFI()) {
Builder.defineMacro("__LFI__");
}

Builder.defineMacro("__SEG_GS");
Builder.defineMacro("__SEG_FS");
Builder.defineMacro("__seg_gs", "__attribute__((address_space(256)))");
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ add_clang_library(clangDriver
ToolChains/Hexagon.cpp
ToolChains/HLSL.cpp
ToolChains/Hurd.cpp
ToolChains/LFILinux.cpp
ToolChains/Linux.cpp
ToolChains/MipsLinux.cpp
ToolChains/MinGW.cpp
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "ToolChains/Haiku.h"
#include "ToolChains/Hexagon.h"
#include "ToolChains/Hurd.h"
#include "ToolChains/LFILinux.h"
#include "ToolChains/Lanai.h"
#include "ToolChains/Linux.h"
#include "ToolChains/MSP430.h"
Expand Down Expand Up @@ -6654,6 +6655,8 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = std::make_unique<toolchains::VEToolChain>(*this, Target, Args);
else if (Target.isOHOSFamily())
TC = std::make_unique<toolchains::OHOS>(*this, Target, Args);
else if (Target.isLFI())
TC = std::make_unique<toolchains::LFILinuxToolChain>(*this, Target, Args);
else
TC = std::make_unique<toolchains::Linux>(*this, Target, Args);
break;
Expand Down
29 changes: 29 additions & 0 deletions clang/lib/Driver/ToolChains/LFILinux.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- LFILinux.cpp - LFI ToolChain Implementations ------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "LFILinux.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Options.h"

using namespace clang::driver::toolchains;
using namespace llvm::opt;

void LFILinuxToolChain::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
break;
}
}
35 changes: 35 additions & 0 deletions clang/lib/Driver/ToolChains/LFILinux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===--- LFILinux.h - LFI ToolChain Implementations -------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H

#include "Linux.h"

namespace clang {
namespace driver {
namespace toolchains {

class LLVM_LIBRARY_VISIBILITY LFILinuxToolChain : public Linux {
public:
LFILinuxToolChain(const Driver &D, const llvm::Triple &Triple,
const llvm::opt::ArgList &Args)
: Linux(D, Triple, Args) {
ExtraOpts.push_back("-z");
ExtraOpts.push_back("separate-code");
}

void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
};

} // end namespace toolchains
} // end namespace driver
} // end namespace clang

#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_LFI_LINUX_H
3 changes: 3 additions & 0 deletions clang/tools/driver/cc1as_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCLFI.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
Expand Down Expand Up @@ -577,6 +578,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
Str.reset(TheTarget->createMCObjectStreamer(
T, Ctx, std::move(MAB), std::move(OW), std::move(CE), *STI));
Str.get()->initSections(Opts.NoExecStack, *STI);
if (T.isLFI())
initializeLFIMCStreamer(*Str.get(), Ctx, T);
if (T.isOSBinFormatMachO() && T.isOSDarwin()) {
Triple *TVT = Opts.DarwinTargetVariantTriple
? &*Opts.DarwinTargetVariantTriple
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
set(ARM64 aarch64)
set(ARM64 aarch64 aarch64_lfi)
set(ARM32 arm armhf)
set(HEXAGON hexagon)
set(X86 i386)
set(X86_64 x86_64)
set(X86_64 x86_64 x86_64_lfi)
set(LOONGARCH64 loongarch64)
set(MIPS32 mips mipsel)
set(MIPS64 mips64 mips64el)
Expand Down
4 changes: 2 additions & 2 deletions compiler-rt/cmake/builtin-config-ix.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ else()
endif()

set(AMDGPU amdgcn)
set(ARM64 aarch64)
set(ARM64 aarch64 aarch64_lfi)
set(ARM32 arm armhf armv4t armv5te armv6 armv6m armv7m armv7em armv7 armv7s armv7k armv8m.base armv8m.main armv8.1m.main)
set(AVR avr)
set(HEXAGON hexagon)
set(X86 i386)
set(X86_64 x86_64)
set(X86_64 x86_64 x86_64_lfi)
set(LOONGARCH64 loongarch64)
set(MIPS32 mips mipsel)
set(MIPS64 mips64 mips64el)
Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/lib/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,8 @@ endif()

set(amdgcn_SOURCES ${GENERIC_SOURCES})

set(x86_64_lfi_SOURCES ${x86_64_SOURCES})

set(armv4t_SOURCES ${arm_min_SOURCES})
set(armv5te_SOURCES ${arm_min_SOURCES})
set(armv6_SOURCES ${arm_min_SOURCES})
Expand All @@ -649,6 +651,7 @@ set(armv7k_SOURCES ${arm_SOURCES})
set(arm64_SOURCES ${aarch64_SOURCES})
set(arm64e_SOURCES ${aarch64_SOURCES})
set(arm64_32_SOURCES ${aarch64_SOURCES})
set(aarch64_lfi_SOURCES ${aarch64_SOURCES})

# macho_embedded archs
set(armv6m_SOURCES ${thumb1_SOURCES})
Expand Down
4 changes: 4 additions & 0 deletions compiler-rt/lib/hwasan/hwasan_interceptors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,9 @@ InternalLongjmp(__hw_register_buf env, int retval) {
"ldp x21, x22, [%0, #2<<3];"
"ldp x23, x24, [%0, #4<<3];"
"ldp x25, x26, [%0, #6<<3];"
#ifndef __LFI__
"ldp x27, x28, [%0, #8<<3];"
#endif
"ldp x29, x30, [%0, #10<<3];"
"ldp d8, d9, [%0, #14<<3];"
"ldp d10, d11, [%0, #16<<3];"
Expand All @@ -407,7 +409,9 @@ InternalLongjmp(__hw_register_buf env, int retval) {
"mov (1*8)(%0),%%rbp;"
"mov (2*8)(%0),%%r12;"
"mov (3*8)(%0),%%r13;"
#ifndef __LFI__
"mov (4*8)(%0),%%r14;"
#endif
"mov (5*8)(%0),%%r15;"
"mov (6*8)(%0),%%rsp;"
"mov (7*8)(%0),%%rdx;"
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/orc/sysv_reenter.x86-64.S
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ __orc_rt_sysv_reenter:
movq %rax, 8(%rbp)
fxrstor64 (%rsp)
movq -112(%rbp), %r15
#ifndef __LFI__
movq -104(%rbp), %r14
#endif
movq -96(%rbp), %r13
movq -88(%rbp), %r12
movq -80(%rbp), %r11
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/xray/xray_trampoline_x86_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@
movq 32(%rsp), %r11
movq 24(%rsp), %r12
movq 16(%rsp), %r13
#ifndef __LFI__
movq 8(%rsp), %r14
#endif
movq 0(%rsp), %r15
addq $240, %rsp
CFI_ADJUST_CFA_OFFSET(-240)
Expand Down
7 changes: 7 additions & 0 deletions libunwind/src/UnwindRegistersRestore.S
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_x86_64_jumpto)
movq 88(%rdi), %r11
movq 96(%rdi), %r12
movq 104(%rdi), %r13
#ifndef __LFI__
movq 112(%rdi), %r14
#endif
movq 120(%rdi), %r15
# skip rflags
# skip cs
Expand Down Expand Up @@ -655,8 +657,13 @@ DEFINE_LIBUNWIND_FUNCTION(__libunwind_Registers_arm64_jumpto)
ldp x20,x21, [x0, #0x0A0]
ldp x22,x23, [x0, #0x0B0]
ldp x24,x25, [x0, #0x0C0]
#ifdef __LFI__
ldp x26,xzr, [x0, #0x0D0]
ldp xzr,x29, [x0, #0x0E0]
#else
ldp x26,x27, [x0, #0x0D0]
ldp x28,x29, [x0, #0x0E0]
#endif
ldr x30, [x0, #0x100] // restore pc into lr
#if defined(__ARM_FP) && __ARM_FP != 0
ldp d0, d1, [x0, #0x110]
Expand Down
2 changes: 1 addition & 1 deletion lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2901,7 +2901,7 @@ template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
if (p->p_type == PT_LOAD && (p->p_flags & PF_X))
fillTrap(
ctx.target->trapInstr,
ctx.bufferStart + alignDown(p->firstSec->offset + p->p_filesz, 4),
ctx.bufferStart + p->firstSec->offset,
ctx.bufferStart + alignToPowerOf2(p->firstSec->offset + p->p_filesz,
ctx.arg.maxPageSize));

Expand Down
22 changes: 22 additions & 0 deletions llvm/include/llvm/MC/MCLFI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===- MCLFI.h - LFI-specific code for MC -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// This file was written by the Native Client authors, modified for LFI.
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/CommandLine.h"

namespace llvm {

class MCContext;
class MCStreamer;
class Triple;

void initializeLFIMCStreamer(MCStreamer &Streamer, MCContext &Ctx,
const Triple &TheTriple);

} // namespace llvm
79 changes: 79 additions & 0 deletions llvm/include/llvm/MC/MCLFIExpander.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//===- llvm/MC/MCLFIExpander.h ----------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// This file was written by the Native Client authors, modified for LFI.
//
//===----------------------------------------------------------------------===//
//
// This file declares the MCLFIExpander class. This is an abstract
// class that encapsulates the expansion logic for MCInsts, and holds
// state such as available scratch registers.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_MC_MCLFIEXPANDER_H
#define LLVM_MC_MCLFIEXPANDER_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"

namespace llvm {
class MCInst;
class MCSubtargetInfo;
class MCStreamer;

class MCLFIExpander {
private:
SmallVector<MCRegister, 2> ScratchRegs;
bool Enabled = true;

protected:
MCContext &Ctx;
std::unique_ptr<MCInstrInfo> InstInfo;
std::unique_ptr<MCRegisterInfo> RegInfo;
void invalidateScratchRegs(const MCInst &Inst);
MCRegister getScratchReg(int index);
unsigned numScratchRegs() const;
virtual bool isValidScratchRegister(MCRegister Reg) const = 0;

public:
MCLFIExpander(MCContext &Ctx, std::unique_ptr<MCRegisterInfo> &&RI,
std::unique_ptr<MCInstrInfo> &&II)
: Ctx(Ctx), InstInfo(std::move(II)), RegInfo(std::move(RI)) {}

void Error(const MCInst &Inst, const char msg[]);

bool addScratchReg(MCRegister Reg);
void clearScratchRegs();

void disable();
void enable();
bool isEnabled();

bool isPseudo(const MCInst &Inst) const;

bool mayAffectControlFlow(const MCInst &Inst) const;
bool isCall(const MCInst &Inst) const;
bool isBranch(const MCInst &Inst) const;
bool isIndirectBranch(const MCInst &Inst) const;
bool isReturn(const MCInst &Inst) const;
bool isVariadic(const MCInst &Inst) const;

bool mayLoad(const MCInst &Inst) const;
bool mayStore(const MCInst &Inst) const;

bool mayModifyRegister(const MCInst &Inst, MCRegister Reg) const;
bool explicitlyModifiesRegister(const MCInst &Inst, MCRegister Reg) const;

virtual ~MCLFIExpander() = default;
virtual bool expandInst(const MCInst &Inst, MCStreamer &Out,
const MCSubtargetInfo &STI) = 0;
};

} // namespace llvm
#endif
7 changes: 7 additions & 0 deletions llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCFragment.h"
#include "llvm/MC/MCLinkerOptimizationHint.h"
#include "llvm/MC/MCLFIExpander.h"
#include "llvm/MC/MCPseudoProbe.h"
#include "llvm/MC/MCWinEH.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -276,6 +277,8 @@ class MCStreamer {
/// Returns true if the .cv_loc directive is in the right section.
bool checkCVLocSection(unsigned FuncId, unsigned FileNo, SMLoc Loc);

std::unique_ptr<MCLFIExpander> LFIExpander;

public:
MCStreamer(const MCStreamer &) = delete;
MCStreamer &operator=(const MCStreamer &) = delete;
Expand All @@ -293,6 +296,10 @@ class MCStreamer {
return StartTokLocPtr ? *StartTokLocPtr : SMLoc();
}

void setLFIExpander(MCLFIExpander *Exp) { LFIExpander.reset(Exp); }

MCLFIExpander *getLFIExpander() { return LFIExpander.get(); }

/// State management
///
virtual void reset();
Expand Down
Loading