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/lib/CodeGen/TargetInfo.h b/clang/lib/CodeGen/TargetInfo.h --- a/clang/lib/CodeGen/TargetInfo.h +++ b/clang/lib/CodeGen/TargetInfo.h @@ -199,9 +199,10 @@ /// Return a constant used by UBSan as a signature to identify functions /// possessing type information, or 0 if the platform is unsupported. + /// This magic number is invalid instruction encoding in many targets. virtual llvm::Constant * getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const { - return nullptr; + return llvm::ConstantInt::get(CGM.Int32Ty, 0xc105cafe); } /// Determine whether a call to an unprototyped functions under diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -1290,15 +1290,6 @@ std::string &AsmString, unsigned NumOutputs) const override; - llvm::Constant * - getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { - unsigned Sig = (0xeb << 0) | // jmp rel8 - (0x06 << 8) | // .+0x08 - ('v' << 16) | - ('2' << 24); - return llvm::ConstantInt::get(CGM.Int32Ty, Sig); - } - StringRef getARCRetainAutoreleasedReturnValueMarker() const override { return "movl\t%ebp, %ebp" "\t\t// marker for objc_retainAutoreleaseReturnValue"; @@ -2536,15 +2527,6 @@ return TargetCodeGenInfo::isNoProtoCallVariadic(args, fnType); } - llvm::Constant * - getUBSanFunctionSignature(CodeGen::CodeGenModule &CGM) const override { - unsigned Sig = (0xeb << 0) | // jmp rel8 - (0x06 << 8) | // .+0x08 - ('v' << 16) | - ('2' << 24); - return llvm::ConstantInt::get(CGM.Int32Ty, Sig); - } - void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { if (GV->isDeclaration()) 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: icmp eq i32 {{.*}}, -1056584962, !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 @@ -22,4 +22,4 @@ // CHECK: br label %[[LABEL4]], !nosanitize void caller(void (*f)()) { f(); } -// CHECK: ![[FUNCSAN]] = !{i32 846595819, ptr @[[PROXY]]} +// CHECK: ![[FUNCSAN]] = !{i32 -1056584962, ptr @[[PROXY]]} 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,21 @@ CurrentPatchableFunctionEntrySym = CurrentFnBegin; } + // Emit the function prologue data for the indirect call sanitizer. + if (const MDNode *MD = F.getMetadata(LLVMContext::MD_func_sanitize)) { + 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 +1039,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 3238382334 # 0xc105cafe +; 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 @@ -15,4 +15,4 @@ ret void } -!0 = !{i32 846595819, ptr @__llvm_rtti_proxy} +!0 = !{i32 3238382334, ptr @__llvm_rtti_proxy} 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 3238382334 +; 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 3238382334, ptr @__llvm_rtti_proxy}