[PATCH] D41036: IRGen: When performing CFI checks, load vtable pointer from vbase when necessary.
pcc added a comment. Ping. https://reviews.llvm.org/D41036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41036: IRGen: When performing CFI checks, load vtable pointer from vbase when necessary.
This revision was automatically updated to reflect the committed changes. Closed by commit rL320638: IRGen: When performing CFI checks, load vtable pointer from vbase when… (authored by pcc, committed by ). Changed prior to commit: https://reviews.llvm.org/D41036?vs=126220&id=126831#toc Repository: rL LLVM https://reviews.llvm.org/D41036 Files: cfe/trunk/lib/CodeGen/CGCXXABI.h cfe/trunk/lib/CodeGen/CGClass.cpp cfe/trunk/lib/CodeGen/CGExprCXX.cpp cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp Index: cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp === --- cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp +++ cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-nvcall -fsanitize-trap=cfi-nvcall | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template +struct bar : virtual public foo { + void f() {} +}; + +struct baz : public bar { + virtual ~baz() {} + void g() {} +}; + +void f(baz *z) { + // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z" + // Load z, vbtable, vbase offset and vtable. + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" + z->g(); +} Index: cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp === --- cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp +++ cfe/trunk/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template +struct bar : virtual public foo { + void f() { +// CHECK: define{{.*}}@"\01?f@?$bar@UbazUEAAXXZ" +// Load "this", vbtable, vbase offset and vtable. +// CHECK: load +// CHECK: load +// CHECK: load +// CHECK: load +// CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" +static_cast(*this); + } +}; + +struct baz : public bar { + virtual ~baz() {} +}; + +int main() { + baz *z = new baz; + z->f(); +} Index: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp === --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp @@ -389,6 +389,10 @@ void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; + std::pair + LoadVTablePtr(CodeGenFunction &CGF, Address This, +const CXXRecordDecl *RD) override; + private: bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { const auto &VtableLayout = @@ -4041,3 +4045,9 @@ } return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); } + +std::pair +ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) { + return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; +} Index: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp === --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp @@ -578,7 +578,7 @@ return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); } - std::pair + std::tuple performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy); @@ -745,6 +745,10 @@ llvm::GlobalVariable *getThrowInfo(QualType T) override; + std::pair + LoadVTablePtr(CodeGenFunction &CGF, Address This, +const CXXRecordDecl *RD) override; + private: typedef std::pair VFTableIdTy; typedef llvm::DenseMap VTablesMapTy; @@ -926,7 +930,7 @@ /// We need to perform a generic polymorphic operation (like a typeid /// or a cast), which requires an object with a vfptr. Adjust the /// address to point to an object with a vfptr. -std::pair +std::tuple MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy) { Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); @@ -937,7 +941,8 @@ // covers non-virtual base subobjects: a class with its own virtual // functions would be a candidate to be a primary base. if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr()) -return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0)); +return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0), + SrcDecl); // Okay, one of the vbases must have a vfptr, or else this isn't // actually a polymorphic class. @@ -956,7 +961,7 @@ llvm::Value *Pt
[PATCH] D41036: IRGen: When performing CFI checks, load vtable pointer from vbase when necessary.
rnk added a comment. Looks good! Repository: rL LLVM https://reviews.llvm.org/D41036 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D41036: IRGen: When performing CFI checks, load vtable pointer from vbase when necessary.
pcc created this revision. Under the Microsoft ABI, it is possible for an object not to have a virtual table pointer of its own if all of its virtual functions were introduced by virtual bases. In that case, we need to load the vtable pointer from one of the virtual bases and perform the type check using its type. https://reviews.llvm.org/D41036 Files: clang/lib/CodeGen/CGCXXABI.h clang/lib/CodeGen/CGClass.cpp clang/lib/CodeGen/CGExprCXX.cpp clang/lib/CodeGen/ItaniumCXXABI.cpp clang/lib/CodeGen/MicrosoftCXXABI.cpp clang/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp clang/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp Index: clang/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp === --- /dev/null +++ clang/test/CodeGenCXX/cfi-ms-vbase-nvcall.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-nvcall -fsanitize-trap=cfi-nvcall | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template +struct bar : virtual public foo { + void f() {} +}; + +struct baz : public bar { + virtual ~baz() {} + void g() {} +}; + +void f(baz *z) { + // CHECK: define{{.*}}@"\01?f@@YAXPEAUbaz@@@Z" + // Load z, vbtable, vbase offset and vtable. + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: load + // CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" + z->g(); +} Index: clang/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp === --- /dev/null +++ clang/test/CodeGenCXX/cfi-ms-vbase-derived-cast.cpp @@ -0,0 +1,29 @@ +// RUN: %clang_cc1 -flto -flto-unit -emit-llvm -o - -triple=x86_64-pc-win32 %s -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast | FileCheck %s + +struct foo { + virtual ~foo() {} + virtual void f() = 0; +}; + +template +struct bar : virtual public foo { + void f() { +// CHECK: define{{.*}}@"\01?f@?$bar@UbazUEAAXXZ" +// Load "this", vbtable, vbase offset and vtable. +// CHECK: load +// CHECK: load +// CHECK: load +// CHECK: load +// CHECK: @llvm.type.test{{.*}}!"?AUfoo@@" +static_cast(*this); + } +}; + +struct baz : public bar { + virtual ~baz() {} +}; + +int main() { + baz *z = new baz; + z->f(); +} Index: clang/lib/CodeGen/MicrosoftCXXABI.cpp === --- clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -578,7 +578,7 @@ return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); } - std::pair + std::tuple performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy); @@ -745,6 +745,10 @@ llvm::GlobalVariable *getThrowInfo(QualType T) override; + std::pair + LoadVTablePtr(CodeGenFunction &CGF, Address This, +const CXXRecordDecl *RD) override; + private: typedef std::pair VFTableIdTy; typedef llvm::DenseMap VTablesMapTy; @@ -926,7 +930,7 @@ /// We need to perform a generic polymorphic operation (like a typeid /// or a cast), which requires an object with a vfptr. Adjust the /// address to point to an object with a vfptr. -std::pair +std::tuple MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy) { Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); @@ -937,7 +941,8 @@ // covers non-virtual base subobjects: a class with its own virtual // functions would be a candidate to be a primary base. if (Context.getASTRecordLayout(SrcDecl).hasExtendableVFPtr()) -return std::make_pair(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0)); +return std::make_tuple(Value, llvm::ConstantInt::get(CGF.Int32Ty, 0), + SrcDecl); // Okay, one of the vbases must have a vfptr, or else this isn't // actually a polymorphic class. @@ -956,7 +961,7 @@ llvm::Value *Ptr = CGF.Builder.CreateInBoundsGEP(Value.getPointer(), Offset); CharUnits VBaseAlign = CGF.CGM.getVBaseAlignment(Value.getAlignment(), SrcDecl, PolymorphicBase); - return std::make_pair(Address(Ptr, VBaseAlign), Offset); + return std::make_tuple(Address(Ptr, VBaseAlign), Offset, PolymorphicBase); } bool MicrosoftCXXABI::shouldTypeidBeNullChecked(bool IsDeref, @@ -987,7 +992,7 @@ QualType SrcRecordTy, Address ThisPtr, llvm::Type *StdTypeInfoPtrTy) { - std::tie(ThisPtr, std::ignore) = + std::tie(ThisPtr, std::ignore, std::ignore) = performBaseAdjustment(CGF, ThisPtr, SrcRecordTy); auto Typeid = emitRTtypeidCall(CGF, ThisPtr.getPointer()).getInstruction(); return CGF.Builder.CreateBitCast(Typeid, StdTypeInfoPtrTy); @@ -1011,7 +1016,8 @@ CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType());