Index: llvm/lib/Target/X86/X86IndirectBranchTracking.cpp =================================================================== --- llvm/lib/Target/X86/X86IndirectBranchTracking.cpp +++ llvm/lib/Target/X86/X86IndirectBranchTracking.cpp @@ -18,6 +18,7 @@ #include "X86.h" #include "X86InstrInfo.h" #include "X86Subtarget.h" +#include "X86TargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -102,7 +103,17 @@ // Check that the cf-protection-branch is enabled. Metadata *isCFProtectionSupported = MF.getMMI().getModule()->getModuleFlag("cf-protection-branch"); - if (!isCFProtectionSupported && !IndirectBranchTracking) + // NB: We need to enable IBT in jitted code if JIT compiler is CET + // enabled. +#ifdef __CET__ + const X86TargetMachine *TM = + static_cast(&MF.getTarget()); + bool isJITwithCET = TM->isJIT(); +#else + bool isJITwithCET = false; +#endif + // Jitted code generated by CET-enabled JIT compiler will default enable CET. + if (!isCFProtectionSupported && !IndirectBranchTracking && !isJITwithCET) return false; // True if the current MF was changed and false otherwise. @@ -112,11 +123,11 @@ EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32; // Non-internal function or function whose address was taken, can be - // accessed through indirect calls. Mark the first BB with ENDBR instruction - // unless nocf_check attribute is used. - if ((MF.getFunction().hasAddressTaken() || - !MF.getFunction().hasLocalLinkage()) && - !MF.getFunction().doesNoCfCheck()) { + // accessed through indirect calls. Mark the first BB with ENDBR + // instruction unless nocf_check attribute is used. + // For internal function, its may also be accessed by function address + // which usually is a indirect jump. + if (!MF.getFunction().doesNoCfCheck()) { auto MBB = MF.begin(); Changed |= addENDBR(*MBB, MBB->begin()); } @@ -136,8 +147,8 @@ Changed |= addENDBR(MBB, std::next(I)); if (EHPadIBTNeeded && I->isEHLabel()) { - Changed |= addENDBR(MBB, std::next(I)); - EHPadIBTNeeded = false; + Changed |= addENDBR(MBB, std::next(I)); + EHPadIBTNeeded = false; } } } Index: llvm/lib/Target/X86/X86TargetMachine.h =================================================================== --- llvm/lib/Target/X86/X86TargetMachine.h +++ llvm/lib/Target/X86/X86TargetMachine.h @@ -30,6 +30,8 @@ class X86TargetMachine final : public LLVMTargetMachine { std::unique_ptr TLOF; mutable StringMap> SubtargetMap; + // True if this is used in JIT. + bool IsJIT; public: X86TargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -52,6 +54,8 @@ TargetLoweringObjectFile *getObjFileLowering() const override { return TLOF.get(); } + + bool isJIT() const { return IsJIT; } }; } // end namespace llvm Index: llvm/lib/Target/X86/X86TargetMachine.cpp =================================================================== --- llvm/lib/Target/X86/X86TargetMachine.cpp +++ llvm/lib/Target/X86/X86TargetMachine.cpp @@ -214,7 +214,7 @@ getEffectiveRelocModel(TT, JIT, RM), getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL), - TLOF(createTLOF(getTargetTriple())) { + TLOF(createTLOF(getTargetTriple())), IsJIT(JIT) { // On PS4, the "return address" of a 'noreturn' call must still be within // the calling function, and TrapUnreachable is an easy way to get that. if (TT.isPS4() || TT.isOSBinFormatMachO()) { Index: llvm/test/CodeGen/X86/indirect-branch-tracking.ll =================================================================== --- llvm/test/CodeGen/X86/indirect-branch-tracking.ll +++ llvm/test/CodeGen/X86/indirect-branch-tracking.ll @@ -153,8 +153,8 @@ define internal i8 @test5(){ ; ALL-LABEL: test5 -; X86_64-NOT: endbr64 -; X86-NOT: endbr32 +; X86_64: endbr64 +; X86: endbr32 ret i8 1 } Index: llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll =================================================================== --- llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll +++ llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll @@ -69,15 +69,17 @@ ; CHECK-NEXT: .Lfunc_begin3: ; CHECK-NEXT: .cfi_startproc ; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: endbr +; CHECK-NEXT: .Lpatch1 ; CHECK-NEXT: nop ; CHECK-NOT: .Lpatch0: ;; Another basic block has ENDBR, but it doesn't affect our decision to not create .Lpatch0 ; CHECK: endbr ; CHECK: .section __patchable_function_entries,"awo",@progbits,f1i{{$}} ; 32-NEXT: .p2align 2 -; 32-NEXT: .long .Lfunc_begin3 +; 32-NEXT: .long .Lpatch1 ; 64-NEXT: .p2align 3 -; 64-NEXT: .quad .Lfunc_begin3 +; 64-NEXT: .quad .Lpatch1 entry: tail call i32 @llvm.eh.sjlj.setjmp(i8* bitcast ([5 x i8*]* @buf to i8*)) ret void