Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4380,7 +4380,7 @@ CGM.GetAddrOfRTTIDescriptor(QualType(FnType, 0), /*ForEH=*/true); llvm::Type *PrefixStructTyElems[] = { PrefixSig->getType(), - FTRTTIConst->getType() + (CGM.getTriple().isOSDarwin() ? Int8PtrPtrTy : Int8PtrTy) }; llvm::StructType *PrefixStructTy = llvm::StructType::get( CGM.getLLVMContext(), PrefixStructTyElems, /*isPacked=*/true); @@ -4402,8 +4402,10 @@ EmitBlock(TypeCheck); llvm::Value *CalleeRTTIPtr = Builder.CreateConstGEP2_32(PrefixStructTy, CalleePrefixStruct, 0, 1); - llvm::Value *CalleeRTTI = + llvm::Value *CalleeRTTIEncoded = Builder.CreateAlignedLoad(CalleeRTTIPtr, getPointerAlign()); + llvm::Value *CalleeRTTI = + DecodeAddrUsedInPrologue(CalleePtr, CalleeRTTIEncoded); llvm::Value *CalleeRTTIMatch = Builder.CreateICmpEQ(CalleeRTTI, FTRTTIConst); llvm::Constant *StaticData[] = { Index: lib/CodeGen/CodeGenFunction.h =================================================================== --- lib/CodeGen/CodeGenFunction.h +++ lib/CodeGen/CodeGenFunction.h @@ -1775,6 +1775,15 @@ /// EmitMCountInstrumentation - Emit call to .mcount. void EmitMCountInstrumentation(); + /// Encode an address into a form suitable for use in a function prologue. + llvm::Constant *EncodeAddrForUseInPrologue(llvm::Function *F, + llvm::Constant *Addr); + + /// Decode an address used in a function prologue, encoded by \c + /// EncodeAddrForUseInPrologue. + llvm::Value *DecodeAddrUsedInPrologue(llvm::Value *F, + llvm::Value *EncodedAddr); + /// EmitFunctionProlog - Emit the target specific LLVM code to load the /// arguments for the given function. This is also responsible for naming the /// LLVM function arguments. Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -428,6 +428,48 @@ return CGM.getCodeGenOpts().XRayInstrumentFunctions; } +llvm::Constant * +CodeGenFunction::EncodeAddrForUseInPrologue(llvm::Function *F, + llvm::Constant *Addr) { + if (!CGM.getTriple().isOSDarwin()) + return Addr; + + // Addresses stored in prologue data can't require run-time fixups and must + // be PC-relative. Run-time fixups are undesirable because they necessitate + // writable text segments, which is unsafe. And absolute addresses are + // undesirable because they break PIE mode. + + // Add a layer of indirection through a private global. Taking its address + // won't result in a run-time fixup, even if Addr has linkonce_odr linkage. + auto *GV = new llvm::GlobalVariable(CGM.getModule(), Addr->getType(), + /*isConstant=*/false, + llvm::GlobalValue::PrivateLinkage, Addr); + + // Create a PC-relative address. + auto *GOTAsInt = llvm::ConstantExpr::getPtrToInt(GV, IntPtrTy); + auto *FuncAsInt = llvm::ConstantExpr::getPtrToInt(F, IntPtrTy); + auto *PCRelAsInt = llvm::ConstantExpr::getSub(GOTAsInt, FuncAsInt); + return llvm::ConstantExpr::getIntToPtr(PCRelAsInt, Int8PtrPtrTy); +} + +llvm::Value * +CodeGenFunction::DecodeAddrUsedInPrologue(llvm::Value *F, + llvm::Value *EncodedAddr) { + if (!CGM.getTriple().isOSDarwin()) + return EncodedAddr; + + // Reconstruct the address of the global. + auto *PCRelAsInt = + Builder.CreatePtrToInt(EncodedAddr, IntPtrTy, "encoded_addr.int"); + auto *FuncAsInt = Builder.CreatePtrToInt(F, IntPtrTy, "func_addr.int"); + auto *GOTAsInt = Builder.CreateAdd(PCRelAsInt, FuncAsInt, "global_addr.int"); + auto *GOTAddr = Builder.CreateIntToPtr(GOTAsInt, Int8PtrPtrTy, "global_addr"); + + // Load the original pointer through the global. + return Builder.CreateLoad(Address(GOTAddr, getPointerAlign()), + "decoded_addr"); +} + /// EmitFunctionInstrumentation - Emit LLVM code to call the specified /// instrumentation function with the current function and the call site, if /// function instrumentation is enabled. @@ -823,7 +865,10 @@ CGM.getTargetCodeGenInfo().getUBSanFunctionSignature(CGM)) { llvm::Constant *FTRTTIConst = CGM.GetAddrOfRTTIDescriptor(FD->getType(), /*ForEH=*/true); - llvm::Constant *PrologueStructElems[] = { PrologueSig, FTRTTIConst }; + llvm::Constant *FTRTTIConstEncoded = + EncodeAddrForUseInPrologue(Fn, FTRTTIConst); + llvm::Constant *PrologueStructElems[] = {PrologueSig, + FTRTTIConstEncoded}; llvm::Constant *PrologueStructConst = llvm::ConstantStruct::getAnon(PrologueStructElems, /*Packed=*/true); Fn->setPrologueData(PrologueStructConst); Index: test/CodeGenCXX/catch-undef-behavior.cpp =================================================================== --- test/CodeGenCXX/catch-undef-behavior.cpp +++ test/CodeGenCXX/catch-undef-behavior.cpp @@ -3,6 +3,7 @@ // RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-X32 // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-X86 +// RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-apple-darwin | FileCheck %s --check-prefix=FSAN-DARWIN struct S { double d; @@ -16,6 +17,8 @@ // Check that type mismatch handler is not modified by ASan. // CHECK-ASAN: private unnamed_addr global { { [{{.*}} x i8]*, i32, i32 }, { i16, i16, [4 x i8] }*, i8*, i8 } { {{.*}}, { i16, i16, [4 x i8] }* [[TYPE_DESCR]], {{.*}} } +// FSAN-DARWIN: [[IndirectRTTI_ZTIFvPFviEE:@.+]] = private global i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) + struct T : S {}; // CHECK-LABEL: @_Z17reference_binding @@ -395,6 +398,8 @@ // CHECK-NEXT: br i1 [[AND]] } +// +// FSAN-DARWIN: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8** }> <{ i32 1413876459, i8** inttoptr (i64 sub (i64 ptrtoint (i8** [[IndirectRTTI_ZTIFvPFviEE]] to i64), i64 ptrtoint (void (void (i32)*)* @_Z22indirect_function_callPFviE to i64)) to i8**) }> // CHECK-LABEL: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413876459, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> // CHECK-X32: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> // CHECK-X86: @_Z22indirect_function_callPFviE({{.*}} prologue <{ i32, i8* }> <{ i32 1413875435, i8* bitcast ({ i8*, i8* }* @_ZTIFvPFviEE to i8*) }> @@ -412,6 +417,26 @@ // CHECK-NEXT: [[RTTI:%.+]] = load i8*, i8** [[RTTIPTR]] // CHECK-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) // CHECK-NEXT: br i1 [[RTTICMP]] + + // FSAN-DARWIN: [[PTR:%.+]] = bitcast void (i32)* {{.*}} to <{ i32, i8** }>* + + // Signature check + // FSAN-DARWIN-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i8** }>, <{ i32, i8** }>* [[PTR]], i32 0, i32 0 + // FSAN-DARWIN-NEXT: [[SIG:%.+]] = load i32, i32* [[SIGPTR]] + // FSAN-DARWIN-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], 1413876459 + // FSAN-DARWIN-NEXT: br i1 [[SIGCMP]] + + // RTTI pointer check + // FSAN-DARWIN: [[RTTIPTR:%.+]] = getelementptr <{ i32, i8** }>, <{ i32, i8** }>* [[PTR]], i32 0, i32 1 + // FSAN-DARWIN-NEXT: [[RTTIEnc:%.+]] = load i8**, i8*** [[RTTIPTR]] + // FSAN-DARWIN-NEXT: [[RTTIEncInt:%.+]] = ptrtoint i8** [[RTTIEnc]] to i64 + // FSAN-DARWIN-NEXT: [[FuncAddrInt:%.+]] = ptrtoint void (i32)* {{.*}} to i64 + // FSAN-DARWIN-NEXT: [[IndirectGVInt:%.+]] = add i64 [[RTTIEncInt]], [[FuncAddrInt]] + // FSAN-DARWIN-NEXT: [[IndirectGV:%.+]] = inttoptr i64 [[IndirectGVInt]] to i8** + // FSAN-DARWIN-NEXT: [[RTTI:%.+]] = load i8*, i8** [[IndirectGV]], align 8 + // FSAN-DARWIN-NEXT: [[RTTICMP:%.+]] = icmp eq i8* [[RTTI]], bitcast ({ i8*, i8* }* @_ZTIFviE to i8*) + // FSAN-DARWIN-NEXT: br i1 [[RTTICMP]] + p(42); }