diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2017-12-13 21:53:04 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2017-12-13 21:53:04 +0000 |
commit | 6010880bd13b11ea687658d8f5bc4913bc62eb27 (patch) | |
tree | b65f59e8515805d5b1301f1a443568677ff4f897 /clang/lib/CodeGen | |
parent | 14318c5b318cd90123029fd1622dfcd024caeff4 (diff) | |
download | bcm5719-llvm-6010880bd13b11ea687658d8f5bc4913bc62eb27.tar.gz bcm5719-llvm-6010880bd13b11ea687658d8f5bc4913bc62eb27.zip |
IRGen: When performing CFI checks, load vtable pointer from vbase when necessary.
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.
Differential Revision: https://reviews.llvm.org/D41036
llvm-svn: 320638
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 7 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 8 | ||||
-rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 10 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 29 |
5 files changed, 47 insertions, 12 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index ed5771d2ca4..83426dc3a03 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -582,6 +582,13 @@ public: /// Emit a single constructor/destructor with the given type from a C++ /// constructor Decl. virtual void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) = 0; + + /// Load a vtable from This, an object of polymorphic type RD, or from one of + /// its virtual bases if it does not have its own vtable. Returns the vtable + /// and the class from which the vtable was loaded. + virtual std::pair<llvm::Value *, const CXXRecordDecl *> + LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) = 0; }; // Create an instance of a C++ ABI class: diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 95043ea0325..9bbdc98f1f2 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2627,8 +2627,9 @@ void CodeGenFunction::EmitVTablePtrCheckForCast(QualType T, EmitBlock(CheckBlock); } - llvm::Value *VTable = - GetVTablePtr(Address(Derived, getPointerAlign()), Int8PtrTy, ClassDecl); + llvm::Value *VTable; + std::tie(VTable, ClassDecl) = CGM.getCXXABI().LoadVTablePtr( + *this, Address(Derived, getPointerAlign()), ClassDecl); EmitVTablePtrCheck(ClassDecl, VTable, TCK, Loc); diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 3eb4bd6b901..41bb199ffde 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -368,9 +368,11 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( } else { if (SanOpts.has(SanitizerKind::CFINVCall) && MD->getParent()->isDynamicClass()) { - llvm::Value *VTable = GetVTablePtr(This, Int8PtrTy, MD->getParent()); - EmitVTablePtrCheckForCall(MD->getParent(), VTable, CFITCK_NVCall, - CE->getLocStart()); + llvm::Value *VTable; + const CXXRecordDecl *RD; + std::tie(VTable, RD) = + CGM.getCXXABI().LoadVTablePtr(*this, This, MD->getParent()); + EmitVTablePtrCheckForCall(RD, VTable, CFITCK_NVCall, CE->getLocStart()); } if (getLangOpts().AppleKext && MD->isVirtual() && HasQualifier) diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index ea5e8dd82c5..c375b82ea93 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -389,6 +389,10 @@ public: void emitCXXStructor(const CXXMethodDecl *MD, StructorType Type) override; + std::pair<llvm::Value *, const CXXRecordDecl *> + LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) override; + private: bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const { const auto &VtableLayout = @@ -4041,3 +4045,9 @@ ItaniumCXXABI::emitTerminateForUnexpectedException(CodeGenFunction &CGF, } return CGF.EmitNounwindRuntimeCall(CGF.CGM.getTerminateFn()); } + +std::pair<llvm::Value *, const CXXRecordDecl *> +ItaniumCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) { + return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; +} diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 97a7fbab9a5..ffb3681c258 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -578,7 +578,7 @@ private: return GetVBaseOffsetFromVBPtr(CGF, Base, VBPOffset, VBTOffset, VBPtr); } - std::pair<Address, llvm::Value *> + std::tuple<Address, llvm::Value *, const CXXRecordDecl *> performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy); @@ -745,6 +745,10 @@ public: llvm::GlobalVariable *getThrowInfo(QualType T) override; + std::pair<llvm::Value *, const CXXRecordDecl *> + LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) override; + private: typedef std::pair<const CXXRecordDecl *, CharUnits> VFTableIdTy; typedef llvm::DenseMap<VFTableIdTy, llvm::GlobalVariable *> VTablesMapTy; @@ -926,7 +930,7 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF, /// 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<Address, llvm::Value *> +std::tuple<Address, llvm::Value *, const CXXRecordDecl *> MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy) { Value = CGF.Builder.CreateBitCast(Value, CGF.Int8PtrTy); @@ -937,7 +941,8 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, // 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 @@ MicrosoftCXXABI::performBaseAdjustment(CodeGenFunction &CGF, Address Value, 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 @@ llvm::Value *MicrosoftCXXABI::EmitTypeid(CodeGenFunction &CGF, 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 @@ llvm::Value *MicrosoftCXXABI::EmitDynamicCastCall( CGF.CGM.GetAddrOfRTTIDescriptor(DestRecordTy.getUnqualifiedType()); llvm::Value *Offset; - std::tie(This, Offset) = performBaseAdjustment(CGF, This, SrcRecordTy); + std::tie(This, Offset, std::ignore) = + performBaseAdjustment(CGF, This, SrcRecordTy); llvm::Value *ThisPtr = This.getPointer(); Offset = CGF.Builder.CreateTrunc(Offset, CGF.Int32Ty); @@ -1037,7 +1043,8 @@ llvm::Value * MicrosoftCXXABI::EmitDynamicCastToVoid(CodeGenFunction &CGF, Address Value, QualType SrcRecordTy, QualType DestTy) { - std::tie(Value, std::ignore) = performBaseAdjustment(CGF, Value, SrcRecordTy); + std::tie(Value, std::ignore, std::ignore) = + performBaseAdjustment(CGF, Value, SrcRecordTy); // PVOID __RTCastToVoid( // PVOID inptr) @@ -4244,3 +4251,11 @@ void MicrosoftCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) { }; CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(), Args); } + +std::pair<llvm::Value *, const CXXRecordDecl *> +MicrosoftCXXABI::LoadVTablePtr(CodeGenFunction &CGF, Address This, + const CXXRecordDecl *RD) { + std::tie(This, std::ignore, RD) = + performBaseAdjustment(CGF, This, QualType(RD->getTypeForDecl(), 0)); + return {CGF.GetVTablePtr(This, CGM.Int8PtrTy, RD), RD}; +} |