diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 57 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Driver/SanitizerArgs.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 39 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 3 |
9 files changed, 76 insertions, 77 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 351dae9d4dd..71b305c773d 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2489,7 +2489,7 @@ void CodeGenFunction::EmitBitSetCodeForVCall(const CXXRecordDecl *RD, llvm::Value *VTable, SourceLocation Loc) { if (CGM.getCodeGenOpts().WholeProgramVTables && - !CGM.IsBitSetBlacklistedRecord(RD)) { + CGM.HasHiddenLTOVisibility(RD)) { llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(QualType(RD->getTypeForDecl(), 0)); llvm::Value *BitSetName = @@ -2565,7 +2565,12 @@ void CodeGenFunction::EmitVTablePtrCheck(const CXXRecordDecl *RD, llvm::Value *VTable, CFITypeCheckKind TCK, SourceLocation Loc) { - if (CGM.IsBitSetBlacklistedRecord(RD)) + if (!CGM.getCodeGenOpts().SanitizeCfiCrossDso && + !CGM.HasHiddenLTOVisibility(RD)) + return; + + std::string TypeName = RD->getQualifiedNameAsString(); + if (getContext().getSanitizerBlacklist().isBlacklistedType(TypeName)) return; SanitizerScope SanScope(this); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index f139e2c8504..478164e273b 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -902,34 +902,43 @@ void CodeGenModule::EmitDeferredVTables() { DeferredVTables.clear(); } -bool CodeGenModule::NeedVTableBitSets() { - return getCodeGenOpts().WholeProgramVTables || - getLangOpts().Sanitize.has(SanitizerKind::CFIVCall) || - getLangOpts().Sanitize.has(SanitizerKind::CFINVCall) || - getLangOpts().Sanitize.has(SanitizerKind::CFIDerivedCast) || - getLangOpts().Sanitize.has(SanitizerKind::CFIUnrelatedCast); -} +bool CodeGenModule::HasHiddenLTOVisibility(const CXXRecordDecl *RD) { + LinkageInfo LV = RD->getLinkageAndVisibility(); + if (!isExternallyVisible(LV.getLinkage())) + return true; -bool CodeGenModule::IsBitSetBlacklistedRecord(const CXXRecordDecl *RD) { - std::string TypeName = RD->getQualifiedNameAsString(); - auto isInBlacklist = [&](const SanitizerBlacklist &BL) { - if (RD->hasAttr<UuidAttr>() && BL.isBlacklistedType("attr:uuid")) - return true; + if (RD->hasAttr<LTOVisibilityPublicAttr>() || RD->hasAttr<UuidAttr>()) + return false; - return BL.isBlacklistedType(TypeName); - }; + if (getTriple().isOSBinFormatCOFF()) { + if (RD->hasAttr<DLLExportAttr>() || RD->hasAttr<DLLImportAttr>()) + return false; + } else { + if (LV.getVisibility() != HiddenVisibility) + return false; + } - return isInBlacklist(WholeProgramVTablesBlacklist) || - ((LangOpts.Sanitize.has(SanitizerKind::CFIVCall) || - LangOpts.Sanitize.has(SanitizerKind::CFINVCall) || - LangOpts.Sanitize.has(SanitizerKind::CFIDerivedCast) || - LangOpts.Sanitize.has(SanitizerKind::CFIUnrelatedCast)) && - isInBlacklist(getContext().getSanitizerBlacklist())); + if (getCodeGenOpts().LTOVisibilityPublicStd) { + const DeclContext *DC = RD; + while (1) { + auto *D = cast<Decl>(DC); + DC = DC->getParent(); + if (isa<TranslationUnitDecl>(DC->getRedeclContext())) { + if (auto *ND = dyn_cast<NamespaceDecl>(D)) + if (const IdentifierInfo *II = ND->getIdentifier()) + if (II->isStr("std") || II->isStr("stdext")) + return false; + break; + } + } + } + + return true; } void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, const VTableLayout &VTLayout) { - if (!NeedVTableBitSets()) + if (!getCodeGenOpts().PrepareForLTO) return; CharUnits PointerWidth = @@ -938,12 +947,8 @@ void CodeGenModule::EmitVTableBitSetEntries(llvm::GlobalVariable *VTable, typedef std::pair<const CXXRecordDecl *, unsigned> BSEntry; std::vector<BSEntry> BitsetEntries; // Create a bit set entry for each address point. - for (auto &&AP : VTLayout.getAddressPoints()) { - if (IsBitSetBlacklistedRecord(AP.first.getBase())) - continue; - + for (auto &&AP : VTLayout.getAddressPoints()) BitsetEntries.push_back(std::make_pair(AP.first.getBase(), AP.second)); - } // Sort the bit set entries for determinism. std::sort(BitsetEntries.begin(), BitsetEntries.end(), diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 64fe3652a9d..8ff99a6c404 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -88,9 +88,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO, PreprocessorOpts(PPO), CodeGenOpts(CGO), TheModule(M), Diags(diags), Target(C.getTargetInfo()), ABI(createCXXABI(*this)), VMContext(M.getContext()), Types(*this), VTables(*this), - SanitizerMD(new SanitizerMetadata(*this)), - WholeProgramVTablesBlacklist(CGO.WholeProgramVTablesBlacklistFiles, - C.getSourceManager()) { + SanitizerMD(new SanitizerMetadata(*this)) { // Initialize the type cache. llvm::LLVMContext &LLVMContext = M.getContext(); diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 34d1111889a..a75e4aa2a32 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -490,8 +490,6 @@ private: /// MDNodes. llvm::DenseMap<QualType, llvm::Metadata *> MetadataIdMap; - SanitizerBlacklist WholeProgramVTablesBlacklist; - public: CodeGenModule(ASTContext &C, const HeaderSearchOptions &headersearchopts, const PreprocessorOptions &ppopts, @@ -1115,12 +1113,10 @@ public: void EmitOMPDeclareReduction(const OMPDeclareReductionDecl *D, CodeGenFunction *CGF = nullptr); - /// Returns whether we need bit sets attached to vtables. - bool NeedVTableBitSets(); - - /// Returns whether the given record is blacklisted from whole-program - /// transformations (i.e. CFI or whole-program vtable optimization). - bool IsBitSetBlacklistedRecord(const CXXRecordDecl *RD); + /// Returns whether the given record has hidden LTO visibility and therefore + /// may participate in (single-module) CFI and whole-program vtable + /// optimization. + bool HasHiddenLTOVisibility(const CXXRecordDecl *RD); /// Emit bit set entries for the given vtable using the given layout if /// vptr CFI is enabled. diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index e578863bfc3..0e15f5054d8 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1503,7 +1503,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, const CXXRecordDecl *RD, llvm::GlobalVariable *VTable) { - if (!CGM.NeedVTableBitSets()) + if (!CGM.getCodeGenOpts().PrepareForLTO) return; llvm::NamedMDNode *BitsetsMD = @@ -1519,15 +1519,13 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, : CharUnits::Zero(); if (Info->PathToBaseWithVPtr.empty()) { - if (!CGM.IsBitSetBlacklistedRecord(RD)) - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); return; } // Add a bitset entry for the least derived base belonging to this vftable. - if (!CGM.IsBitSetBlacklistedRecord(Info->PathToBaseWithVPtr.back())) - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, - Info->PathToBaseWithVPtr.back()); + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, + Info->PathToBaseWithVPtr.back()); // Add a bitset entry for each derived class that is laid out at the same // offset as the least derived base. @@ -1545,12 +1543,11 @@ void MicrosoftCXXABI::emitVTableBitSetEntries(VPtrInfo *Info, Offset = VBI->second.VBaseOffset; if (!Offset.isZero()) return; - if (!CGM.IsBitSetBlacklistedRecord(DerivedRD)) - CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD); + CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, DerivedRD); } // Finally do the same for the most derived class. - if (Info->FullOffsetInMDC.isZero() && !CGM.IsBitSetBlacklistedRecord(RD)) + if (Info->FullOffsetInMDC.isZero()) CGM.CreateVTableBitSetEntry(BitsetsMD, VTable, AddressPoint, RD); } @@ -1819,7 +1816,7 @@ llvm::Value *MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, MicrosoftVTableContext::MethodVFTableLocation ML = CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD); - if (CGM.NeedVTableBitSets()) + if (CGM.getCodeGenOpts().PrepareForLTO) CGF.EmitBitSetCodeForVCall(getClassAtVTableLocation(getContext(), GD, ML), VTable, Loc); diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 50a93a8d431..6f19a2fa96b 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -39,6 +39,7 @@ enum : SanitizerMask { TrappingSupported = (Undefined & ~Vptr) | UnsignedIntegerOverflow | LocalBounds | CFI, TrappingDefault = CFI, + CFIClasses = CFIVCall | CFINVCall | CFIDerivedCast | CFIUnrelatedCast, }; enum CoverageFeature { @@ -560,6 +561,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime) || D.CCCIsCXX(); + // Require -fvisibility= flag on non-Windows if vptr CFI is enabled. + if ((Kinds & CFIClasses) && !TC.getTriple().isOSWindows() && + !Args.hasArg(options::OPT_fvisibility_EQ)) { + D.Diag(clang::diag::err_drv_argument_only_allowed_with) + << lastArgumentForMask(D, Args, Kinds & CFIClasses) + << "-fvisibility="; + } + // Finally, initialize the set of available and recoverable sanitizers. Sanitizers.Mask |= Kinds; RecoverableSanitizers.Mask |= RecoverableKinds; diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 74ac8070561..f0199aab274 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -4429,32 +4429,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-ffunction-sections"); } - if (Args.hasFlag(options::OPT_fwhole_program_vtables, - options::OPT_fno_whole_program_vtables, false)) { - if (!D.isUsingLTO()) - D.Diag(diag::err_drv_argument_only_allowed_with) - << "-fwhole-program-vtables" - << "-flto"; - CmdArgs.push_back("-fwhole-program-vtables"); - - clang::SmallString<64> Path(D.ResourceDir); - llvm::sys::path::append(Path, "vtables_blacklist.txt"); - if (llvm::sys::fs::exists(Path)) { - SmallString<64> BlacklistOpt("-fwhole-program-vtables-blacklist="); - BlacklistOpt += Path.str(); - CmdArgs.push_back(Args.MakeArgString(BlacklistOpt)); - } - - for (const Arg *A : - Args.filtered(options::OPT_fwhole_program_vtables_blacklist_EQ)) { - A->claim(); - if (!llvm::sys::fs::exists(A->getValue())) - D.Diag(clang::diag::err_drv_no_such_file) << A->getValue(); - } - - Args.AddAllArgs(CmdArgs, options::OPT_fwhole_program_vtables_blacklist_EQ); - } - if (Args.hasFlag(options::OPT_fdata_sections, options::OPT_fno_data_sections, UseSeparateSections)) { CmdArgs.push_back("-fdata-sections"); @@ -5785,6 +5759,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(I->getFilename()); } + bool WholeProgramVTables = + Args.hasFlag(options::OPT_fwhole_program_vtables, + options::OPT_fno_whole_program_vtables, false); + if (WholeProgramVTables) { + if (!D.isUsingLTO()) + D.Diag(diag::err_drv_argument_only_allowed_with) + << "-fwhole-program-vtables" + << "-flto"; + CmdArgs.push_back("-fwhole-program-vtables"); + } + // Finally add the compile command to the compilation. if (Args.hasArg(options::OPT__SLASH_fallback) && Output.getType() == types::TY_Object && @@ -6048,11 +6033,13 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, if (Args.hasArg(options::OPT__SLASH_LDd)) CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); + CmdArgs.push_back("-flto-visibility-public-std"); FlagForCRT = "--dependent-lib=libcmt"; break; case options::OPT__SLASH_MTd: CmdArgs.push_back("-D_DEBUG"); CmdArgs.push_back("-D_MT"); + CmdArgs.push_back("-flto-visibility-public-std"); FlagForCRT = "--dependent-lib=libcmtd"; break; default: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 0c4d5c71d5c..4bef159f3bf 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -482,8 +482,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.EmitCodeView = Args.hasArg(OPT_gcodeview); Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); - Opts.WholeProgramVTablesBlacklistFiles = - Args.getAllArgValues(OPT_fwhole_program_vtables_blacklist_EQ); + Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); Opts.DebugExplicitImport = Triple.isPS4CPU(); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 0ba9799d042..9bf5fc9e36d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5749,6 +5749,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_InternalLinkage: handleInternalLinkageAttr(S, D, Attr); break; + case AttributeList::AT_LTOVisibilityPublic: + handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, Attr); + break; // Microsoft attributes: case AttributeList::AT_MSNoVTable: |