Path: blob/main/contrib/llvm-project/clang/lib/Driver/SanitizerArgs.cpp
35233 views
//===--- SanitizerArgs.cpp - Arguments for sanitizer tools ---------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "clang/Driver/SanitizerArgs.h"8#include "ToolChains/CommonArgs.h"9#include "clang/Basic/Sanitizers.h"10#include "clang/Driver/Driver.h"11#include "clang/Driver/DriverDiagnostic.h"12#include "clang/Driver/Options.h"13#include "clang/Driver/ToolChain.h"14#include "llvm/ADT/StringExtras.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/ADT/StringSwitch.h"17#include "llvm/Support/Path.h"18#include "llvm/Support/SpecialCaseList.h"19#include "llvm/Support/VirtualFileSystem.h"20#include "llvm/TargetParser/AArch64TargetParser.h"21#include "llvm/TargetParser/RISCVTargetParser.h"22#include "llvm/TargetParser/TargetParser.h"23#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"24#include <memory>2526using namespace clang;27using namespace clang::driver;28using namespace llvm::opt;2930static const SanitizerMask NeedsUbsanRt =31SanitizerKind::Undefined | SanitizerKind::Integer |32SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |33SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |34SanitizerKind::ObjCCast;35static const SanitizerMask NeedsUbsanCxxRt =36SanitizerKind::Vptr | SanitizerKind::CFI;37static const SanitizerMask NotAllowedWithTrap = SanitizerKind::Vptr;38static const SanitizerMask NotAllowedWithMinimalRuntime = SanitizerKind::Vptr;39static const SanitizerMask NotAllowedWithExecuteOnly =40SanitizerKind::Function | SanitizerKind::KCFI;41static const SanitizerMask NeedsUnwindTables =42SanitizerKind::Address | SanitizerKind::HWAddress | SanitizerKind::Thread |43SanitizerKind::Memory | SanitizerKind::DataFlow |44SanitizerKind::NumericalStability;45static const SanitizerMask SupportsCoverage =46SanitizerKind::Address | SanitizerKind::HWAddress |47SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress |48SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |49SanitizerKind::MemtagGlobals | SanitizerKind::Memory |50SanitizerKind::KernelMemory | SanitizerKind::Leak |51SanitizerKind::Undefined | SanitizerKind::Integer | SanitizerKind::Bounds |52SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |53SanitizerKind::DataFlow | SanitizerKind::Fuzzer |54SanitizerKind::FuzzerNoLink | SanitizerKind::FloatDivideByZero |55SanitizerKind::SafeStack | SanitizerKind::ShadowCallStack |56SanitizerKind::Thread | SanitizerKind::ObjCCast | SanitizerKind::KCFI |57SanitizerKind::NumericalStability;58static const SanitizerMask RecoverableByDefault =59SanitizerKind::Undefined | SanitizerKind::Integer |60SanitizerKind::ImplicitConversion | SanitizerKind::Nullability |61SanitizerKind::FloatDivideByZero | SanitizerKind::ObjCCast;62static const SanitizerMask Unrecoverable =63SanitizerKind::Unreachable | SanitizerKind::Return;64static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress |65SanitizerKind::KernelHWAddress |66SanitizerKind::KCFI;67static const SanitizerMask NeedsLTO = SanitizerKind::CFI;68static const SanitizerMask TrappingSupported =69(SanitizerKind::Undefined & ~SanitizerKind::Vptr) | SanitizerKind::Integer |70SanitizerKind::Nullability | SanitizerKind::LocalBounds |71SanitizerKind::CFI | SanitizerKind::FloatDivideByZero |72SanitizerKind::ObjCCast;73static const SanitizerMask TrappingDefault = SanitizerKind::CFI;74static const SanitizerMask CFIClasses =75SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |76SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |77SanitizerKind::CFIUnrelatedCast;78static const SanitizerMask CompatibleWithMinimalRuntime =79TrappingSupported | SanitizerKind::Scudo | SanitizerKind::ShadowCallStack |80SanitizerKind::MemtagStack | SanitizerKind::MemtagHeap |81SanitizerKind::MemtagGlobals | SanitizerKind::KCFI;8283enum CoverageFeature {84CoverageFunc = 1 << 0,85CoverageBB = 1 << 1,86CoverageEdge = 1 << 2,87CoverageIndirCall = 1 << 3,88CoverageTraceBB = 1 << 4, // Deprecated.89CoverageTraceCmp = 1 << 5,90CoverageTraceDiv = 1 << 6,91CoverageTraceGep = 1 << 7,92Coverage8bitCounters = 1 << 8, // Deprecated.93CoverageTracePC = 1 << 9,94CoverageTracePCGuard = 1 << 10,95CoverageNoPrune = 1 << 11,96CoverageInline8bitCounters = 1 << 12,97CoveragePCTable = 1 << 13,98CoverageStackDepth = 1 << 14,99CoverageInlineBoolFlag = 1 << 15,100CoverageTraceLoads = 1 << 16,101CoverageTraceStores = 1 << 17,102CoverageControlFlow = 1 << 18,103};104105enum BinaryMetadataFeature {106BinaryMetadataCovered = 1 << 0,107BinaryMetadataAtomics = 1 << 1,108BinaryMetadataUAR = 1 << 2,109};110111/// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any112/// invalid components. Returns a SanitizerMask.113static SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,114bool DiagnoseErrors);115116/// Parse -f(no-)?sanitize-coverage= flag values, diagnosing any invalid117/// components. Returns OR of members of \c CoverageFeature enumeration.118static int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,119bool DiagnoseErrors);120121/// Parse -f(no-)?sanitize-metadata= flag values, diagnosing any invalid122/// components. Returns OR of members of \c BinaryMetadataFeature enumeration.123static int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,124bool DiagnoseErrors);125126/// Produce an argument string from ArgList \p Args, which shows how it127/// provides some sanitizer kind from \p Mask. For example, the argument list128/// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt129/// would produce "-fsanitize=vptr".130static std::string lastArgumentForMask(const Driver &D,131const llvm::opt::ArgList &Args,132SanitizerMask Mask);133134/// Produce an argument string from argument \p A, which shows how it provides135/// a value in \p Mask. For instance, the argument136/// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce137/// "-fsanitize=alignment".138static std::string describeSanitizeArg(const llvm::opt::Arg *A,139SanitizerMask Mask);140141/// Produce a string containing comma-separated names of sanitizers in \p142/// Sanitizers set.143static std::string toString(const clang::SanitizerSet &Sanitizers);144145/// Return true if an execute-only target disallows data access to code146/// sections.147static bool isExecuteOnlyTarget(const llvm::Triple &Triple,148const llvm::opt::ArgList &Args) {149if (Triple.isPS5())150return true;151return Args.hasFlagNoClaim(options::OPT_mexecute_only,152options::OPT_mno_execute_only, false);153}154155static void validateSpecialCaseListFormat(const Driver &D,156std::vector<std::string> &SCLFiles,157unsigned MalformedSCLErrorDiagID,158bool DiagnoseErrors) {159if (SCLFiles.empty())160return;161162std::string BLError;163std::unique_ptr<llvm::SpecialCaseList> SCL(164llvm::SpecialCaseList::create(SCLFiles, D.getVFS(), BLError));165if (!SCL.get() && DiagnoseErrors)166D.Diag(MalformedSCLErrorDiagID) << BLError;167}168169static void addDefaultIgnorelists(const Driver &D, SanitizerMask Kinds,170std::vector<std::string> &IgnorelistFiles,171bool DiagnoseErrors) {172struct Ignorelist {173const char *File;174SanitizerMask Mask;175} Ignorelists[] = {{"asan_ignorelist.txt", SanitizerKind::Address},176{"hwasan_ignorelist.txt", SanitizerKind::HWAddress},177{"memtag_ignorelist.txt", SanitizerKind::MemTag},178{"msan_ignorelist.txt", SanitizerKind::Memory},179{"nsan_ignorelist.txt", SanitizerKind::NumericalStability},180{"tsan_ignorelist.txt", SanitizerKind::Thread},181{"dfsan_abilist.txt", SanitizerKind::DataFlow},182{"cfi_ignorelist.txt", SanitizerKind::CFI},183{"ubsan_ignorelist.txt",184SanitizerKind::Undefined | SanitizerKind::Integer |185SanitizerKind::Nullability |186SanitizerKind::FloatDivideByZero}};187188for (auto BL : Ignorelists) {189if (!(Kinds & BL.Mask))190continue;191192clang::SmallString<64> Path(D.ResourceDir);193llvm::sys::path::append(Path, "share", BL.File);194if (D.getVFS().exists(Path))195IgnorelistFiles.push_back(std::string(Path));196else if (BL.Mask == SanitizerKind::CFI && DiagnoseErrors)197// If cfi_ignorelist.txt cannot be found in the resource dir, driver198// should fail.199D.Diag(clang::diag::err_drv_missing_sanitizer_ignorelist) << Path;200}201validateSpecialCaseListFormat(202D, IgnorelistFiles, clang::diag::err_drv_malformed_sanitizer_ignorelist,203DiagnoseErrors);204}205206/// Parse -f(no-)?sanitize-(coverage-)?(allow|ignore)list argument's values,207/// diagnosing any invalid file paths and validating special case list format.208static void parseSpecialCaseListArg(const Driver &D,209const llvm::opt::ArgList &Args,210std::vector<std::string> &SCLFiles,211llvm::opt::OptSpecifier SCLOptionID,212llvm::opt::OptSpecifier NoSCLOptionID,213unsigned MalformedSCLErrorDiagID,214bool DiagnoseErrors) {215for (const auto *Arg : Args) {216// Match -fsanitize-(coverage-)?(allow|ignore)list.217if (Arg->getOption().matches(SCLOptionID)) {218Arg->claim();219std::string SCLPath = Arg->getValue();220if (D.getVFS().exists(SCLPath)) {221SCLFiles.push_back(SCLPath);222} else if (DiagnoseErrors) {223D.Diag(clang::diag::err_drv_no_such_file) << SCLPath;224}225// Match -fno-sanitize-ignorelist.226} else if (Arg->getOption().matches(NoSCLOptionID)) {227Arg->claim();228SCLFiles.clear();229}230}231validateSpecialCaseListFormat(D, SCLFiles, MalformedSCLErrorDiagID,232DiagnoseErrors);233}234235/// Sets group bits for every group that has at least one representative already236/// enabled in \p Kinds.237static SanitizerMask setGroupBits(SanitizerMask Kinds) {238#define SANITIZER(NAME, ID)239#define SANITIZER_GROUP(NAME, ID, ALIAS) \240if (Kinds & SanitizerKind::ID) \241Kinds |= SanitizerKind::ID##Group;242#include "clang/Basic/Sanitizers.def"243return Kinds;244}245246static SanitizerMask parseSanitizeTrapArgs(const Driver &D,247const llvm::opt::ArgList &Args,248bool DiagnoseErrors) {249SanitizerMask TrapRemove; // During the loop below, the accumulated set of250// sanitizers disabled by the current sanitizer251// argument or any argument after it.252SanitizerMask TrappingKinds;253SanitizerMask TrappingSupportedWithGroups = setGroupBits(TrappingSupported);254255for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {256if (Arg->getOption().matches(options::OPT_fsanitize_trap_EQ)) {257Arg->claim();258SanitizerMask Add = parseArgValues(D, Arg, true);259Add &= ~TrapRemove;260SanitizerMask InvalidValues = Add & ~TrappingSupportedWithGroups;261if (InvalidValues && DiagnoseErrors) {262SanitizerSet S;263S.Mask = InvalidValues;264D.Diag(diag::err_drv_unsupported_option_argument)265<< Arg->getSpelling() << toString(S);266}267TrappingKinds |= expandSanitizerGroups(Add) & ~TrapRemove;268} else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) {269Arg->claim();270TrapRemove |=271expandSanitizerGroups(parseArgValues(D, Arg, DiagnoseErrors));272}273}274275// Apply default trapping behavior.276TrappingKinds |= TrappingDefault & ~TrapRemove;277278return TrappingKinds;279}280281bool SanitizerArgs::needsFuzzerInterceptors() const {282return needsFuzzer() && !needsAsanRt() && !needsTsanRt() && !needsMsanRt();283}284285bool SanitizerArgs::needsUbsanRt() const {286// All of these include ubsan.287if (needsAsanRt() || needsMsanRt() || needsNsanRt() || needsHwasanRt() ||288needsTsanRt() || needsDfsanRt() || needsLsanRt() || needsCfiDiagRt() ||289(needsScudoRt() && !requiresMinimalRuntime()))290return false;291292return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) ||293CoverageFeatures;294}295296bool SanitizerArgs::needsCfiRt() const {297return !(Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&298CfiCrossDso && !ImplicitCfiRuntime;299}300301bool SanitizerArgs::needsCfiDiagRt() const {302return (Sanitizers.Mask & SanitizerKind::CFI & ~TrapSanitizers.Mask) &&303CfiCrossDso && !ImplicitCfiRuntime;304}305306bool SanitizerArgs::requiresPIE() const { return NeedPIE; }307308bool SanitizerArgs::needsUnwindTables() const {309return static_cast<bool>(Sanitizers.Mask & NeedsUnwindTables);310}311312bool SanitizerArgs::needsLTO() const {313return static_cast<bool>(Sanitizers.Mask & NeedsLTO);314}315316SanitizerArgs::SanitizerArgs(const ToolChain &TC,317const llvm::opt::ArgList &Args,318bool DiagnoseErrors) {319SanitizerMask AllRemove; // During the loop below, the accumulated set of320// sanitizers disabled by the current sanitizer321// argument or any argument after it.322SanitizerMask AllAddedKinds; // Mask of all sanitizers ever enabled by323// -fsanitize= flags (directly or via group324// expansion), some of which may be disabled325// later. Used to carefully prune326// unused-argument diagnostics.327SanitizerMask DiagnosedKinds; // All Kinds we have diagnosed up to now.328// Used to deduplicate diagnostics.329SanitizerMask Kinds;330const SanitizerMask Supported = setGroupBits(TC.getSupportedSanitizers());331332CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso,333options::OPT_fno_sanitize_cfi_cross_dso, false);334335ToolChain::RTTIMode RTTIMode = TC.getRTTIMode();336337const Driver &D = TC.getDriver();338SanitizerMask TrappingKinds = parseSanitizeTrapArgs(D, Args, DiagnoseErrors);339SanitizerMask InvalidTrappingKinds = TrappingKinds & NotAllowedWithTrap;340341MinimalRuntime =342Args.hasFlag(options::OPT_fsanitize_minimal_runtime,343options::OPT_fno_sanitize_minimal_runtime, MinimalRuntime);344345// The object size sanitizer should not be enabled at -O0.346Arg *OptLevel = Args.getLastArg(options::OPT_O_Group);347bool RemoveObjectSizeAtO0 =348!OptLevel || OptLevel->getOption().matches(options::OPT_O0);349350for (const llvm::opt::Arg *Arg : llvm::reverse(Args)) {351if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {352Arg->claim();353SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);354355if (RemoveObjectSizeAtO0) {356AllRemove |= SanitizerKind::ObjectSize;357358// The user explicitly enabled the object size sanitizer. Warn359// that this does nothing at -O0.360if ((Add & SanitizerKind::ObjectSize) && DiagnoseErrors)361D.Diag(diag::warn_drv_object_size_disabled_O0)362<< Arg->getAsString(Args);363}364365AllAddedKinds |= expandSanitizerGroups(Add);366367// Avoid diagnosing any sanitizer which is disabled later.368Add &= ~AllRemove;369// At this point we have not expanded groups, so any unsupported370// sanitizers in Add are those which have been explicitly enabled.371// Diagnose them.372if (SanitizerMask KindsToDiagnose =373Add & InvalidTrappingKinds & ~DiagnosedKinds) {374if (DiagnoseErrors) {375std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);376D.Diag(diag::err_drv_argument_not_allowed_with)377<< Desc << "-fsanitize-trap=undefined";378}379DiagnosedKinds |= KindsToDiagnose;380}381Add &= ~InvalidTrappingKinds;382383if (MinimalRuntime) {384if (SanitizerMask KindsToDiagnose =385Add & NotAllowedWithMinimalRuntime & ~DiagnosedKinds) {386if (DiagnoseErrors) {387std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);388D.Diag(diag::err_drv_argument_not_allowed_with)389<< Desc << "-fsanitize-minimal-runtime";390}391DiagnosedKinds |= KindsToDiagnose;392}393Add &= ~NotAllowedWithMinimalRuntime;394}395396if (llvm::opt::Arg *A = Args.getLastArg(options::OPT_mcmodel_EQ)) {397StringRef CM = A->getValue();398if (CM != "small" &&399(Add & SanitizerKind::Function & ~DiagnosedKinds)) {400if (DiagnoseErrors)401D.Diag(diag::err_drv_argument_only_allowed_with)402<< "-fsanitize=function"403<< "-mcmodel=small";404Add &= ~SanitizerKind::Function;405DiagnosedKinds |= SanitizerKind::Function;406}407}408// -fsanitize=function and -fsanitize=kcfi instrument indirect function409// calls to load a type hash before the function label. Therefore, an410// execute-only target doesn't support the function and kcfi sanitizers.411const llvm::Triple &Triple = TC.getTriple();412if (isExecuteOnlyTarget(Triple, Args)) {413if (SanitizerMask KindsToDiagnose =414Add & NotAllowedWithExecuteOnly & ~DiagnosedKinds) {415if (DiagnoseErrors) {416std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);417D.Diag(diag::err_drv_argument_not_allowed_with)418<< Desc << Triple.str();419}420DiagnosedKinds |= KindsToDiagnose;421}422Add &= ~NotAllowedWithExecuteOnly;423}424425// FIXME: Make CFI on member function calls compatible with cross-DSO CFI.426// There are currently two problems:427// - Virtual function call checks need to pass a pointer to the function428// address to llvm.type.test and a pointer to the address point to the429// diagnostic function. Currently we pass the same pointer to both430// places.431// - Non-virtual function call checks may need to check multiple type432// identifiers.433// Fixing both of those may require changes to the cross-DSO CFI434// interface.435if (CfiCrossDso && (Add & SanitizerKind::CFIMFCall & ~DiagnosedKinds)) {436if (DiagnoseErrors)437D.Diag(diag::err_drv_argument_not_allowed_with)438<< "-fsanitize=cfi-mfcall"439<< "-fsanitize-cfi-cross-dso";440Add &= ~SanitizerKind::CFIMFCall;441DiagnosedKinds |= SanitizerKind::CFIMFCall;442}443444if (SanitizerMask KindsToDiagnose = Add & ~Supported & ~DiagnosedKinds) {445if (DiagnoseErrors) {446std::string Desc = describeSanitizeArg(Arg, KindsToDiagnose);447D.Diag(diag::err_drv_unsupported_opt_for_target)448<< Desc << TC.getTriple().str();449}450DiagnosedKinds |= KindsToDiagnose;451}452Add &= Supported;453454// Test for -fno-rtti + explicit -fsanitizer=vptr before expanding groups455// so we don't error out if -fno-rtti and -fsanitize=undefined were456// passed.457if ((Add & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {458if (const llvm::opt::Arg *NoRTTIArg = TC.getRTTIArg()) {459assert(NoRTTIArg->getOption().matches(options::OPT_fno_rtti) &&460"RTTI disabled without -fno-rtti option?");461// The user explicitly passed -fno-rtti with -fsanitize=vptr, but462// the vptr sanitizer requires RTTI, so this is a user error.463if (DiagnoseErrors)464D.Diag(diag::err_drv_argument_not_allowed_with)465<< "-fsanitize=vptr" << NoRTTIArg->getAsString(Args);466} else {467// The vptr sanitizer requires RTTI, but RTTI is disabled (by468// default). Warn that the vptr sanitizer is being disabled.469if (DiagnoseErrors)470D.Diag(diag::warn_drv_disabling_vptr_no_rtti_default);471}472473// Take out the Vptr sanitizer from the enabled sanitizers474AllRemove |= SanitizerKind::Vptr;475}476477Add = expandSanitizerGroups(Add);478// Group expansion may have enabled a sanitizer which is disabled later.479Add &= ~AllRemove;480// Silently discard any unsupported sanitizers implicitly enabled through481// group expansion.482Add &= ~InvalidTrappingKinds;483if (MinimalRuntime) {484Add &= ~NotAllowedWithMinimalRuntime;485}486// NotAllowedWithExecuteOnly is silently discarded on an execute-only487// target if implicitly enabled through group expansion.488if (isExecuteOnlyTarget(Triple, Args))489Add &= ~NotAllowedWithExecuteOnly;490if (CfiCrossDso)491Add &= ~SanitizerKind::CFIMFCall;492// -fsanitize=undefined does not expand to signed-integer-overflow in493// -fwrapv (implied by -fno-strict-overflow) mode.494if (Add & SanitizerKind::UndefinedGroup) {495bool S = Args.hasFlagNoClaim(options::OPT_fno_strict_overflow,496options::OPT_fstrict_overflow, false);497if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))498Add &= ~SanitizerKind::SignedIntegerOverflow;499}500Add &= Supported;501502if (Add & SanitizerKind::Fuzzer)503Add |= SanitizerKind::FuzzerNoLink;504505// Enable coverage if the fuzzing flag is set.506if (Add & SanitizerKind::FuzzerNoLink) {507CoverageFeatures |= CoverageInline8bitCounters | CoverageIndirCall |508CoverageTraceCmp | CoveragePCTable;509// Due to TLS differences, stack depth tracking is only enabled on Linux510if (TC.getTriple().isOSLinux())511CoverageFeatures |= CoverageStackDepth;512}513514Kinds |= Add;515} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {516Arg->claim();517SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);518AllRemove |= expandSanitizerGroups(Remove);519}520}521522std::pair<SanitizerMask, SanitizerMask> IncompatibleGroups[] = {523std::make_pair(SanitizerKind::Address,524SanitizerKind::Thread | SanitizerKind::Memory),525std::make_pair(SanitizerKind::Thread, SanitizerKind::Memory),526std::make_pair(SanitizerKind::Leak,527SanitizerKind::Thread | SanitizerKind::Memory),528std::make_pair(SanitizerKind::KernelAddress,529SanitizerKind::Address | SanitizerKind::Leak |530SanitizerKind::Thread | SanitizerKind::Memory),531std::make_pair(SanitizerKind::HWAddress,532SanitizerKind::Address | SanitizerKind::Thread |533SanitizerKind::Memory | SanitizerKind::KernelAddress),534std::make_pair(SanitizerKind::Scudo,535SanitizerKind::Address | SanitizerKind::HWAddress |536SanitizerKind::Leak | SanitizerKind::Thread |537SanitizerKind::Memory | SanitizerKind::KernelAddress),538std::make_pair(SanitizerKind::SafeStack,539(TC.getTriple().isOSFuchsia() ? SanitizerMask()540: SanitizerKind::Leak) |541SanitizerKind::Address | SanitizerKind::HWAddress |542SanitizerKind::Thread | SanitizerKind::Memory |543SanitizerKind::KernelAddress),544std::make_pair(SanitizerKind::KernelHWAddress,545SanitizerKind::Address | SanitizerKind::HWAddress |546SanitizerKind::Leak | SanitizerKind::Thread |547SanitizerKind::Memory | SanitizerKind::KernelAddress |548SanitizerKind::SafeStack),549std::make_pair(SanitizerKind::KernelMemory,550SanitizerKind::Address | SanitizerKind::HWAddress |551SanitizerKind::Leak | SanitizerKind::Thread |552SanitizerKind::Memory | SanitizerKind::KernelAddress |553SanitizerKind::Scudo | SanitizerKind::SafeStack),554std::make_pair(SanitizerKind::MemTag,555SanitizerKind::Address | SanitizerKind::KernelAddress |556SanitizerKind::HWAddress |557SanitizerKind::KernelHWAddress),558std::make_pair(SanitizerKind::KCFI, SanitizerKind::Function)};559// Enable toolchain specific default sanitizers if not explicitly disabled.560SanitizerMask Default = TC.getDefaultSanitizers() & ~AllRemove;561562// Disable default sanitizers that are incompatible with explicitly requested563// ones.564for (auto G : IncompatibleGroups) {565SanitizerMask Group = G.first;566if ((Default & Group) && (Kinds & G.second))567Default &= ~Group;568}569570Kinds |= Default;571572// We disable the vptr sanitizer if it was enabled by group expansion but RTTI573// is disabled.574if ((Kinds & SanitizerKind::Vptr) && (RTTIMode == ToolChain::RM_Disabled)) {575Kinds &= ~SanitizerKind::Vptr;576}577578// Check that LTO is enabled if we need it.579if ((Kinds & NeedsLTO) && !D.isUsingLTO() && DiagnoseErrors) {580D.Diag(diag::err_drv_argument_only_allowed_with)581<< lastArgumentForMask(D, Args, Kinds & NeedsLTO) << "-flto";582}583584if ((Kinds & SanitizerKind::ShadowCallStack) && TC.getTriple().isAArch64() &&585!llvm::AArch64::isX18ReservedByDefault(TC.getTriple()) &&586!Args.hasArg(options::OPT_ffixed_x18) && DiagnoseErrors) {587D.Diag(diag::err_drv_argument_only_allowed_with)588<< lastArgumentForMask(D, Args, Kinds & SanitizerKind::ShadowCallStack)589<< "-ffixed-x18";590}591592// Report error if there are non-trapping sanitizers that require593// c++abi-specific parts of UBSan runtime, and they are not provided by the594// toolchain. We don't have a good way to check the latter, so we just595// check if the toolchan supports vptr.596if (~Supported & SanitizerKind::Vptr) {597SanitizerMask KindsToDiagnose = Kinds & ~TrappingKinds & NeedsUbsanCxxRt;598// The runtime library supports the Microsoft C++ ABI, but only well enough599// for CFI. FIXME: Remove this once we support vptr on Windows.600if (TC.getTriple().isOSWindows())601KindsToDiagnose &= ~SanitizerKind::CFI;602if (KindsToDiagnose) {603SanitizerSet S;604S.Mask = KindsToDiagnose;605if (DiagnoseErrors)606D.Diag(diag::err_drv_unsupported_opt_for_target)607<< ("-fno-sanitize-trap=" + toString(S)) << TC.getTriple().str();608Kinds &= ~KindsToDiagnose;609}610}611612// Warn about incompatible groups of sanitizers.613for (auto G : IncompatibleGroups) {614SanitizerMask Group = G.first;615if (Kinds & Group) {616if (SanitizerMask Incompatible = Kinds & G.second) {617if (DiagnoseErrors)618D.Diag(clang::diag::err_drv_argument_not_allowed_with)619<< lastArgumentForMask(D, Args, Group)620<< lastArgumentForMask(D, Args, Incompatible);621Kinds &= ~Incompatible;622}623}624}625// FIXME: Currently -fsanitize=leak is silently ignored in the presence of626// -fsanitize=address. Perhaps it should print an error, or perhaps627// -f(-no)sanitize=leak should change whether leak detection is enabled by628// default in ASan?629630// Parse -f(no-)?sanitize-recover flags.631SanitizerMask RecoverableKinds = RecoverableByDefault | AlwaysRecoverable;632SanitizerMask DiagnosedUnrecoverableKinds;633SanitizerMask DiagnosedAlwaysRecoverableKinds;634for (const auto *Arg : Args) {635if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) {636SanitizerMask Add = parseArgValues(D, Arg, DiagnoseErrors);637// Report error if user explicitly tries to recover from unrecoverable638// sanitizer.639if (SanitizerMask KindsToDiagnose =640Add & Unrecoverable & ~DiagnosedUnrecoverableKinds) {641SanitizerSet SetToDiagnose;642SetToDiagnose.Mask |= KindsToDiagnose;643if (DiagnoseErrors)644D.Diag(diag::err_drv_unsupported_option_argument)645<< Arg->getSpelling() << toString(SetToDiagnose);646DiagnosedUnrecoverableKinds |= KindsToDiagnose;647}648RecoverableKinds |= expandSanitizerGroups(Add);649Arg->claim();650} else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover_EQ)) {651SanitizerMask Remove = parseArgValues(D, Arg, DiagnoseErrors);652// Report error if user explicitly tries to disable recovery from653// always recoverable sanitizer.654if (SanitizerMask KindsToDiagnose =655Remove & AlwaysRecoverable & ~DiagnosedAlwaysRecoverableKinds) {656SanitizerSet SetToDiagnose;657SetToDiagnose.Mask |= KindsToDiagnose;658if (DiagnoseErrors)659D.Diag(diag::err_drv_unsupported_option_argument)660<< Arg->getSpelling() << toString(SetToDiagnose);661DiagnosedAlwaysRecoverableKinds |= KindsToDiagnose;662}663RecoverableKinds &= ~expandSanitizerGroups(Remove);664Arg->claim();665}666}667RecoverableKinds &= Kinds;668RecoverableKinds &= ~Unrecoverable;669670TrappingKinds &= Kinds;671RecoverableKinds &= ~TrappingKinds;672673// Setup ignorelist files.674// Add default ignorelist from resource directory for activated sanitizers,675// and validate special case lists format.676if (!Args.hasArgNoClaim(options::OPT_fno_sanitize_ignorelist))677addDefaultIgnorelists(D, Kinds, SystemIgnorelistFiles, DiagnoseErrors);678679// Parse -f(no-)?sanitize-ignorelist options.680// This also validates special case lists format.681parseSpecialCaseListArg(682D, Args, UserIgnorelistFiles, options::OPT_fsanitize_ignorelist_EQ,683options::OPT_fno_sanitize_ignorelist,684clang::diag::err_drv_malformed_sanitizer_ignorelist, DiagnoseErrors);685686// Parse -f[no-]sanitize-memory-track-origins[=level] options.687if (AllAddedKinds & SanitizerKind::Memory) {688if (Arg *A =689Args.getLastArg(options::OPT_fsanitize_memory_track_origins_EQ,690options::OPT_fno_sanitize_memory_track_origins)) {691if (!A->getOption().matches(692options::OPT_fno_sanitize_memory_track_origins)) {693StringRef S = A->getValue();694if (S.getAsInteger(0, MsanTrackOrigins) || MsanTrackOrigins < 0 ||695MsanTrackOrigins > 2) {696if (DiagnoseErrors)697D.Diag(clang::diag::err_drv_invalid_value)698<< A->getAsString(Args) << S;699}700}701}702MsanUseAfterDtor = Args.hasFlag(703options::OPT_fsanitize_memory_use_after_dtor,704options::OPT_fno_sanitize_memory_use_after_dtor, MsanUseAfterDtor);705MsanParamRetval = Args.hasFlag(706options::OPT_fsanitize_memory_param_retval,707options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);708} else if (AllAddedKinds & SanitizerKind::KernelMemory) {709MsanUseAfterDtor = false;710MsanParamRetval = Args.hasFlag(711options::OPT_fsanitize_memory_param_retval,712options::OPT_fno_sanitize_memory_param_retval, MsanParamRetval);713} else {714MsanUseAfterDtor = false;715MsanParamRetval = false;716}717718if (AllAddedKinds & SanitizerKind::MemTag) {719StringRef S =720Args.getLastArgValue(options::OPT_fsanitize_memtag_mode_EQ, "sync");721if (S == "async" || S == "sync") {722MemtagMode = S.str();723} else {724D.Diag(clang::diag::err_drv_invalid_value_with_suggestion)725<< "-fsanitize-memtag-mode=" << S << "{async, sync}";726MemtagMode = "sync";727}728}729730if (AllAddedKinds & SanitizerKind::Thread) {731TsanMemoryAccess = Args.hasFlag(732options::OPT_fsanitize_thread_memory_access,733options::OPT_fno_sanitize_thread_memory_access, TsanMemoryAccess);734TsanFuncEntryExit = Args.hasFlag(735options::OPT_fsanitize_thread_func_entry_exit,736options::OPT_fno_sanitize_thread_func_entry_exit, TsanFuncEntryExit);737TsanAtomics =738Args.hasFlag(options::OPT_fsanitize_thread_atomics,739options::OPT_fno_sanitize_thread_atomics, TsanAtomics);740}741742if (AllAddedKinds & SanitizerKind::CFI) {743// Without PIE, external function address may resolve to a PLT record, which744// can not be verified by the target module.745NeedPIE |= CfiCrossDso;746CfiICallGeneralizePointers =747Args.hasArg(options::OPT_fsanitize_cfi_icall_generalize_pointers);748749CfiICallNormalizeIntegers =750Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);751752if (CfiCrossDso && CfiICallGeneralizePointers && DiagnoseErrors)753D.Diag(diag::err_drv_argument_not_allowed_with)754<< "-fsanitize-cfi-cross-dso"755<< "-fsanitize-cfi-icall-generalize-pointers";756757CfiCanonicalJumpTables =758Args.hasFlag(options::OPT_fsanitize_cfi_canonical_jump_tables,759options::OPT_fno_sanitize_cfi_canonical_jump_tables, true);760}761762if (AllAddedKinds & SanitizerKind::KCFI) {763CfiICallNormalizeIntegers =764Args.hasArg(options::OPT_fsanitize_cfi_icall_normalize_integers);765766if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)767D.Diag(diag::err_drv_argument_not_allowed_with)768<< "-fsanitize=kcfi"769<< lastArgumentForMask(D, Args, SanitizerKind::CFI);770}771772Stats = Args.hasFlag(options::OPT_fsanitize_stats,773options::OPT_fno_sanitize_stats, false);774775if (MinimalRuntime) {776SanitizerMask IncompatibleMask =777Kinds & ~setGroupBits(CompatibleWithMinimalRuntime);778if (IncompatibleMask && DiagnoseErrors)779D.Diag(clang::diag::err_drv_argument_not_allowed_with)780<< "-fsanitize-minimal-runtime"781<< lastArgumentForMask(D, Args, IncompatibleMask);782783SanitizerMask NonTrappingCfi = Kinds & SanitizerKind::CFI & ~TrappingKinds;784if (NonTrappingCfi && DiagnoseErrors)785D.Diag(clang::diag::err_drv_argument_only_allowed_with)786<< "fsanitize-minimal-runtime"787<< "fsanitize-trap=cfi";788}789790// Parse -f(no-)?sanitize-coverage flags if coverage is supported by the791// enabled sanitizers.792for (const auto *Arg : Args) {793if (Arg->getOption().matches(options::OPT_fsanitize_coverage)) {794int LegacySanitizeCoverage;795if (Arg->getNumValues() == 1 &&796!StringRef(Arg->getValue(0))797.getAsInteger(0, LegacySanitizeCoverage)) {798CoverageFeatures = 0;799Arg->claim();800if (LegacySanitizeCoverage != 0 && DiagnoseErrors) {801D.Diag(diag::warn_drv_deprecated_arg)802<< Arg->getAsString(Args) << /*hasReplacement=*/true803<< "-fsanitize-coverage=trace-pc-guard";804}805continue;806}807CoverageFeatures |= parseCoverageFeatures(D, Arg, DiagnoseErrors);808809// Disable coverage and not claim the flags if there is at least one810// non-supporting sanitizer.811if (!(AllAddedKinds & ~AllRemove & ~setGroupBits(SupportsCoverage))) {812Arg->claim();813} else {814CoverageFeatures = 0;815}816} else if (Arg->getOption().matches(options::OPT_fno_sanitize_coverage)) {817Arg->claim();818CoverageFeatures &= ~parseCoverageFeatures(D, Arg, DiagnoseErrors);819}820}821// Choose at most one coverage type: function, bb, or edge.822if (DiagnoseErrors) {823if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageBB))824D.Diag(clang::diag::err_drv_argument_not_allowed_with)825<< "-fsanitize-coverage=func"826<< "-fsanitize-coverage=bb";827if ((CoverageFeatures & CoverageFunc) && (CoverageFeatures & CoverageEdge))828D.Diag(clang::diag::err_drv_argument_not_allowed_with)829<< "-fsanitize-coverage=func"830<< "-fsanitize-coverage=edge";831if ((CoverageFeatures & CoverageBB) && (CoverageFeatures & CoverageEdge))832D.Diag(clang::diag::err_drv_argument_not_allowed_with)833<< "-fsanitize-coverage=bb"834<< "-fsanitize-coverage=edge";835// Basic block tracing and 8-bit counters require some type of coverage836// enabled.837if (CoverageFeatures & CoverageTraceBB)838D.Diag(clang::diag::warn_drv_deprecated_arg)839<< "-fsanitize-coverage=trace-bb" << /*hasReplacement=*/true840<< "-fsanitize-coverage=trace-pc-guard";841if (CoverageFeatures & Coverage8bitCounters)842D.Diag(clang::diag::warn_drv_deprecated_arg)843<< "-fsanitize-coverage=8bit-counters" << /*hasReplacement=*/true844<< "-fsanitize-coverage=trace-pc-guard";845}846847int InsertionPointTypes = CoverageFunc | CoverageBB | CoverageEdge;848int InstrumentationTypes = CoverageTracePC | CoverageTracePCGuard |849CoverageInline8bitCounters | CoverageTraceLoads |850CoverageTraceStores | CoverageInlineBoolFlag |851CoverageControlFlow;852if ((CoverageFeatures & InsertionPointTypes) &&853!(CoverageFeatures & InstrumentationTypes) && DiagnoseErrors) {854D.Diag(clang::diag::warn_drv_deprecated_arg)855<< "-fsanitize-coverage=[func|bb|edge]" << /*hasReplacement=*/true856<< "-fsanitize-coverage=[func|bb|edge],[trace-pc-guard|trace-pc],["857"control-flow]";858}859860// trace-pc w/o func/bb/edge implies edge.861if (!(CoverageFeatures & InsertionPointTypes)) {862if (CoverageFeatures &863(CoverageTracePC | CoverageTracePCGuard | CoverageInline8bitCounters |864CoverageInlineBoolFlag | CoverageControlFlow))865CoverageFeatures |= CoverageEdge;866867if (CoverageFeatures & CoverageStackDepth)868CoverageFeatures |= CoverageFunc;869}870871// Parse -fsanitize-coverage-(allow|ignore)list options if coverage enabled.872// This also validates special case lists format.873// Here, OptSpecifier() acts as a never-matching command-line argument.874// So, there is no way to clear coverage lists but you can append to them.875if (CoverageFeatures) {876parseSpecialCaseListArg(877D, Args, CoverageAllowlistFiles,878options::OPT_fsanitize_coverage_allowlist, OptSpecifier(),879clang::diag::err_drv_malformed_sanitizer_coverage_allowlist,880DiagnoseErrors);881parseSpecialCaseListArg(882D, Args, CoverageIgnorelistFiles,883options::OPT_fsanitize_coverage_ignorelist, OptSpecifier(),884clang::diag::err_drv_malformed_sanitizer_coverage_ignorelist,885DiagnoseErrors);886}887888// Parse -f(no-)?sanitize-metadata.889for (const auto *Arg :890Args.filtered(options::OPT_fexperimental_sanitize_metadata_EQ,891options::OPT_fno_experimental_sanitize_metadata_EQ)) {892if (Arg->getOption().matches(893options::OPT_fexperimental_sanitize_metadata_EQ)) {894Arg->claim();895BinaryMetadataFeatures |=896parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);897} else {898Arg->claim();899BinaryMetadataFeatures &=900~parseBinaryMetadataFeatures(D, Arg, DiagnoseErrors);901}902}903904// Parse -fsanitize-metadata-ignorelist option if enabled.905if (BinaryMetadataFeatures) {906parseSpecialCaseListArg(907D, Args, BinaryMetadataIgnorelistFiles,908options::OPT_fexperimental_sanitize_metadata_ignorelist_EQ,909OptSpecifier(), // Cannot clear ignore list, only append.910clang::diag::err_drv_malformed_sanitizer_metadata_ignorelist,911DiagnoseErrors);912}913914SharedRuntime =915Args.hasFlag(options::OPT_shared_libsan, options::OPT_static_libsan,916TC.getTriple().isAndroid() || TC.getTriple().isOSFuchsia() ||917TC.getTriple().isOSDarwin());918919ImplicitCfiRuntime = TC.getTriple().isAndroid();920921if (AllAddedKinds & SanitizerKind::Address) {922NeedPIE |= TC.getTriple().isOSFuchsia();923if (Arg *A =924Args.getLastArg(options::OPT_fsanitize_address_field_padding)) {925StringRef S = A->getValue();926// Legal values are 0 and 1, 2, but in future we may add more levels.927if ((S.getAsInteger(0, AsanFieldPadding) || AsanFieldPadding < 0 ||928AsanFieldPadding > 2) &&929DiagnoseErrors) {930D.Diag(clang::diag::err_drv_invalid_value) << A->getAsString(Args) << S;931}932}933934if (Arg *WindowsDebugRTArg =935Args.getLastArg(options::OPT__SLASH_MTd, options::OPT__SLASH_MT,936options::OPT__SLASH_MDd, options::OPT__SLASH_MD,937options::OPT__SLASH_LDd, options::OPT__SLASH_LD)) {938switch (WindowsDebugRTArg->getOption().getID()) {939case options::OPT__SLASH_MTd:940case options::OPT__SLASH_MDd:941case options::OPT__SLASH_LDd:942if (DiagnoseErrors) {943D.Diag(clang::diag::err_drv_argument_not_allowed_with)944<< WindowsDebugRTArg->getAsString(Args)945<< lastArgumentForMask(D, Args, SanitizerKind::Address);946D.Diag(clang::diag::note_drv_address_sanitizer_debug_runtime);947}948}949}950951StableABI = Args.hasFlag(options::OPT_fsanitize_stable_abi,952options::OPT_fno_sanitize_stable_abi, false);953954AsanUseAfterScope = Args.hasFlag(955options::OPT_fsanitize_address_use_after_scope,956options::OPT_fno_sanitize_address_use_after_scope, AsanUseAfterScope);957958AsanPoisonCustomArrayCookie = Args.hasFlag(959options::OPT_fsanitize_address_poison_custom_array_cookie,960options::OPT_fno_sanitize_address_poison_custom_array_cookie,961AsanPoisonCustomArrayCookie);962963AsanOutlineInstrumentation =964Args.hasFlag(options::OPT_fsanitize_address_outline_instrumentation,965options::OPT_fno_sanitize_address_outline_instrumentation,966AsanOutlineInstrumentation);967968AsanGlobalsDeadStripping = Args.hasFlag(969options::OPT_fsanitize_address_globals_dead_stripping,970options::OPT_fno_sanitize_address_globals_dead_stripping, true);971972// Enable ODR indicators which allow better handling of mixed instrumented973// and uninstrumented globals. Disable them for Windows where weak odr974// indicators (.weak.__odr_asan_gen*) may cause multiple definition linker975// errors in the absence of -lldmingw.976AsanUseOdrIndicator =977Args.hasFlag(options::OPT_fsanitize_address_use_odr_indicator,978options::OPT_fno_sanitize_address_use_odr_indicator,979!TC.getTriple().isOSWindows());980981if (AllAddedKinds & SanitizerKind::PointerCompare & ~AllRemove) {982AsanInvalidPointerCmp = true;983}984985if (AllAddedKinds & SanitizerKind::PointerSubtract & ~AllRemove) {986AsanInvalidPointerSub = true;987}988989if (TC.getTriple().isOSDarwin() &&990(Args.hasArg(options::OPT_mkernel) ||991Args.hasArg(options::OPT_fapple_kext))) {992AsanDtorKind = llvm::AsanDtorKind::None;993}994995if (const auto *Arg =996Args.getLastArg(options::OPT_sanitize_address_destructor_EQ)) {997auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());998if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid && DiagnoseErrors) {999TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)1000<< Arg->getSpelling() << Arg->getValue();1001}1002AsanDtorKind = parsedAsanDtorKind;1003}10041005if (const auto *Arg = Args.getLastArg(1006options::OPT_sanitize_address_use_after_return_EQ)) {1007auto parsedAsanUseAfterReturn =1008AsanDetectStackUseAfterReturnModeFromString(Arg->getValue());1009if (parsedAsanUseAfterReturn ==1010llvm::AsanDetectStackUseAfterReturnMode::Invalid &&1011DiagnoseErrors) {1012TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)1013<< Arg->getSpelling() << Arg->getValue();1014}1015AsanUseAfterReturn = parsedAsanUseAfterReturn;1016}10171018} else {1019AsanUseAfterScope = false;1020// -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.1021SanitizerMask DetectInvalidPointerPairs =1022SanitizerKind::PointerCompare | SanitizerKind::PointerSubtract;1023if ((AllAddedKinds & DetectInvalidPointerPairs & ~AllRemove) &&1024DiagnoseErrors) {1025TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)1026<< lastArgumentForMask(D, Args,1027SanitizerKind::PointerCompare |1028SanitizerKind::PointerSubtract)1029<< "-fsanitize=address";1030}1031}10321033if (AllAddedKinds & SanitizerKind::HWAddress) {1034if (Arg *HwasanAbiArg =1035Args.getLastArg(options::OPT_fsanitize_hwaddress_abi_EQ)) {1036HwasanAbi = HwasanAbiArg->getValue();1037if (HwasanAbi != "platform" && HwasanAbi != "interceptor" &&1038DiagnoseErrors)1039D.Diag(clang::diag::err_drv_invalid_value)1040<< HwasanAbiArg->getAsString(Args) << HwasanAbi;1041} else {1042HwasanAbi = "interceptor";1043}1044if (TC.getTriple().getArch() == llvm::Triple::x86_64)1045HwasanUseAliases = Args.hasFlag(1046options::OPT_fsanitize_hwaddress_experimental_aliasing,1047options::OPT_fno_sanitize_hwaddress_experimental_aliasing,1048HwasanUseAliases);1049}10501051if (AllAddedKinds & SanitizerKind::SafeStack) {1052// SafeStack runtime is built into the system on Android and Fuchsia.1053SafeStackRuntime =1054!TC.getTriple().isAndroid() && !TC.getTriple().isOSFuchsia();1055}10561057LinkRuntimes =1058Args.hasFlag(options::OPT_fsanitize_link_runtime,1059options::OPT_fno_sanitize_link_runtime, LinkRuntimes);10601061// Parse -link-cxx-sanitizer flag.1062LinkCXXRuntimes = Args.hasArg(options::OPT_fsanitize_link_cxx_runtime,1063options::OPT_fno_sanitize_link_cxx_runtime,1064LinkCXXRuntimes) ||1065D.CCCIsCXX();10661067NeedsMemProfRt = Args.hasFlag(options::OPT_fmemory_profile,1068options::OPT_fmemory_profile_EQ,1069options::OPT_fno_memory_profile, false);10701071// Finally, initialize the set of available and recoverable sanitizers.1072Sanitizers.Mask |= Kinds;1073RecoverableSanitizers.Mask |= RecoverableKinds;1074TrapSanitizers.Mask |= TrappingKinds;1075assert(!(RecoverableKinds & TrappingKinds) &&1076"Overlap between recoverable and trapping sanitizers");1077}10781079static std::string toString(const clang::SanitizerSet &Sanitizers) {1080std::string Res;1081#define SANITIZER(NAME, ID) \1082if (Sanitizers.has(SanitizerKind::ID)) { \1083if (!Res.empty()) \1084Res += ","; \1085Res += NAME; \1086}1087#include "clang/Basic/Sanitizers.def"1088return Res;1089}10901091static void addSpecialCaseListOpt(const llvm::opt::ArgList &Args,1092llvm::opt::ArgStringList &CmdArgs,1093const char *SCLOptFlag,1094const std::vector<std::string> &SCLFiles) {1095for (const auto &SCLPath : SCLFiles) {1096SmallString<64> SCLOpt(SCLOptFlag);1097SCLOpt += SCLPath;1098CmdArgs.push_back(Args.MakeArgString(SCLOpt));1099}1100}11011102static void addIncludeLinkerOption(const ToolChain &TC,1103const llvm::opt::ArgList &Args,1104llvm::opt::ArgStringList &CmdArgs,1105StringRef SymbolName) {1106SmallString<64> LinkerOptionFlag;1107LinkerOptionFlag = "--linker-option=/include:";1108if (TC.getTriple().getArch() == llvm::Triple::x86) {1109// Win32 mangles C function names with a '_' prefix.1110LinkerOptionFlag += '_';1111}1112LinkerOptionFlag += SymbolName;1113CmdArgs.push_back(Args.MakeArgString(LinkerOptionFlag));1114}11151116static bool hasTargetFeatureMTE(const llvm::opt::ArgStringList &CmdArgs) {1117for (auto Start = CmdArgs.begin(), End = CmdArgs.end(); Start != End;1118++Start) {1119auto It = std::find(Start, End, StringRef("+mte"));1120if (It == End)1121break;1122if (It > Start && *std::prev(It) == StringRef("-target-feature"))1123return true;1124Start = It;1125}1126return false;1127}11281129void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,1130llvm::opt::ArgStringList &CmdArgs,1131types::ID InputType) const {1132// NVPTX doesn't currently support sanitizers. Bailing out here means1133// that e.g. -fsanitize=address applies only to host code, which is what we1134// want for now.1135if (TC.getTriple().isNVPTX())1136return;1137// AMDGPU sanitizer support is experimental and controlled by -fgpu-sanitize.1138bool GPUSanitize = false;1139if (TC.getTriple().isAMDGPU()) {1140if (!Args.hasFlag(options::OPT_fgpu_sanitize, options::OPT_fno_gpu_sanitize,1141true))1142return;1143GPUSanitize = true;1144}11451146// Translate available CoverageFeatures to corresponding clang-cc1 flags.1147// Do it even if Sanitizers.empty() since some forms of coverage don't require1148// sanitizers.1149std::pair<int, const char *> CoverageFlags[] = {1150std::make_pair(CoverageFunc, "-fsanitize-coverage-type=1"),1151std::make_pair(CoverageBB, "-fsanitize-coverage-type=2"),1152std::make_pair(CoverageEdge, "-fsanitize-coverage-type=3"),1153std::make_pair(CoverageIndirCall, "-fsanitize-coverage-indirect-calls"),1154std::make_pair(CoverageTraceBB, "-fsanitize-coverage-trace-bb"),1155std::make_pair(CoverageTraceCmp, "-fsanitize-coverage-trace-cmp"),1156std::make_pair(CoverageTraceDiv, "-fsanitize-coverage-trace-div"),1157std::make_pair(CoverageTraceGep, "-fsanitize-coverage-trace-gep"),1158std::make_pair(Coverage8bitCounters, "-fsanitize-coverage-8bit-counters"),1159std::make_pair(CoverageTracePC, "-fsanitize-coverage-trace-pc"),1160std::make_pair(CoverageTracePCGuard,1161"-fsanitize-coverage-trace-pc-guard"),1162std::make_pair(CoverageInline8bitCounters,1163"-fsanitize-coverage-inline-8bit-counters"),1164std::make_pair(CoverageInlineBoolFlag,1165"-fsanitize-coverage-inline-bool-flag"),1166std::make_pair(CoveragePCTable, "-fsanitize-coverage-pc-table"),1167std::make_pair(CoverageNoPrune, "-fsanitize-coverage-no-prune"),1168std::make_pair(CoverageStackDepth, "-fsanitize-coverage-stack-depth"),1169std::make_pair(CoverageTraceLoads, "-fsanitize-coverage-trace-loads"),1170std::make_pair(CoverageTraceStores, "-fsanitize-coverage-trace-stores"),1171std::make_pair(CoverageControlFlow, "-fsanitize-coverage-control-flow")};1172for (auto F : CoverageFlags) {1173if (CoverageFeatures & F.first)1174CmdArgs.push_back(F.second);1175}1176addSpecialCaseListOpt(1177Args, CmdArgs, "-fsanitize-coverage-allowlist=", CoverageAllowlistFiles);1178addSpecialCaseListOpt(Args, CmdArgs, "-fsanitize-coverage-ignorelist=",1179CoverageIgnorelistFiles);11801181if (!GPUSanitize) {1182// Translate available BinaryMetadataFeatures to corresponding clang-cc11183// flags. Does not depend on any other sanitizers. Unsupported on GPUs.1184const std::pair<int, std::string> BinaryMetadataFlags[] = {1185std::make_pair(BinaryMetadataCovered, "covered"),1186std::make_pair(BinaryMetadataAtomics, "atomics"),1187std::make_pair(BinaryMetadataUAR, "uar")};1188for (const auto &F : BinaryMetadataFlags) {1189if (BinaryMetadataFeatures & F.first)1190CmdArgs.push_back(1191Args.MakeArgString("-fexperimental-sanitize-metadata=" + F.second));1192}1193addSpecialCaseListOpt(Args, CmdArgs,1194"-fexperimental-sanitize-metadata-ignorelist=",1195BinaryMetadataIgnorelistFiles);1196}11971198if (TC.getTriple().isOSWindows() && needsUbsanRt() &&1199Args.hasFlag(options::OPT_frtlib_defaultlib,1200options::OPT_fno_rtlib_defaultlib, true)) {1201// Instruct the code generator to embed linker directives in the object file1202// that cause the required runtime libraries to be linked.1203CmdArgs.push_back(1204Args.MakeArgString("--dependent-lib=" +1205TC.getCompilerRTBasename(Args, "ubsan_standalone")));1206if (types::isCXX(InputType))1207CmdArgs.push_back(Args.MakeArgString(1208"--dependent-lib=" +1209TC.getCompilerRTBasename(Args, "ubsan_standalone_cxx")));1210}1211if (TC.getTriple().isOSWindows() && needsStatsRt() &&1212Args.hasFlag(options::OPT_frtlib_defaultlib,1213options::OPT_fno_rtlib_defaultlib, true)) {1214CmdArgs.push_back(Args.MakeArgString(1215"--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats_client")));12161217// The main executable must export the stats runtime.1218// FIXME: Only exporting from the main executable (e.g. based on whether the1219// translation unit defines main()) would save a little space, but having1220// multiple copies of the runtime shouldn't hurt.1221CmdArgs.push_back(Args.MakeArgString(1222"--dependent-lib=" + TC.getCompilerRTBasename(Args, "stats")));1223addIncludeLinkerOption(TC, Args, CmdArgs, "__sanitizer_stats_register");1224}12251226if (Sanitizers.empty())1227return;1228CmdArgs.push_back(Args.MakeArgString("-fsanitize=" + toString(Sanitizers)));12291230if (!RecoverableSanitizers.empty())1231CmdArgs.push_back(Args.MakeArgString("-fsanitize-recover=" +1232toString(RecoverableSanitizers)));12331234if (!TrapSanitizers.empty())1235CmdArgs.push_back(1236Args.MakeArgString("-fsanitize-trap=" + toString(TrapSanitizers)));12371238addSpecialCaseListOpt(Args, CmdArgs,1239"-fsanitize-ignorelist=", UserIgnorelistFiles);1240addSpecialCaseListOpt(Args, CmdArgs,1241"-fsanitize-system-ignorelist=", SystemIgnorelistFiles);12421243if (MsanTrackOrigins)1244CmdArgs.push_back(Args.MakeArgString("-fsanitize-memory-track-origins=" +1245Twine(MsanTrackOrigins)));12461247if (MsanUseAfterDtor)1248CmdArgs.push_back("-fsanitize-memory-use-after-dtor");12491250if (!MsanParamRetval)1251CmdArgs.push_back("-fno-sanitize-memory-param-retval");12521253// FIXME: Pass these parameters as function attributes, not as -llvm flags.1254if (!TsanMemoryAccess) {1255CmdArgs.push_back("-mllvm");1256CmdArgs.push_back("-tsan-instrument-memory-accesses=0");1257CmdArgs.push_back("-mllvm");1258CmdArgs.push_back("-tsan-instrument-memintrinsics=0");1259}1260if (!TsanFuncEntryExit) {1261CmdArgs.push_back("-mllvm");1262CmdArgs.push_back("-tsan-instrument-func-entry-exit=0");1263}1264if (!TsanAtomics) {1265CmdArgs.push_back("-mllvm");1266CmdArgs.push_back("-tsan-instrument-atomics=0");1267}12681269if (HwasanUseAliases) {1270CmdArgs.push_back("-mllvm");1271CmdArgs.push_back("-hwasan-experimental-use-page-aliases=1");1272}12731274if (CfiCrossDso)1275CmdArgs.push_back("-fsanitize-cfi-cross-dso");12761277if (CfiICallGeneralizePointers)1278CmdArgs.push_back("-fsanitize-cfi-icall-generalize-pointers");12791280if (CfiICallNormalizeIntegers)1281CmdArgs.push_back("-fsanitize-cfi-icall-experimental-normalize-integers");12821283if (CfiCanonicalJumpTables)1284CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");12851286if (Stats)1287CmdArgs.push_back("-fsanitize-stats");12881289if (MinimalRuntime)1290CmdArgs.push_back("-fsanitize-minimal-runtime");12911292if (AsanFieldPadding)1293CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-field-padding=" +1294Twine(AsanFieldPadding)));12951296if (AsanUseAfterScope)1297CmdArgs.push_back("-fsanitize-address-use-after-scope");12981299if (AsanPoisonCustomArrayCookie)1300CmdArgs.push_back("-fsanitize-address-poison-custom-array-cookie");13011302if (AsanGlobalsDeadStripping)1303CmdArgs.push_back("-fsanitize-address-globals-dead-stripping");13041305if (!AsanUseOdrIndicator)1306CmdArgs.push_back("-fno-sanitize-address-use-odr-indicator");13071308if (AsanInvalidPointerCmp) {1309CmdArgs.push_back("-mllvm");1310CmdArgs.push_back("-asan-detect-invalid-pointer-cmp");1311}13121313if (AsanInvalidPointerSub) {1314CmdArgs.push_back("-mllvm");1315CmdArgs.push_back("-asan-detect-invalid-pointer-sub");1316}13171318if (AsanOutlineInstrumentation) {1319CmdArgs.push_back("-mllvm");1320CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");1321}13221323// When emitting Stable ABI instrumentation, force outlining calls and avoid1324// inlining shadow memory poisoning. While this is a big performance burden1325// for now it allows full abstraction from implementation details.1326if (StableABI) {1327CmdArgs.push_back("-mllvm");1328CmdArgs.push_back("-asan-instrumentation-with-call-threshold=0");1329CmdArgs.push_back("-mllvm");1330CmdArgs.push_back("-asan-max-inline-poisoning-size=0");1331CmdArgs.push_back("-mllvm");1332CmdArgs.push_back("-asan-guard-against-version-mismatch=0");1333}13341335// Only pass the option to the frontend if the user requested,1336// otherwise the frontend will just use the codegen default.1337if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {1338CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor=" +1339AsanDtorKindToString(AsanDtorKind)));1340}13411342if (AsanUseAfterReturn != llvm::AsanDetectStackUseAfterReturnMode::Invalid) {1343CmdArgs.push_back(Args.MakeArgString(1344"-fsanitize-address-use-after-return=" +1345AsanDetectStackUseAfterReturnModeToString(AsanUseAfterReturn)));1346}13471348if (!HwasanAbi.empty()) {1349CmdArgs.push_back("-default-function-attr");1350CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));1351}13521353if (Sanitizers.has(SanitizerKind::HWAddress) && !HwasanUseAliases) {1354CmdArgs.push_back("-target-feature");1355CmdArgs.push_back("+tagged-globals");1356}13571358// MSan: Workaround for PR16386.1359// ASan: This is mainly to help LSan with cases such as1360// https://github.com/google/sanitizers/issues/3731361// We can't make this conditional on -fsanitize=leak, as that flag shouldn't1362// affect compilation.1363if (Sanitizers.has(SanitizerKind::Memory) ||1364Sanitizers.has(SanitizerKind::Address))1365CmdArgs.push_back("-fno-assume-sane-operator-new");13661367// libFuzzer wants to intercept calls to certain library functions, so the1368// following -fno-builtin-* flags force the compiler to emit interposable1369// libcalls to these functions. Other sanitizers effectively do the same thing1370// by marking all library call sites with NoBuiltin attribute in their LLVM1371// pass. (see llvm::maybeMarkSanitizerLibraryCallNoBuiltin)1372if (Sanitizers.has(SanitizerKind::FuzzerNoLink)) {1373CmdArgs.push_back("-fno-builtin-bcmp");1374CmdArgs.push_back("-fno-builtin-memcmp");1375CmdArgs.push_back("-fno-builtin-strncmp");1376CmdArgs.push_back("-fno-builtin-strcmp");1377CmdArgs.push_back("-fno-builtin-strncasecmp");1378CmdArgs.push_back("-fno-builtin-strcasecmp");1379CmdArgs.push_back("-fno-builtin-strstr");1380CmdArgs.push_back("-fno-builtin-strcasestr");1381CmdArgs.push_back("-fno-builtin-memmem");1382}13831384// Require -fvisibility= flag on non-Windows when compiling if vptr CFI is1385// enabled.1386if (Sanitizers.hasOneOf(CFIClasses) && !TC.getTriple().isOSWindows() &&1387!Args.hasArg(options::OPT_fvisibility_EQ)) {1388TC.getDriver().Diag(clang::diag::err_drv_argument_only_allowed_with)1389<< lastArgumentForMask(TC.getDriver(), Args,1390Sanitizers.Mask & CFIClasses)1391<< "-fvisibility=";1392}13931394if (Sanitizers.has(SanitizerKind::MemtagStack) &&1395!hasTargetFeatureMTE(CmdArgs))1396TC.getDriver().Diag(diag::err_stack_tagging_requires_hardware_feature);1397}13981399SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,1400bool DiagnoseErrors) {1401assert((A->getOption().matches(options::OPT_fsanitize_EQ) ||1402A->getOption().matches(options::OPT_fno_sanitize_EQ) ||1403A->getOption().matches(options::OPT_fsanitize_recover_EQ) ||1404A->getOption().matches(options::OPT_fno_sanitize_recover_EQ) ||1405A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||1406A->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) &&1407"Invalid argument in parseArgValues!");1408SanitizerMask Kinds;1409for (int i = 0, n = A->getNumValues(); i != n; ++i) {1410const char *Value = A->getValue(i);1411SanitizerMask Kind;1412// Special case: don't accept -fsanitize=all.1413if (A->getOption().matches(options::OPT_fsanitize_EQ) &&14140 == strcmp("all", Value))1415Kind = SanitizerMask();1416else1417Kind = parseSanitizerValue(Value, /*AllowGroups=*/true);14181419if (Kind)1420Kinds |= Kind;1421else if (DiagnoseErrors)1422D.Diag(clang::diag::err_drv_unsupported_option_argument)1423<< A->getSpelling() << Value;1424}1425return Kinds;1426}14271428int parseCoverageFeatures(const Driver &D, const llvm::opt::Arg *A,1429bool DiagnoseErrors) {1430assert(A->getOption().matches(options::OPT_fsanitize_coverage) ||1431A->getOption().matches(options::OPT_fno_sanitize_coverage));1432int Features = 0;1433for (int i = 0, n = A->getNumValues(); i != n; ++i) {1434const char *Value = A->getValue(i);1435int F = llvm::StringSwitch<int>(Value)1436.Case("func", CoverageFunc)1437.Case("bb", CoverageBB)1438.Case("edge", CoverageEdge)1439.Case("indirect-calls", CoverageIndirCall)1440.Case("trace-bb", CoverageTraceBB)1441.Case("trace-cmp", CoverageTraceCmp)1442.Case("trace-div", CoverageTraceDiv)1443.Case("trace-gep", CoverageTraceGep)1444.Case("8bit-counters", Coverage8bitCounters)1445.Case("trace-pc", CoverageTracePC)1446.Case("trace-pc-guard", CoverageTracePCGuard)1447.Case("no-prune", CoverageNoPrune)1448.Case("inline-8bit-counters", CoverageInline8bitCounters)1449.Case("inline-bool-flag", CoverageInlineBoolFlag)1450.Case("pc-table", CoveragePCTable)1451.Case("stack-depth", CoverageStackDepth)1452.Case("trace-loads", CoverageTraceLoads)1453.Case("trace-stores", CoverageTraceStores)1454.Case("control-flow", CoverageControlFlow)1455.Default(0);1456if (F == 0 && DiagnoseErrors)1457D.Diag(clang::diag::err_drv_unsupported_option_argument)1458<< A->getSpelling() << Value;1459Features |= F;1460}1461return Features;1462}14631464int parseBinaryMetadataFeatures(const Driver &D, const llvm::opt::Arg *A,1465bool DiagnoseErrors) {1466assert(1467A->getOption().matches(options::OPT_fexperimental_sanitize_metadata_EQ) ||1468A->getOption().matches(1469options::OPT_fno_experimental_sanitize_metadata_EQ));1470int Features = 0;1471for (int i = 0, n = A->getNumValues(); i != n; ++i) {1472const char *Value = A->getValue(i);1473int F = llvm::StringSwitch<int>(Value)1474.Case("covered", BinaryMetadataCovered)1475.Case("atomics", BinaryMetadataAtomics)1476.Case("uar", BinaryMetadataUAR)1477.Case("all", ~0)1478.Default(0);1479if (F == 0 && DiagnoseErrors)1480D.Diag(clang::diag::err_drv_unsupported_option_argument)1481<< A->getSpelling() << Value;1482Features |= F;1483}1484return Features;1485}14861487std::string lastArgumentForMask(const Driver &D, const llvm::opt::ArgList &Args,1488SanitizerMask Mask) {1489for (llvm::opt::ArgList::const_reverse_iterator I = Args.rbegin(),1490E = Args.rend();1491I != E; ++I) {1492const auto *Arg = *I;1493if (Arg->getOption().matches(options::OPT_fsanitize_EQ)) {1494SanitizerMask AddKinds =1495expandSanitizerGroups(parseArgValues(D, Arg, false));1496if (AddKinds & Mask)1497return describeSanitizeArg(Arg, Mask);1498} else if (Arg->getOption().matches(options::OPT_fno_sanitize_EQ)) {1499SanitizerMask RemoveKinds =1500expandSanitizerGroups(parseArgValues(D, Arg, false));1501Mask &= ~RemoveKinds;1502}1503}1504llvm_unreachable("arg list didn't provide expected value");1505}15061507std::string describeSanitizeArg(const llvm::opt::Arg *A, SanitizerMask Mask) {1508assert(A->getOption().matches(options::OPT_fsanitize_EQ) &&1509"Invalid argument in describeSanitizerArg!");15101511std::string Sanitizers;1512for (int i = 0, n = A->getNumValues(); i != n; ++i) {1513if (expandSanitizerGroups(1514parseSanitizerValue(A->getValue(i), /*AllowGroups=*/true)) &1515Mask) {1516if (!Sanitizers.empty())1517Sanitizers += ",";1518Sanitizers += A->getValue(i);1519}1520}15211522assert(!Sanitizers.empty() && "arg didn't provide expected value");1523return "-fsanitize=" + Sanitizers;1524}152515261527