diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/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 = diff --git a/clang/test/CodeGen/ubsan-function.cpp b/clang/test/CodeGen/ubsan-function.cpp --- a/clang/test/CodeGen/ubsan-function.cpp +++ b/clang/test/CodeGen/ubsan-function.cpp @@ -5,12 +5,12 @@ void fun() {} // CHECK-LABEL: define{{.*}} void @_Z6callerPFvvE(ptr noundef %f) -// CHECK: getelementptr <{ i32, i32 }>, ptr {{.*}}, i32 0, i32 0, !nosanitize +// CHECK: getelementptr <{ i32, i32 }>, ptr {{.*}}, i32 -1, i32 0, !nosanitize // CHECK: load i32, ptr {{.*}}, align {{.*}}, !nosanitize // CHECK: icmp eq i32 {{.*}}, 846595819, !nosanitize // CHECK: br i1 {{.*}}, label %[[LABEL1:.*]], label %[[LABEL4:.*]], !nosanitize // CHECK: [[LABEL1]]: -// CHECK: getelementptr <{ i32, i32 }>, ptr {{.*}}, i32 0, i32 1, !nosanitize +// CHECK: getelementptr <{ i32, i32 }>, ptr {{.*}}, i32 -1, i32 1, !nosanitize // CHECK: load i32, ptr {{.*}}, align {{.*}}, !nosanitize // CHECK: icmp eq ptr {{.*}}, @_ZTIFvvE, !nosanitize // CHECK: br i1 {{.*}}, label %[[LABEL3:.*]], label %[[LABEL2:[^,]*]], {{.*}}!nosanitize diff --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp --- a/compiler-rt/test/ubsan/TestCases/TypeCheck/Function/function.cpp +++ b/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(reinterpret_cast(f))(42); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/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(MD->getOperand(0)); + auto *FTRTTIProxy = mdconst::extract(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(MD->getOperand(0)); - auto *FTRTTIProxy = mdconst::extract(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 diff --git a/llvm/test/CodeGen/X86/func-sanitizer.ll b/llvm/test/CodeGen/X86/func-sanitizer.ll --- a/llvm/test/CodeGen/X86/func-sanitizer.ll +++ b/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 diff --git a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll b/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll --- a/llvm/test/CodeGen/X86/patchable-function-entry-ibt.ll +++ b/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}