Index: lib/CodeGen/CGCXX.cpp =================================================================== --- lib/CodeGen/CGCXX.cpp +++ lib/CodeGen/CGCXX.cpp @@ -31,7 +31,9 @@ /// Try to emit a base destructor as an alias to its primary /// base-class destructor. bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) { - if (!getCodeGenOpts().CXXCtorDtorAliases) + + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor || + !getCodeGenOpts().CXXCtorDtorAliases) return true; // Producing an alias to a base class ctor/dtor can degrade debug quality @@ -113,7 +115,8 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl, GlobalDecl TargetDecl, bool InEveryTU) { - if (!getCodeGenOpts().CXXCtorDtorAliases) + if (getCodeGenOpts().SanitizeMemoryUseAfterDtor || + !getCodeGenOpts().CXXCtorDtorAliases) return true; // The alias will use the linkage of the referent. If we can't Index: lib/CodeGen/CGClass.cpp =================================================================== --- lib/CodeGen/CGClass.cpp +++ lib/CodeGen/CGClass.cpp @@ -1367,52 +1367,6 @@ return true; } -// Generates function call for handling object poisoning, passing in -// references to 'this' and its size as arguments. -// Disables tail call elimination, to prevent the current stack frame from -// disappearing from the stack trace. -static void EmitDtorSanitizerCallback(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor) { - const ASTRecordLayout &Layout = - CGF.getContext().getASTRecordLayout(Dtor->getParent()); - - // Nothing to poison - if(Layout.getFieldCount() == 0) - return; - - // Construct pointer to region to begin poisoning, and calculate poison - // size, so that only members declared in this class are poisoned. - llvm::Value *OffsetPtr; - CharUnits::QuantityType PoisonSize; - ASTContext &Context = CGF.getContext(); - - llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( - CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). - getQuantity()); - - OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( - CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); - - PoisonSize = Layout.getSize().getQuantity() - - Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); - - llvm::Value *Args[] = { - CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), - llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; - - llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; - - llvm::FunctionType *FnType = - llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); - llvm::Value *Fn = - CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); - - // Disables tail call elimination, to prevent the current stack frame from - // disappearing from the stack trace. - CGF.CurFn->addFnAttr("disable-tail-calls", "true"); - CGF.EmitNounwindRuntimeCall(Fn, Args); -} - /// EmitDestructorBody - Emits the body of the current destructor. void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { const CXXDestructorDecl *Dtor = cast(CurGD.getDecl()); @@ -1492,12 +1446,6 @@ if (getLangOpts().AppleKext) CurFn->addFnAttr(llvm::Attribute::AlwaysInline); - // Insert memory-poisoning instrumentation, before final clean ups, - // to ensure this class's members are protected from invalid access. - if (CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor - && SanOpts.has(SanitizerKind::Memory)) - EmitDtorSanitizerCallback(*this, Dtor); - break; } @@ -1586,6 +1534,65 @@ flags.isForNormalCleanup() && useEHCleanupForArray); } }; + +class SanitizeDtor : public EHScopeStack::Cleanup { + const CXXDestructorDecl *Dtor; + public: + SanitizeDtor(const CXXDestructorDecl *Dtor) : Dtor(Dtor) {} + + // Generate function call for handling object poisoning, passing in + // references to 'this' and its size as arguments. + // Disables tail call elimination, to prevent the current stack frame + // from disappearing from the stack trace. + void Emit(CodeGenFunction &CGF, Flags flags) override { + + // check flags to determine if allowed to emit + // Insert memory-poisoning instrumentation, before final clean ups, + // to ensure this class's members are protected from invalid access. + if (!CGF.CGM.getCodeGenOpts().SanitizeMemoryUseAfterDtor + || !CGF.SanOpts.has(SanitizerKind::Memory)) + return; + + const ASTRecordLayout &Layout = + CGF.getContext().getASTRecordLayout(Dtor->getParent()); + + // Nothing to poison + if(Layout.getFieldCount() == 0) + return; + + // Construct pointer to region to begin poisoning, and calculate poison + // size, so that only members declared in this class are poisoned. + llvm::Value *OffsetPtr; + CharUnits::QuantityType PoisonSize; + ASTContext &Context = CGF.getContext(); + + llvm::ConstantInt *OffsetSizePtr = llvm::ConstantInt::get( + CGF.SizeTy, Context.toCharUnitsFromBits(Layout.getFieldOffset(0)). + getQuantity()); + + OffsetPtr = CGF.Builder.CreateGEP(CGF.Builder.CreateBitCast( + CGF.LoadCXXThis(), CGF.Int8PtrTy), OffsetSizePtr); + + PoisonSize = Layout.getNonVirtualSize().getQuantity() - + Context.toCharUnitsFromBits(Layout.getFieldOffset(0)).getQuantity(); + + llvm::Value *Args[] = { + CGF.Builder.CreateBitCast(OffsetPtr, CGF.VoidPtrTy), + llvm::ConstantInt::get(CGF.SizeTy, PoisonSize)}; + + llvm::Type *ArgTypes[] = {CGF.VoidPtrTy, CGF.SizeTy}; + + llvm::FunctionType *FnType = + llvm::FunctionType::get(CGF.VoidTy, ArgTypes, false); + llvm::Value *Fn = + CGF.CGM.CreateRuntimeFunction(FnType, "__sanitizer_dtor_callback"); + + // Disables tail call elimination, to prevent the current stack frame from + // disappearing from the stack trace. + CGF.CurFn->addFnAttr("disable-tail-calls", "true"); + CGF.EmitNounwindRuntimeCall(Fn, Args); + } +}; } /// \brief Emit all code that comes at the end of class's @@ -1658,6 +1665,8 @@ /*BaseIsVirtual*/ false); } + EHStack.pushCleanup(NormalCleanup, DD); + // Destroy direct fields. for (const auto *Field : ClassDecl->fields()) { QualType type = Field->getType();