Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// (0.0 [default] to skip none, 1.0 to skip all).
SanitizerMaskCutoffs SanitizeSkipHotCutoffs;

/// Set of sanitizer checks that will be annotated with debug info.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Set of sanitizer checks that will be annotated with debug info.
/// Set of sanitizer checks that will be annotated with extra debug info.

SanitizerSet SanitizeAnnotateDebugInfo;

/// List of backend command-line options for -fembed-bitcode.
std::vector<uint8_t> CmdArgs;

Expand Down
25 changes: 25 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2533,6 +2533,31 @@ def fno_sanitize_merge_handlers : Flag<["-"], "fno-sanitize-merge">, Group<f_cla
Alias<fno_sanitize_merge_handlers_EQ>, AliasArgs<["all"]>,
Visibility<[ClangOption, CLOption]>,
HelpText<"Do not allow compiler to merge handlers for any sanitizers">;
def fsanitize_annotate_debug_info_EQ
: CommaJoined<["-"], "fsanitize-annotate-debug-info=">,
Group<f_clang_Group>,
HelpText<"Annotate checks with debug info for specified sanitizers, if "
"supported">;
Copy link
Contributor

@delcypher delcypher May 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can afford to be a bit more verbose in the help text. What about something like this?

Suggested change
HelpText<"Annotate checks with debug info for specified sanitizers, if "
"supported">;
HelpText<"Annotate sanitizer instrumentation with extra debug info for the specified sanitizers, if "
"supported">;

My thinking is

  • Replace checks with instrumentation because not all instrumentation is necessarily a check. E.g. I think stack poisoning is done with instrumentation and that's not a "check".
  • Say "extra debug info" since this is additional information on top of normal debug info
  • Add missing "the"

def fno_sanitize_annotate_debug_info_EQ
: CommaJoined<["-"], "fno-sanitize-annotate-debug-info=">,
Group<f_clang_Group>,
HelpText<"Do not allow compiler to annotate checks with debug info for "
"specified sanitizers">;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
HelpText<"Do not allow compiler to annotate checks with debug info for "
"specified sanitizers">;
HelpText<"Do not allow compiler to annotate checks with debug info for "
"the specified sanitizers">;

def fsanitize_annotate_debug_info
: Flag<["-"], "fsanitize-annotate_debug_info">,
Group<f_clang_Group>,
Alias<fsanitize_annotate_debug_info_EQ>,
AliasArgs<["all"]>,
HelpText<"Allow compiler to annotate checks with debug info for all "
"sanitizers, where supported">;
def fno_sanitize_annotate_debug_info
: Flag<["-"], "fno-sanitize-annotate_debug_info">,
Group<f_clang_Group>,
Alias<fno_sanitize_annotate_debug_info_EQ>,
AliasArgs<["all"]>,
Visibility<[ClangOption, CLOption]>,
HelpText<"Do not allow compiler to annotate checks with debug info for "
"any sanitizers">;
def fsanitize_undefined_trap_on_error
: Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>,
Alias<fsanitize_trap_EQ>, AliasArgs<["undefined"]>;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/SanitizerArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class SanitizerArgs {
SanitizerSet TrapSanitizers;
SanitizerSet MergeHandlers;
SanitizerMaskCutoffs SkipHotCutoffs;
SanitizerSet AnnotateDebugInfo;

std::vector<std::string> UserIgnorelistFiles;
std::vector<std::string> SystemIgnorelistFiles;
Expand Down
8 changes: 6 additions & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1228,7 +1228,11 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
SanitizerScope SanScope(this);

llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
if (ClArrayBoundsPseudoFn && CheckDI) {
auto CurrentCheckKind = SanitizerKind::SO_ArrayBounds;
// TODO: deprecate ClArrayBoundsPseudoFn
if ((ClArrayBoundsPseudoFn ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add TODO to clean up mllvm flag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be nice to make clear that SO_ArrayBounds here is the same as on line 1252
E.g. auto CurrentCheck = SO_ArrayBounds;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added CurrentCheckKind (there is already a Check variable that contains the instructions)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would drop the Current then for symmety

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

CGM.getCodeGenOpts().SanitizeAnnotateDebugInfo.has(CurrentCheckKind)) &&
CheckDI) {
CheckDI = getDebugInfo()->CreateSyntheticInlineAt(
Builder.getCurrentDebugLocation(), "__ubsan_check_array_bounds");
}
Expand All @@ -1245,7 +1249,7 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
};
llvm::Value *Check = Accessed ? Builder.CreateICmpULT(IndexVal, BoundVal)
: Builder.CreateICmpULE(IndexVal, BoundVal);
EmitCheck(std::make_pair(Check, SanitizerKind::SO_ArrayBounds),
EmitCheck(std::make_pair(Check, CurrentCheckKind),
SanitizerHandler::OutOfBounds, StaticData, Index);
}

Expand Down
19 changes: 18 additions & 1 deletion clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ static const SanitizerMask MergeDefault =
SanitizerKind::Undefined | SanitizerKind::Vptr;
static const SanitizerMask TrappingDefault =
SanitizerKind::CFI | SanitizerKind::LocalBounds;
static const SanitizerMask AnnotateDebugInfoDefault;
static const SanitizerMask CFIClasses =
SanitizerKind::CFIVCall | SanitizerKind::CFINVCall |
SanitizerKind::CFIMFCall | SanitizerKind::CFIDerivedCast |
Expand Down Expand Up @@ -738,6 +739,13 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
// Parse -fno-sanitize-top-hot flags
SkipHotCutoffs = parseSanitizeSkipHotCutoffArgs(D, Args, DiagnoseErrors);

// Parse -f(no-)?sanitize-annotate-debug-info flags
SanitizerMask AnnotateDebugInfoKinds =
parseSanitizeArgs(D, Args, DiagnoseErrors, AnnotateDebugInfoDefault, {},
{}, options::OPT_fsanitize_annotate_debug_info_EQ,
options::OPT_fno_sanitize_annotate_debug_info_EQ);
AnnotateDebugInfoKinds &= Kinds;

// Setup ignorelist files.
// Add default ignorelist from resource directory for activated sanitizers,
// and validate special case lists format.
Expand Down Expand Up @@ -1157,6 +1165,8 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,

MergeHandlers.Mask |= MergeKinds;

AnnotateDebugInfo.Mask |= AnnotateDebugInfoKinds;

// Zero out SkipHotCutoffs for unused sanitizers
SkipHotCutoffs.clear(~Sanitizers.Mask);
}
Expand Down Expand Up @@ -1335,6 +1345,10 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
CmdArgs.push_back(
Args.MakeArgString("-fsanitize-skip-hot-cutoff=" + SkipHotCutoffsStr));

if (!AnnotateDebugInfo.empty())
CmdArgs.push_back(Args.MakeArgString("-fsanitize-annotate-debug-info=" +
toString(AnnotateDebugInfo)));

addSpecialCaseListOpt(Args, CmdArgs,
"-fsanitize-ignorelist=", UserIgnorelistFiles);
addSpecialCaseListOpt(Args, CmdArgs,
Expand Down Expand Up @@ -1518,7 +1532,10 @@ SanitizerMask parseArgValues(const Driver &D, const llvm::opt::Arg *A,
A->getOption().matches(options::OPT_fsanitize_trap_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_trap_EQ) ||
A->getOption().matches(options::OPT_fsanitize_merge_handlers_EQ) ||
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ)) &&
A->getOption().matches(options::OPT_fno_sanitize_merge_handlers_EQ) ||
A->getOption().matches(options::OPT_fsanitize_annotate_debug_info_EQ) ||
A->getOption().matches(
options::OPT_fno_sanitize_annotate_debug_info_EQ)) &&
"Invalid argument in parseArgValues!");
SanitizerMask Kinds;
for (int i = 0, n = A->getNumValues(); i != n; ++i) {
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1838,6 +1838,10 @@ void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts,
for (std::string Sanitizer : Values)
GenerateArg(Consumer, OPT_fsanitize_skip_hot_cutoff_EQ, Sanitizer);

for (StringRef Sanitizer :
serializeSanitizerKinds(Opts.SanitizeAnnotateDebugInfo))
GenerateArg(Consumer, OPT_fsanitize_annotate_debug_info_EQ, Sanitizer);

if (!Opts.EmitVersionIdentMetadata)
GenerateArg(Consumer, OPT_Qn);

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

parseSanitizerKinds(
"-fsanitize-annotate-debug-info=",
Args.getAllArgValues(OPT_fsanitize_annotate_debug_info_EQ), Diags,
Opts.SanitizeAnnotateDebugInfo);

Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);

if (!LangOpts->CUDAIsDevice)
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGen/bounds-checking-debuginfo.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
// 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
// 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

// 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
// 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

int f();
void d(double*);
Expand Down
Loading
Loading