[clang] [sanitizer] add pseudofunction to indicate array-bounds check (#128977)
With this, we can: * use profilers to estimate how many cycles we spend on these checks (subject to caveats), * more easily see why we crashed.
This commit is contained in:
parent
812efdb094
commit
c0952a931c
@ -1786,8 +1786,8 @@ llvm::DIType *CGDebugInfo::createFieldType(
|
||||
}
|
||||
|
||||
llvm::DISubprogram *
|
||||
CGDebugInfo::createInlinedTrapSubprogram(StringRef FuncName,
|
||||
llvm::DIFile *FileScope) {
|
||||
CGDebugInfo::createInlinedSubprogram(StringRef FuncName,
|
||||
llvm::DIFile *FileScope) {
|
||||
// We are caching the subprogram because we don't want to duplicate
|
||||
// subprograms with the same message. Note that `SPFlagDefinition` prevents
|
||||
// subprograms from being uniqued.
|
||||
@ -3614,6 +3614,14 @@ llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
|
||||
return DBuilder.createTempMacroFile(Parent, Line, FName);
|
||||
}
|
||||
|
||||
llvm::DILocation *CGDebugInfo::CreateSyntheticInlineAt(llvm::DebugLoc Location,
|
||||
StringRef FuncName) {
|
||||
llvm::DISubprogram *SP =
|
||||
createInlinedSubprogram(FuncName, Location->getFile());
|
||||
return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0,
|
||||
/*Scope=*/SP, /*InlinedAt=*/Location);
|
||||
}
|
||||
|
||||
llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
|
||||
llvm::DebugLoc TrapLocation, StringRef Category, StringRef FailureMsg) {
|
||||
// Create a debug location from `TrapLocation` that adds an artificial inline
|
||||
@ -3625,10 +3633,7 @@ llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
|
||||
FuncName += "$";
|
||||
FuncName += FailureMsg;
|
||||
|
||||
llvm::DISubprogram *TrapSP =
|
||||
createInlinedTrapSubprogram(FuncName, TrapLocation->getFile());
|
||||
return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0,
|
||||
/*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
|
||||
return CreateSyntheticInlineAt(TrapLocation, FuncName);
|
||||
}
|
||||
|
||||
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
|
||||
|
@ -359,8 +359,8 @@ class CGDebugInfo {
|
||||
|
||||
/// A function that returns the subprogram corresponding to the artificial
|
||||
/// inlined function for traps.
|
||||
llvm::DISubprogram *createInlinedTrapSubprogram(StringRef FuncName,
|
||||
llvm::DIFile *FileScope);
|
||||
llvm::DISubprogram *createInlinedSubprogram(StringRef FuncName,
|
||||
llvm::DIFile *FileScope);
|
||||
|
||||
/// Helpers for collecting fields of a record.
|
||||
/// @{
|
||||
@ -635,6 +635,13 @@ public:
|
||||
llvm::DILocation *CreateTrapFailureMessageFor(llvm::DebugLoc TrapLocation,
|
||||
StringRef Category,
|
||||
StringRef FailureMsg);
|
||||
/// Create a debug location from `Location` that adds an artificial inline
|
||||
/// frame where the frame name is FuncName
|
||||
///
|
||||
/// This is used to indiciate instructions that come from compiler
|
||||
/// instrumentation.
|
||||
llvm::DILocation *CreateSyntheticInlineAt(llvm::DebugLoc Location,
|
||||
StringRef FuncName);
|
||||
|
||||
private:
|
||||
/// Emit call to llvm.dbg.declare for a variable declaration.
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "clang/AST/StmtVisitor.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Basic/Module.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
@ -60,8 +61,14 @@ namespace clang {
|
||||
llvm::cl::opt<bool> ClSanitizeGuardChecks(
|
||||
"ubsan-guard-checks", llvm::cl::Optional,
|
||||
llvm::cl::desc("Guard UBSAN checks with `llvm.allow.ubsan.check()`."));
|
||||
|
||||
} // namespace clang
|
||||
|
||||
static llvm::cl::opt<bool> ClArrayBoundsPseudoFn(
|
||||
"array-bounds-pseudofn", llvm::cl::Hidden, llvm::cl::Optional,
|
||||
llvm::cl::desc("Emit debug info that places array-bounds instrumentation "
|
||||
"in an inline function called __ubsan_check_array_bounds."));
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Defines for metadata
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -1215,6 +1222,13 @@ void CodeGenFunction::EmitBoundsCheckImpl(const Expr *E, llvm::Value *Bound,
|
||||
|
||||
SanitizerScope SanScope(this);
|
||||
|
||||
llvm::DILocation *CheckDI = Builder.getCurrentDebugLocation();
|
||||
if (ClArrayBoundsPseudoFn && CheckDI) {
|
||||
CheckDI = getDebugInfo()->CreateSyntheticInlineAt(
|
||||
Builder.getCurrentDebugLocation(), "__ubsan_check_array_bounds");
|
||||
}
|
||||
ApplyDebugLocation ApplyTrapDI(*this, CheckDI);
|
||||
|
||||
bool IndexSigned = IndexType->isSignedIntegerOrEnumerationType();
|
||||
llvm::Value *IndexVal = Builder.CreateIntCast(Index, SizeTy, IndexSigned);
|
||||
llvm::Value *BoundVal = Builder.CreateIntCast(Bound, SizeTy, false);
|
||||
|
@ -1,6 +1,6 @@
|
||||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5
|
||||
// RUN: %clang_cc1 -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 -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 -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
|
||||
|
||||
|
||||
int f();
|
||||
@ -28,10 +28,10 @@ void d(double*);
|
||||
// CHECK-TRAP-NEXT: call void @llvm.ubsantrap(i8 18) #[[ATTR3:[0-9]+]], !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-TRAP-NEXT: unreachable, !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-TRAP: [[CONT]]:
|
||||
// CHECK-TRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG23]]
|
||||
// CHECK-TRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG23]]
|
||||
// CHECK-TRAP-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG23]]
|
||||
// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG24:![0-9]+]]
|
||||
// CHECK-TRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG26:![0-9]+]]
|
||||
// CHECK-TRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG26]]
|
||||
// CHECK-TRAP-NEXT: [[TMP2:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG26]]
|
||||
// CHECK-TRAP-NEXT: ret double [[TMP2]], !dbg [[DBG27:![0-9]+]]
|
||||
//
|
||||
// CHECK-NOTRAP-LABEL: define dso_local double @f1(
|
||||
// CHECK-NOTRAP-SAME: i32 noundef [[B:%.*]], i32 noundef [[I:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG4:![0-9]+]] {
|
||||
@ -49,16 +49,16 @@ void d(double*);
|
||||
// CHECK-NOTRAP-NEXT: [[CALL:%.*]] = call i32 (...) @f(), !dbg [[DBG22:![0-9]+]]
|
||||
// CHECK-NOTRAP-NEXT: [[TMP0:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG23:![0-9]+]], !nosanitize [[META10:![0-9]+]]
|
||||
// CHECK-NOTRAP-NEXT: [[TMP1:%.*]] = icmp ult i64 [[TMP0]], 10, !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !dbg [[DBG23]], !prof [[PROF24:![0-9]+]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP-NEXT: br i1 [[TMP1]], label %[[CONT:.*]], label %[[HANDLER_OUT_OF_BOUNDS:.*]], !dbg [[DBG23]], !prof [[PROF27:![0-9]+]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP: [[HANDLER_OUT_OF_BOUNDS]]:
|
||||
// CHECK-NOTRAP-NEXT: [[TMP2:%.*]] = zext i32 [[CALL]] to i64, !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP-NEXT: call void @__ubsan_handle_out_of_bounds_abort(ptr @[[GLOB2:[0-9]+]], i64 [[TMP2]]) #[[ATTR3:[0-9]+]], !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP-NEXT: unreachable, !dbg [[DBG23]], !nosanitize [[META10]]
|
||||
// CHECK-NOTRAP: [[CONT]]:
|
||||
// CHECK-NOTRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG23]]
|
||||
// CHECK-NOTRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG23]]
|
||||
// CHECK-NOTRAP-NEXT: [[TMP3:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG23]]
|
||||
// CHECK-NOTRAP-NEXT: ret double [[TMP3]], !dbg [[DBG25:![0-9]+]]
|
||||
// CHECK-NOTRAP-NEXT: [[IDXPROM:%.*]] = sext i32 [[CALL]] to i64, !dbg [[DBG26:![0-9]+]]
|
||||
// CHECK-NOTRAP-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [10 x double], ptr [[A]], i64 0, i64 [[IDXPROM]], !dbg [[DBG26]]
|
||||
// CHECK-NOTRAP-NEXT: [[TMP3:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !dbg [[DBG26]]
|
||||
// CHECK-NOTRAP-NEXT: ret double [[TMP3]], !dbg [[DBG28:![0-9]+]]
|
||||
//
|
||||
double f1(int b, int i) {
|
||||
double a[10];
|
||||
@ -88,8 +88,11 @@ double f1(int b, int i) {
|
||||
// CHECK-TRAP: [[DBG20]] = !DILocation(line: 65, column: 5, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG21]] = !DILocation(line: 65, column: 3, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG22]] = !DILocation(line: 66, column: 12, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG23]] = !DILocation(line: 66, column: 10, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG24]] = !DILocation(line: 66, column: 3, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG23]] = !DILocation(line: 0, scope: [[META24:![0-9]+]], inlinedAt: [[DBG26]])
|
||||
// CHECK-TRAP: [[META24]] = distinct !DISubprogram(name: "__ubsan_check_array_bounds", scope: [[META5]], file: [[META5]], type: [[META25:![0-9]+]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]])
|
||||
// CHECK-TRAP: [[META25]] = !DISubroutineType(types: null)
|
||||
// CHECK-TRAP: [[DBG26]] = !DILocation(line: 66, column: 10, scope: [[DBG4]])
|
||||
// CHECK-TRAP: [[DBG27]] = !DILocation(line: 66, column: 3, scope: [[DBG4]])
|
||||
//.
|
||||
// CHECK-NOTRAP: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C11, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
|
||||
// CHECK-NOTRAP: [[META1]] = !DIFile(filename: "<stdin>", directory: {{.*}})
|
||||
@ -112,7 +115,10 @@ double f1(int b, int i) {
|
||||
// CHECK-NOTRAP: [[DBG20]] = !DILocation(line: 65, column: 5, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[DBG21]] = !DILocation(line: 65, column: 3, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[DBG22]] = !DILocation(line: 66, column: 12, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[DBG23]] = !DILocation(line: 66, column: 10, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[PROF24]] = !{!"branch_weights", i32 1048575, i32 1}
|
||||
// CHECK-NOTRAP: [[DBG25]] = !DILocation(line: 66, column: 3, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[DBG23]] = !DILocation(line: 0, scope: [[META24:![0-9]+]], inlinedAt: [[DBG26]])
|
||||
// CHECK-NOTRAP: [[META24]] = distinct !DISubprogram(name: "__ubsan_check_array_bounds", scope: [[META5]], file: [[META5]], type: [[META25:![0-9]+]], flags: DIFlagArtificial, spFlags: DISPFlagDefinition, unit: [[META0]])
|
||||
// CHECK-NOTRAP: [[META25]] = !DISubroutineType(types: null)
|
||||
// CHECK-NOTRAP: [[DBG26]] = !DILocation(line: 66, column: 10, scope: [[DBG4]])
|
||||
// CHECK-NOTRAP: [[PROF27]] = !{!"branch_weights", i32 1048575, i32 1}
|
||||
// CHECK-NOTRAP: [[DBG28]] = !DILocation(line: 66, column: 3, scope: [[DBG4]])
|
||||
//.
|
||||
|
Loading…
x
Reference in New Issue
Block a user