Index: lib/Driver/SanitizerArgs.cpp =================================================================== --- lib/Driver/SanitizerArgs.cpp +++ lib/Driver/SanitizerArgs.cpp @@ -166,11 +166,11 @@ } bool SanitizerArgs::needsCfiRt() const { - return !(Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso; + return !(CFI & ~TrapSanitizers.Mask) && CfiCrossDso; } bool SanitizerArgs::needsCfiDiagRt() const { - return (Sanitizers.Mask & CFI & ~TrapSanitizers.Mask) && CfiCrossDso; + return (CFI & ~TrapSanitizers.Mask) && CfiCrossDso; } bool SanitizerArgs::requiresPIE() const { @@ -361,10 +361,27 @@ << DeprecatedReplacement; } } - RecoverableKinds &= Kinds; - RecoverableKinds &= ~Unrecoverable; - TrappingKinds &= Kinds; + if (AllAddedKinds & CFI) { + CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, + options::OPT_fno_sanitize_cfi_cross_dso, false); + // Without PIE, external function address may resolve to a PLT record, which + // can not be verified by the target module. + NeedPIE |= CfiCrossDso; + } + + // In the cross-DSO CFI mode a module may be asked to handle any type of CFI + // error, even if the module itself is not checked for that type of error. + // Therefore, trap/recover flags should be preserved all CFI checkers. + if (CfiCrossDso) { + TrappingKinds &= (Kinds | CFI); + RecoverableKinds &= (Kinds | CFI); + } else { + TrappingKinds &= Kinds; + RecoverableKinds &= Kinds; + } + + RecoverableKinds &= ~Unrecoverable; // Setup blacklist files. // Add default blacklist from resource directory. @@ -424,14 +441,6 @@ TC.getTriple().getArch() == llvm::Triple::x86_64); } - if (AllAddedKinds & CFI) { - CfiCrossDso = Args.hasFlag(options::OPT_fsanitize_cfi_cross_dso, - options::OPT_fno_sanitize_cfi_cross_dso, false); - // Without PIE, external function address may resolve to a PLT record, which - // can not be verified by the target module. - NeedPIE |= CfiCrossDso; - } - Stats = Args.hasFlag(options::OPT_fsanitize_stats, options::OPT_fno_sanitize_stats, false); Index: test/Driver/fsanitize.c =================================================================== --- test/Driver/fsanitize.c +++ test/Driver/fsanitize.c @@ -272,6 +272,21 @@ // CHECK-CFI-NO-CROSS-DSO: -emit-llvm-bc // CHECK-CFI-NO-CROSS-DSO-NOT: -fsanitize-cfi-cross-dso +// In the non-cross-dso CFI mode, -fsanitize-trap only appears for enabled CFI checkers. +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-vcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-VCALL-TRAP +// CHECK-CFI-VCALL-TRAP: "-fsanitize=cfi-vcall" "-fsanitize-trap=cfi-vcall" + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-VCALL-NO-TRAP +// CHECK-CFI-VCALL-NO-TRAP: "-fsanitize=cfi-vcall" +// CHECK-CFI-VCALL-NO-TRAP-NOT: -fsanitize-trap= + +// In the cross-dso CFI mode, -fsanitize-trap appears for all CFI checkers. +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-vcall -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-CROSS-DSO-VCALL-TRAP +// CHECK-CFI-CROSS-DSO-VCALL-TRAP: "-fsanitize=cfi-vcall" "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi-vcall -fno-sanitize-trap=cfi-vcall -fsanitize-cfi-cross-dso -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-CROSS-DSO-VCALL-NO-TRAP +// CHECK-CFI-CROSS-DSO-VCALL-NO-TRAP: "-fsanitize=cfi-vcall" "-fsanitize-trap=cfi-derived-cast,cfi-icall,cfi-unrelated-cast,cfi-nvcall" + // RUN: %clang -target x86_64-linux-gnu -fsanitize=cfi -fsanitize-stats -flto -c %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-CFI-STATS // CHECK-CFI-STATS: -fsanitize-stats