Skip to content

Commit 6a28d8c

Browse files
authored
[sanitizer] Add plumbing for -fsanitize-annotate-debug-info and partly replace '-mllvm -array-bounds-pseudofn' (#138577)
@fmayer introduced '-mllvm -array-bounds-pseudofn' (#128977) to make it easier to see why crashes occurred, and to estimate with a profiler the cycles spent on these array-bounds checks. This functionality could be usefully generalized to other checks in future work. This patch adds the plumbing for -fsanitize-annotate-debug-info, and connects it to the existing array-bounds-pseudo-fn functionality i.e., -fsanitize-annotate-debug-info=array-bounds can be used as a replacement for '-mllvm -array-bounds-pseudofn', though we do not yet delete the latter. Note: we replaced '-mllvm -array-bounds-pseudofn' in clang/test/CodeGen/bounds-checking-debuginfo.c, because adding test cases would modify the line numbers in the test assertions, and therefore obscure that the test output is the same between '-mllvm -array-bounds-pseudofn' and -fsanitize-annotate-debug-info=array-bounds.
1 parent b756c82 commit 6a28d8c

File tree

8 files changed

+124
-6
lines changed

8 files changed

+124
-6
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
399399
/// (0.0 [default] to skip none, 1.0 to skip all).
400400
SanitizerMaskCutoffs SanitizeSkipHotCutoffs;
401401

402+
/// Set of sanitizer checks, for which the instrumentation will be annotated
403+
/// with extra debug info.
404+
SanitizerSet SanitizeAnnotateDebugInfo;
405+
402406
/// List of backend command-line options for -fembed-bitcode.
403407
std::vector<uint8_t> CmdArgs;
404408

clang/include/clang/Driver/Options.td

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,31 @@ def fno_sanitize_merge_handlers : Flag<["-"], "fno-sanitize-merge">, Group<f_cla
25402540
Alias<fno_sanitize_merge_handlers_EQ>, AliasArgs<["all"]>,
25412541
Visibility<[ClangOption, CLOption]>,
25422542
HelpText<"Do not allow compiler to merge handlers for any sanitizers">;
2543+
def fsanitize_annotate_debug_info_EQ
2544+
: CommaJoined<["-"], "fsanitize-annotate-debug-info=">,
2545+
Group<f_clang_Group>,
2546+
HelpText<"Annotate sanitizer instrumentation with extra debug info for "
2547+
"the specified sanitizers, if supported">;
2548+
def fno_sanitize_annotate_debug_info_EQ
2549+
: CommaJoined<["-"], "fno-sanitize-annotate-debug-info=">,
2550+
Group<f_clang_Group>,
2551+
HelpText<"Do not allow compiler to annotate sanitizer instrumentation "
2552+
"with extra debug info for the specified sanitizers">;
2553+
def fsanitize_annotate_debug_info
2554+
: Flag<["-"], "fsanitize-annotate-debug-info">,
2555+
Group<f_clang_Group>,
2556+
Alias<fsanitize_annotate_debug_info_EQ>,
2557+
AliasArgs<["all"]>,
2558+
HelpText<"Allow compiler to annotate sanitizer instrumentation with "
2559+
"extra debug info for all sanitizers, where supported">;
2560+
def fno_sanitize_annotate_debug_info
2561+
: Flag<["-"], "fno-sanitize-annotate-debug-info">,
2562+
Group<f_clang_Group>,
2563+
Alias<fno_sanitize_annotate_debug_info_EQ>,
2564+
AliasArgs<["all"]>,
2565+
Visibility<[ClangOption, CLOption]>,
2566+
HelpText<"Do not allow compiler to annotate sanitizer instrumentation "
2567+
"with extra debug info for any sanitizers">;
25432568
def fsanitize_undefined_trap_on_error
25442569
: Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>,
25452570
Alias<fsanitize_trap_EQ>, AliasArgs<["undefined"]>;

clang/include/clang/Driver/SanitizerArgs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class SanitizerArgs {
2727
SanitizerSet TrapSanitizers;
2828
SanitizerSet MergeHandlers;
2929
SanitizerMaskCutoffs SkipHotCutoffs;
30+
SanitizerSet AnnotateDebugInfo;
3031

3132
std::vector<std::string> UserIgnorelistFiles;
3233
std::vector<std::string> SystemIgnorelistFiles;

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,7 +1228,11 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
12281228
SanitizerScope SanScope(this);
12291229

12301230
llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
1231-
if (ClArrayBoundsPseudoFn && CheckDI) {
1231+
auto CheckKind = SanitizerKind::SO_ArrayBounds;
1232+
// TODO: deprecate ClArrayBoundsPseudoFn
1233+
if ((ClArrayBoundsPseudoFn ||
1234+
CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(CheckKind)) &&
1235+
CheckDI) {
12321236
CheckDI = getDebugInfo()->CreateSyntheticInlineAt(
12331237
Builder.getCurrentDebugLocation(), "__ubsan_check_array_bounds");
12341238
}
@@ -1245,8 +1249,8 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
12451249
};
12461250
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
12471251
: Builder.CreateICmpULE(IndexVal, BoundVal);
1248-
EmitCheck(std::make_pair(Check, SanitizerKind::SO_ArrayBounds),
1249-
SanitizerHandler::OutOfBounds, StaticData, Index);
1252+
EmitCheck(std::make_pair(Check, CheckKind), SanitizerHandler::OutOfBounds,
1253+
StaticData, Index);
12501254
}
12511255

12521256
CodeGenFunction::ComplexPairTy CodeGenFunction::

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ static const SanitizerMask MergeDefault =
7676
SanitizerKind::Undefined | SanitizerKind::Vptr;
7777
static const SanitizerMask TrappingDefault =
7878
SanitizerKind::CFI | SanitizerKind::LocalBounds;
79+
static const SanitizerMask AnnotateDebugInfoDefault;
7980
static const SanitizerMask CFIClasses =
8081
SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
8182
SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
@@ -738,6 +739,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
738739
// Parse -fno-sanitize-top-hot flags
739740
SkipHotCutoffs = parseSanitizeSkipHotCutoffArgs(D, Args, DiagnoseErrors);
740741

742+
// Parse -f(no-)?sanitize-annotate-debug-info flags
743+
SanitizerMask AnnotateDebugInfoKinds =
744+
parseSanitizeArgs(D, Args, DiagnoseErrors, AnnotateDebugInfoDefault, {},
745+
{}, options::OPT_fsanitize_annotate_debug_info_EQ,
746+
options::OPT_fno_sanitize_annotate_debug_info_EQ);
747+
AnnotateDebugInfoKinds &= Kinds;
748+
741749
// Setup ignorelist files.
742750
// Add default ignorelist from resource directory for activated sanitizers,
743751
// and validate special case lists format.
@@ -1168,6 +1176,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
11681176

11691177
MergeHandlers.Mask |= MergeKinds;
11701178

1179+
AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;
1180+
11711181
// Zero out SkipHotCutoffs for unused sanitizers
11721182
SkipHotCutoffs.clear(~Sanitizers.Mask);
11731183
}
@@ -1351,6 +1361,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
13511361
CmdArgs.push_back(
13521362
Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));
13531363

1364+
if (!AnnotateDebugInfo.empty())
1365+
CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +
1366+
toString(AnnotateDebugInfo)));
1367+
13541368
addSpecialCaseListOpt(Args, CmdArgs,
13551369
"-fsanitize-ignorelist=", UserIgnorelistFiles);
13561370
addSpecialCaseListOpt(Args, CmdArgs,
@@ -1534,7 +1548,10 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
15341548
A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
15351549
A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
15361550
A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
1537-
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
1551+
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
1552+
A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
1553+
A->getOption().matches(
1554+
options::OPT_fno_sanitize_annotate_debug_info_EQ)) &&
15381555
"Invalid argument in parseArgValues!");
15391556
SanitizerMask Kinds;
15401557
for (int i = 0, n = A->getNumValues(); i != n; ++i) {

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,10 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
18381838
for (std::string Sanitizer : Values)
18391839
GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);
18401840

1841+
for (StringRef Sanitizer :
1842+
serializeSanitizerKinds(Opts.SanitizeAnnotateDebugInfo))
1843+
GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);
1844+
18411845
if (!Opts.EmitVersionIdentMetadata)
18421846
GenerateArg(Consumer, OPT_Qn);
18431847

@@ -2332,6 +2336,11 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
23322336
"-fsanitize-skip-hot-cutoff=",
23332337
Args.getAllArgValues(OPT_fsanitize_skip_hot_cutoff_EQ), Diags);
23342338

2339+
parseSanitizerKinds(
2340+
"-fsanitize-annotate-debug-info=",
2341+
Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,
2342+
Opts.SanitizeAnnotateDebugInfo);
2343+
23352344
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
23362345

23372346
if (!LangOpts->CUDAIsDevice)

clang/test/CodeGen/bounds-checking-debuginfo.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
2-
// RUN: %clang_cc1 -mllvm -array-bounds-pseudofn -emit-llvm -fdebug-prefix-map=%S/= -fno-ident -fdebug-compilation-dir=%S -fsanitize=array-bounds -fsanitize-trap=array-bounds -triple x86_64 -debug-info-kind=limited %s -o - | FileCheck --check-prefix=CHECK-TRAP %s
3-
// RUN: %clang_cc1 -mllvm -array-bounds-pseudofn -emit-llvm -fdebug-prefix-map=%S/= -fno-ident -fdebug-compilation-dir=%S -fsanitize=array-bounds -triple x86_64 -debug-info-kind=limited %s -o - | FileCheck --check-prefix=CHECK-NOTRAP %s
42

3+
// RUN: %clang_cc1 -emit-llvm -fdebug-prefix-map=%S/= -fno-ident -fdebug-compilation-dir=%S -fsanitize=array-bounds -fsanitize-trap=array-bounds -fsanitize-annotate-debug-info=array-bounds -triple x86_64 -debug-info-kind=limited %s -o - | FileCheck --check-prefix=CHECK-TRAP %s
4+
// RUN: %clang_cc1 -emit-llvm -fdebug-prefix-map=%S/= -fno-ident -fdebug-compilation-dir=%S -fsanitize=array-bounds -fsanitize-annotate-debug-info=array-bounds -triple x86_64 -debug-info-kind=limited %s -o - | FileCheck --check-prefix=CHECK-NOTRAP %s
55

66
int f();
77
void d(double*);

0 commit comments

Comments
 (0)