MaskRay created this revision. MaskRay added reviewers: dmgreen, lenary, pcc, peter.smith. Herald added subscribers: Enna1, hiraditya, kristof.beyls. Herald added a project: All. MaskRay requested review of this revision. Herald added projects: clang, Sanitizers, LLVM. Herald added subscribers: llvm-commits, Sanitizers, cfe-commits.
The current implementation of -fsanitize=function places two words (the prolog signature and the RTTI proxy) at the function entry, which makes the feature incompatible with Intel Indirect Branch Tracking that needs an ENDBR instruction at the function entry. To allow the combination, move the two words before the function entry, similar to -fsanitize=kcfi. The code will also be shared with my pending patch implementing -fsanitize=function for AArch64 (Branch Target Identification has a similar requirement). --- For the removed function in AsmPrinter.cpp, remove an assert: `mdconst::extract` already asserts non-nullness. For compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp, when the function doesn't have prolog/epilog (-O1 and above), after moving the two words, the address of the function equals the address of ret instruction, so symbolizing the function will additionally get a non-zero column number. Adjust the test to allow an optional column number. .long 846595819 .long .L__llvm_rtti_proxy-_Z1fv _Z1fv: // symbolizing here retrieves the line table entry from the second .loc .file 0 ... .loc 0 1 0 .cfi_startproc .loc 0 2 1 prologue_end retq Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D148665 Files: clang/lib/CodeGen/CGExpr.cpp compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp llvm/test/CodeGen/X86/func-sanitizer.ll llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll
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 @@ -1,6 +1,9 @@ ; RUN: llc -mtriple=i686 %s -o - | FileCheck --check-prefixes=CHECK,32 %s ; RUN: llc -mtriple=x86_64 %s -o - | FileCheck --check-prefixes=CHECK,64 %s +@_ZTIFvvE = linkonce_odr constant i32 1 +@__llvm_rtti_proxy = private unnamed_addr constant ptr @_ZTIFvvE + ;; -fpatchable-function-entry=0 -fcf-protection=branch define void @f0() "patchable-function-entry"="0" { ; CHECK-LABEL: f0: @@ -83,6 +86,25 @@ ret void } +;; Test the interaction with -fsanitize=function. +; CHECK: .type sanitize_function,@function +; CHECK-NEXT: .Ltmp{{.*}}: +; CHECK-NEXT: nop +; CHECK-NEXT: .long 846595819 +; CHECK-NEXT: .long .L__llvm_rtti_proxy-sanitize_function +; CHECK-NEXT: sanitize_function: +; CHECK-NEXT: .Lfunc_begin{{.*}}: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; 32-NEXT: endbr32 +; 64-NEXT: endbr64 +; CHECK-NEXT: nop +; CHECK-NEXT: ret +define void @sanitize_function(ptr noundef %x) "patchable-function-prefix"="1" "patchable-function-entry"="1" !func_sanitize !1 { + ret void +} + !llvm.module.flags = !{!0} !0 = !{i32 8, !"cf-protection-branch", i32 1} +!1 = !{i32 846595819, ptr @__llvm_rtti_proxy} Index: llvm/test/CodeGen/X86/func-sanitizer.ll =================================================================== --- llvm/test/CodeGen/X86/func-sanitizer.ll +++ llvm/test/CodeGen/X86/func-sanitizer.ll @@ -1,12 +1,12 @@ ; RUN: llc -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s -; CHECK: _Z3funv: -; CHECK: .cfi_startproc -; CHECK: .long 846595819 -; CHECK: .long .L__llvm_rtti_proxy-_Z3funv -; CHECK: .L__llvm_rtti_proxy: -; CHECK: .quad i -; CHECK: .size .L__llvm_rtti_proxy, 8 +; CHECK: .type _Z3funv,@function +; CHECK-NEXT: .long 846595819 # 0x327606eb +; CHECK-NEXT: .long .L__llvm_rtti_proxy-_Z3funv +; CHECK-NEXT: _Z3funv: +; CHECK-NEXT: .cfi_startproc +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: retq @i = linkonce_odr constant i32 1 @__llvm_rtti_proxy = private unnamed_addr constant ptr @i Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -970,6 +970,22 @@ CurrentPatchableFunctionEntrySym = CurrentFnBegin; } + // Emit the function prologue data for the indirect call sanitizer. + if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) { + assert(TM.getTargetTriple().isX86()); + assert(MD->getNumOperands() == 2); + + auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0)); + auto *FTRTTIProxy = mdconst::extract<Constant>(MD->getOperand(1)); + emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig); + + const MCExpr *Proxy = lowerConstant(FTRTTIProxy); + const MCExpr *FnExp = MCSymbolRefExpr::create(CurrentFnSym, OutContext); + const MCExpr *PCRel = MCBinaryExpr::createSub(Proxy, FnExp, OutContext); + // Use 32 bit since only small code model is supported. + OutStreamer->emitValue(PCRel, 4u); + } + if (isVerbose()) { F.printAsOperand(OutStreamer->getCommentOS(), /*PrintType=*/false, F.getParent()); @@ -1024,24 +1040,6 @@ // Emit the prologue data. if (F.hasPrologueData()) emitGlobalConstant(F.getParent()->getDataLayout(), F.getPrologueData()); - - // Emit the function prologue data for the indirect call sanitizer. - if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) { - assert(TM.getTargetTriple().getArch() == Triple::x86 || - TM.getTargetTriple().getArch() == Triple::x86_64); - assert(MD->getNumOperands() == 2); - - auto *PrologueSig = mdconst::extract<Constant>(MD->getOperand(0)); - auto *FTRTTIProxy = mdconst::extract<Constant>(MD->getOperand(1)); - assert(PrologueSig && FTRTTIProxy); - emitGlobalConstant(F.getParent()->getDataLayout(), PrologueSig); - - const MCExpr *Proxy = lowerConstant(FTRTTIProxy); - const MCExpr *FnExp = MCSymbolRefExpr::create(CurrentFnSym, OutContext); - const MCExpr *PCRel = MCBinaryExpr::createSub(Proxy, FnExp, OutContext); - // Use 32 bit since only small code model is supported. - OutStreamer->emitValue(PCRel, 4u); - } } /// EmitFunctionEntryLabel - Emit the label that is the entrypoint for the Index: compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp =================================================================== --- compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp @@ -61,7 +61,7 @@ void make_invalid_call() { // CHECK: function.cpp:[[@LINE+4]]:3: runtime error: call to function f() through pointer to incorrect function type 'void (*)(int)' - // CHECK-NEXT: function.cpp:[[@LINE-11]]: note: f() defined here + // CHECK-NEXT: function.cpp:[[@LINE-11]]:{{(11:)?}} note: f() defined here // NOSYM: function.cpp:[[@LINE+2]]:3: runtime error: call to function (unknown) through pointer to incorrect function type 'void (*)(int)' // NOSYM-NEXT: ({{.*}}+0x{{.*}}): note: (unknown) defined here reinterpret_cast<void (*)(int)>(reinterpret_cast<uintptr_t>(f))(42); Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -5368,7 +5368,7 @@ llvm::Value *CalleePrefixStruct = Builder.CreateBitCast( CalleePtr, llvm::PointerType::getUnqual(PrefixStructTy)); llvm::Value *CalleeSigPtr = - Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 0); + Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, -1, 0); llvm::Value *CalleeSig = Builder.CreateAlignedLoad(PrefixSigType, CalleeSigPtr, getIntAlign()); llvm::Value *CalleeSigMatch = Builder.CreateICmpEQ(CalleeSig, PrefixSig); @@ -5379,7 +5379,7 @@ EmitBlock(TypeCheck); llvm::Value *CalleeRTTIPtr = - Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1); + Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, -1, 1); llvm::Value *CalleeRTTIEncoded = Builder.CreateAlignedLoad(Int32Ty, CalleeRTTIPtr, getPointerAlign()); llvm::Value *CalleeRTTI =
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits