-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[clang][CodeGen] Added SanitizerHandler mapping, trap messages in debug info, and corresponding test cases. #143758
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Thank you for submitting a Pull Request (PR) to the LLVM Project! This PR will be automatically labeled and the relevant teams will be notified. If you wish to, you can add reviewers by using the "Reviewers" section on this page. If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers. If you have further questions, they may be answered by the LLVM GitHub User Guide. You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums. |
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-clang Author: None (anthonyhatran) ChangesGSoC 2025 Ran the clang test suite before and after changes, and some (~5) test cases failed: Still need to modify the hard-coded strings after further discussion Patch is 21.80 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/143758.diff 22 Files Affected:
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 6cb348ffdf55f..9100ef80c13f4 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -85,6 +85,98 @@ enum VariableTypeDescriptorKind : uint16_t {
// Miscellaneous Helper Methods
//===--------------------------------------------------------------------===//
+static llvm::StringRef GetTrapMessageForHandler(SanitizerHandler ID) {
+ switch (ID) {
+ case SanitizerHandler::AddOverflow:
+ return "The addition of two signed integers resulted in overflow.";
+
+ case SanitizerHandler::BuiltinUnreachable:
+ return "_builtin_unreachable encountered.";
+
+ case SanitizerHandler::CFICheckFail:
+ return "Control flow integrity check failed.";
+
+ case SanitizerHandler::DivremOverflow: // Unsure
+ return "stub";
+
+ case SanitizerHandler::DynamicTypeCacheMiss: // Unsure
+ return "Data requested for dynamic type not found in cache memory.";
+
+ case SanitizerHandler::FloatCastOverflow: // Pasted from LLVM docs, maybe
+ // something better to put here.
+ return "Conversion to, from, or between floating-point types which would "
+ "overflow the destination.";
+
+ case SanitizerHandler::FunctionTypeMismatch:
+ return "Function called with arguments of a different data type than "
+ "expected";
+
+ case SanitizerHandler::ImplicitConversion:
+ return "Implicit conversion occurred.";
+
+ case SanitizerHandler::InvalidBuiltin:
+ return "Built-in function or keyword not recognized.";
+
+ case SanitizerHandler::InvalidObjCCast:
+ return "Invalid Objective-C cast.";
+
+ case SanitizerHandler::LoadInvalidValue:
+ return "stub";
+
+ case SanitizerHandler::MissingReturn:
+ return "Function is missing a return.";
+
+ case SanitizerHandler::MulOverflow:
+ return "The multiplication of two signed integers resulted in overflow.";
+
+ case SanitizerHandler::NegateOverflow:
+ return "Underflow/negative overflow occurred.";
+
+ case SanitizerHandler::
+ NullabilityArg: // Next 4 pasted from
+ // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
+ return "Passing null as a function parameter which is annotated with "
+ "_Nonnull";
+
+ case SanitizerHandler::NullabilityReturn:
+ return "Returning null from a function with a return type annotated with "
+ "_Nonnull";
+
+ case SanitizerHandler::NonnullArg:
+ return "Passing null as a function parameter which is declared to never be "
+ "null";
+
+ case SanitizerHandler::NonnullReturn:
+ return "Returning null pointer from a function which is declared to never "
+ "be null";
+
+ case SanitizerHandler::OutOfBounds:
+ return "Out of bounds -- memory accessed outside of expected boundaries.";
+
+ case SanitizerHandler::PointerOverflow:
+ return "stub";
+
+ case SanitizerHandler::ShiftOutOfBounds:
+ return "Bit shift attempted to move bits beyond boundaries of data type's "
+ "bit size.";
+
+ case SanitizerHandler::SubOverflow:
+ return "The subtraction of two signed integers resulted in overflow.";
+
+ case SanitizerHandler::TypeMismatch:
+ return "Type mismatch -- value type used does not match type expected.";
+
+ case SanitizerHandler::AlignmentAssumption: // Help on bottom 2
+ return "stub";
+
+ case SanitizerHandler::VLABoundNotPositive:
+ return "stub";
+
+ default:
+ return "";
+ }
+}
+
/// CreateTempAlloca - This creates a alloca and inserts it into the entry
/// block.
RawAddress
@@ -4041,7 +4133,8 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) {
void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
SanitizerHandler CheckHandlerID,
- bool NoMerge) {
+ bool NoMerge, StringRef Annotation,
+ StringRef TrapMessage) {
llvm::BasicBlock *Cont = createBasicBlock("cont");
// If we're optimizing, collapse all calls to trap down to just one per
@@ -4051,6 +4144,14 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID];
+ llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation();
+ llvm::StringRef Category = GetTrapMessageForHandler(CheckHandlerID);
+
+ if (getDebugInfo() && !Category.empty()) {
+ TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor(
+ TrapLocation, Category, TrapMessage);
+ }
+
NoMerge = NoMerge || !CGM.getCodeGenOpts().OptimizationLevel ||
(CurCodeDecl && CurCodeDecl->hasAttr<OptimizeNoneAttr>());
@@ -4059,8 +4160,16 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
auto Call = TrapBB->begin();
assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB");
- Call->applyMergedLocation(Call->getDebugLoc(),
- Builder.getCurrentDebugLocation());
+ // Call->applyMergedLocation(Call->getDebugLoc(),
+ // Builder.getCurrentDebugLocation());
+ Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation);
+
+ auto Unreachable = ++TrapBB->begin();
+ if (isa<llvm::UnreachableInst>(Unreachable)) {
+ Unreachable->applyMergedLocation(Unreachable->getDebugLoc(),
+ TrapLocation);
+ }
+
Builder.CreateCondBr(Checked, Cont, TrapBB,
MDHelper.createLikelyBranchWeights());
} else {
@@ -4069,6 +4178,8 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked,
MDHelper.createLikelyBranchWeights());
EmitBlock(TrapBB);
+ ApplyDebugLocation applyTrapDI(*this, TrapLocation);
+
llvm::CallInst *TrapCall =
Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::ubsantrap),
llvm::ConstantInt::get(CGM.Int8Ty, CheckHandlerID));
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index a5ab9df01dba9..aa9c862511579 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -5281,7 +5281,8 @@ class CodeGenFunction : public CodeGenTypeCache {
/// Create a basic block that will call the trap intrinsic, and emit a
/// conditional branch to it, for the -ftrapv checks.
void EmitTrapCheck(llvm::Value *Checked, SanitizerHandler CheckHandlerID,
- bool NoMerge = false);
+ bool NoMerge = false, StringRef Annotation = "",
+ StringRef TrapMessage = "");
/// Emit a call to trap or debugtrap and attach function attribute
/// "trap-func-name" if specified.
diff --git a/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c
new file mode 100644
index 0000000000000..822a1c003d16a
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-add-overflow.c
@@ -0,0 +1,10 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+
+int add_overflow(int a, int b) {
+ return a + b;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
diff --git a/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c
new file mode 100644
index 0000000000000..ada4c372a92b7
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-builtin-unreachable.c
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=unreachable \
+// RUN: -fsanitize-trap=unreachable -emit-llvm -S -c %s -o - | FileCheck %s
+
+int call_builtin_unreachable()
+{
+ __builtin_unreachable();
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 1) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c
new file mode 100644
index 0000000000000..17b6dca16cc62
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-div-rem-overflow.c
@@ -0,0 +1,10 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+
+int div_rem_overflow(int a, int b) {
+ return a / b;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 3) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
diff --git a/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c
new file mode 100644
index 0000000000000..b761e638c5293
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-float-cast-overflow.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O0 -debug-info-kind=standalone -dwarf-version=5 -fsanitize=float-cast-overflow \
+// RUN: -fsanitize-trap=float-cast-overflow -emit-llvm %s -o - | FileCheck %s
+
+int f(float x) {
+ return (int)x;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 5) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c
new file mode 100644
index 0000000000000..25063b69a894c
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-function-type-mismatch.c
@@ -0,0 +1,16 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+
+void target() { }
+
+int function_type_mismatch() {
+ int (*fp_int)(int);
+
+ fp_int = (int (*)(int))(void *)target;
+
+ return fp_int(42);
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 6) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c
new file mode 100644
index 0000000000000..48eb86d09b51a
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-implicit-conversion.c
@@ -0,0 +1,13 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=implicit-conversion \
+// RUN: -fsanitize-trap=implicit-conversion -emit-llvm -S -c %s -o - | FileCheck %s
+
+unsigned long long big;
+
+unsigned implicit_conversion()
+{
+ return big;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 7) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c
new file mode 100644
index 0000000000000..cd136df2f0ed4
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-invalid-builtin.c
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=builtin \
+// RUN: -fsanitize-trap=builtin -emit-llvm -S -c %s -o - | FileCheck %s
+
+unsigned invalid_builtin(unsigned x)
+{
+ return __builtin_clz(x);
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 8) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c
new file mode 100644
index 0000000000000..09d8d588f0a32
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-load-invalid-value.c
@@ -0,0 +1,15 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+#include <stdbool.h>
+
+unsigned char bad_byte;
+
+bool load_invalid_value()
+{
+ return *((bool *)&bad_byte);
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 10) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp
new file mode 100644
index 0000000000000..7f0265abd2305
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-missing-return.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=return \
+// RUN: -fsanitize-trap=return -emit-llvm -S -c %s -o - | FileCheck %s
+
+int missing_return(int x)
+{
+ if (x > 0)
+ return x;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 11) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c
new file mode 100644
index 0000000000000..e9f76b87455c9
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-mul-overflow.c
@@ -0,0 +1,10 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+
+int mul_overflow(int a, int b) {
+ return a * b;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 12) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
diff --git a/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c
new file mode 100644
index 0000000000000..5660c6bb08d03
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-negate-overflow.c
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \
+// RUN: -fsanitize-trap=undefined -emit-llvm -S -c %s -o - | FileCheck %s
+
+int negate_overflow()
+{
+ int x;
+ return -x;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 13) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c
new file mode 100644
index 0000000000000..e648f91b86b27
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-arg.c
@@ -0,0 +1,17 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=nonnull-attribute \
+// RUN: -fsanitize-trap=nonnull-attribute -emit-llvm -S -c %s -o - | FileCheck %s
+
+__attribute__((nonnull))
+void nonnull_arg(int *p) {
+ (void)p;
+}
+
+void trigger_nonnull_arg()
+{
+ nonnull_arg(0);
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 16) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c
new file mode 100644
index 0000000000000..9b14004d96a02
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-nonnull-return.c
@@ -0,0 +1,15 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=returns-nonnull-attribute \
+// RUN: -fsanitize-trap=returns-nonnull-attribute -emit-llvm -S -c %s -o - | FileCheck %s
+
+__attribute__((returns_nonnull))
+int* must_return_nonnull(int bad)
+{
+ if (bad)
+ return 0;
+ static int x = 1;
+ return &x;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 17) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c
new file mode 100644
index 0000000000000..e0d6a79b27c02
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-arg.c
@@ -0,0 +1,19 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=nullability-arg \
+// RUN: -fsanitize-trap=nullability-arg -emit-llvm -S -c %s -o - | FileCheck %s
+
+#include <stddef.h>
+
+int nullability_arg(int* _Nonnull p)
+{
+ return *p;
+}
+
+int trigger_nullability_arg()
+{
+ return nullability_arg(NULL);
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 14) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c
new file mode 100644
index 0000000000000..e10fc5b225221
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-nullability-return.c
@@ -0,0 +1,19 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=nullability-return \
+// RUN: -fsanitize-trap=nullability-return -emit-llvm -S -c %s -o - | FileCheck %s
+
+#include <stdbool.h>
+#include <stddef.h>
+
+int* _Nonnull nullability_return(bool fail)
+{
+ if (fail)
+ return NULL;
+
+ static int x = 0;
+ return &x;
+}
+
+
+// CHECK: call void @llvm.ubsantrap(i8 15) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c
new file mode 100644
index 0000000000000..9ed093fc528ed
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-out-of-bounds.c
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=bounds \
+// RUN: -fsanitize-trap=bounds -emit-llvm -S -c %s -o - | FileCheck %s
+
+int out_of_bounds()
+{
+ int a[1] = {0};
+ return a[1];
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 18) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c
new file mode 100644
index 0000000000000..93ae42208520f
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-pointer-overflow.c
@@ -0,0 +1,16 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=pointer-overflow \
+// RUN: -fsanitize-trap=pointer-overflow -emit-llvm -S -c %s -o - | FileCheck %s
+
+#include <stddef.h>
+#include <stdint.h>
+
+int* pointer_overflow(void)
+{
+ int buf[4];
+ volatile size_t n = (SIZE_MAX / sizeof(int)) - 1;
+ return buf + n;
+}
+
+// CHECK: call void @llvm.ubsantrap(i8 19) {{.*}}!dbg [[LOC:![0-9]+]]
+// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}})
+// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$
\ No newline at end of file
diff --git a/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c
new file mode 100644
index 0000000000000..6f5aff7cd197a
--- /dev/null
+++ b/clang/test/CodeGen/ubsan-trap-reason-shift-out-of-bounds.c
@@ -0,0 +1,12 @@
+// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=shift \
+// RUN: -fsanitize-trap=shift -emi...
[truncated]
|
Forgot to mention missing test cases: |
clang/lib/CodeGen/CGExpr.cpp
Outdated
@@ -4041,7 +4133,8 @@ void CodeGenFunction::EmitUnreachable(SourceLocation Loc) { | |||
|
|||
void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, | |||
SanitizerHandler CheckHandlerID, | |||
bool NoMerge) { | |||
bool NoMerge, StringRef Annotation, | |||
StringRef TrapMessage) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TrapMessage
parameter seems to not get passed from anywhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like something from the Swift fork of clang. We should remove it from this PR because it isn't needed for this PR.
|
||
// CHECK: call void @llvm.ubsantrap(i8 6) {{.*}}!dbg [[LOC:![0-9]+]] | ||
// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) | ||
// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets check that the "category" part of the fake frame name is correct too
748cafd
to
e40a027
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this. We're off to a good start. Once we have your test cases in a good shape we should look at the failing tests to figure out why they broke so we can fix them or adjust your implementation.
clang/lib/CodeGen/CGExpr.cpp
Outdated
@@ -85,6 +85,92 @@ enum VariableTypeDescriptorKind : uint16_t { | |||
// Miscellaneous Helper Methods | |||
//===--------------------------------------------------------------------===// | |||
|
|||
static llvm::StringRef GetTrapMessageForHandler(SanitizerHandler ID) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably rename this function to mention UBSan in its name given that the current intention is to only handle UBSan traps. E.g. GetUBSanTrapForHandler(SanitizerHandler ID)
clang/lib/CodeGen/CGExpr.cpp
Outdated
return "Alignment assumption violated"; | ||
|
||
case SanitizerHandler::VLABoundNotPositive: | ||
return "Variable-length array bound is not positive"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we explicitly add
case SanitizerHandler::BoundsSafety:
// -fbounds-safety traps are not UBSan traps
return {};
So that no one is later tempted to try and add a case at a later date (they might think it's omission is a mistake).
?
clang/lib/CodeGen/CGExpr.cpp
Outdated
@@ -4051,6 +4137,15 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, | |||
|
|||
llvm::BasicBlock *&TrapBB = TrapBBs[CheckHandlerID]; | |||
|
|||
llvm::DILocation *TrapLocation = Builder.getCurrentDebugLocation(); | |||
llvm::StringRef Category = "UBSan Trap Reason"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that Category
is only used in one place I would be tempted to inline its use. I.e.
TrapLocation = getDebugInfo()->CreateTrapFailureMessageFor(
TrapLocation, "UBSan", TrapMessage);
I realize that might conflict more with the code in the Swift fork of Clang but I'm ok with this. Once we've handled the merge conflict we'll have a better sense of what follow up changes are needed to best resolve the conflict.
Nit: We may want to rename UBSan Trap Reason
. I'm not sure it's necessary to mention Trap
or Reason
. I think UBSan
or Undefined Behavior Sanitizer
(if we wanted to be really verbose) would be sufficient.
clang/lib/CodeGen/CGExpr.cpp
Outdated
@@ -4059,8 +4154,16 @@ void CodeGenFunction::EmitTrapCheck(llvm::Value *Checked, | |||
auto Call = TrapBB->begin(); | |||
assert(isa<llvm::CallInst>(Call) && "Expected call in trap BB"); | |||
|
|||
Call->applyMergedLocation(Call->getDebugLoc(), | |||
Builder.getCurrentDebugLocation()); | |||
// Call->applyMergedLocation(Call->getDebugLoc(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The commented out code needs to be removed.
clang/lib/CodeGen/CGExpr.cpp
Outdated
// Builder.getCurrentDebugLocation()); | ||
Call->applyMergedLocation(Call->getDebugLoc(), TrapLocation); | ||
|
||
auto Unreachable = ++TrapBB->begin(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusting the debug info on the unreachable instructions is a bug fix in the Apple fork of Clang that I never got around to upstreaming. Is this something you needed for writing tests?
If this isn't strictly needed I'd suggest dropping this and you can add it as a separate patch.
|
||
// CHECK: call void @llvm.ubsantrap(i8 0) {{.*}}!dbg [[LOC:![0-9]+]] | ||
// CHECK: [[LOC]] = !DILocation(line: 0, scope: [[MSG:![0-9]+]], {{.+}}) | ||
// CHECK: distinct !DISubprogram(name: "__clang_trap_msg$UBSan Trap Reason |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests aren't matching the DISubprogram
correctly. They are matching the category but they aren't matching the trap message. For example this test should be trying to match the Signed integer addition overflowed
trap message.
clang/lib/CodeGen/CGExpr.cpp
Outdated
static llvm::StringRef GetTrapMessageForHandler(SanitizerHandler ID) { | ||
switch (ID) { | ||
case SanitizerHandler::AddOverflow: | ||
return "Signed integer addition overflowed."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A thought I just had about these. We should probably try running our test cases without -fsanitize-trap=undefined
to see how the non-trapping UBSan runtime describes them. We might want to make the messages here match the wording that's currently used when possible. It won't always because the runtime will have runtime information available that we don't have here.
clang/lib/CodeGen/CGExpr.cpp
Outdated
return "Signed integer addition overflowed."; | ||
|
||
case SanitizerHandler::BuiltinUnreachable: | ||
return "_builtin_unreachable() executed."; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit. We probably should omit the .
at the end of the strings. Clang diagnostics tend to do this so we should probably follow think convention unless we have a good reason to not to do this. I realize these aren't the same thing as clang diagnostics so maybe the best thing to do is see how these render in LLDB and decide if they should end with a .
and then do this consistently.
@anthonyhatran Here's an example for
|
@anthonyhatran Here's an example for
|
@@ -0,0 +1,10 @@ | |||
// RUN: %clang -O0 -g -debug-info-kind=standalone -dwarf-version=5 -fsanitize=undefined \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anthonyhatran We should probably use %clang_cc1
instead as a lot of codegen tests do that. That by-passes the clang driver (which is responsible for presenting a GCC compatible interface).
We should also hardcode a target triple here so that we get deterministic code generation. Otherwise your test will use the host to determine the target which might cause the tests to fail when running on other host platforms.
E.g.: %clang_cc1 -triple arm64-apple-macos
Try to give a more complete description of what we call a "fragment", and how debug records interact when fragments are involved.
Use the Twine version instead of manually building a string
We don't need const on these return types.
We do not need const on a return type.
Note that llvm::interleaved constructs a string with the elements from a given range with a given separator.
Fold (vp.splice (insert_elt poison, scalar, 0), vec, 0, mask, 1, vl) to (vslide1up vec, scalar, mask, vl). Fold (vp.splice (splat_vector scalar), vec, 0, mask, 1, vl) to (vslide1up vec, scalar, mask, vl).
Similar to the existing implementations for X86 and PPC, support symbolizing branch targets for AArch64. Do not omit the address for ADRP as the target is typically not at an intended location. Pull Request: llvm#145009
…guments to Neon FEAT_I8MM (llvm#144698)
…#138891) Adapt address description logic for AIX. Issue: llvm#138916
…5708) The oldest supported version is now 3.1. In terms of semantic analysis the compiler treats all versions <= 4.5 identically, and there is no plan to add version-specific checks for older versions. See discourse thread: https://discourse.llvm.org/t/rfc-remove-openmp-versions-prior-to-3-1/86901
As far as I know binutils does not have a similar option and I don't know of a reason we shouldn't accept the RVC hint instructions. The wording in the spec in the past suggested that maybe these weren't valid instruction names, but that's been modified recently.
…139583) Update asan build configuration for AIX: - Adds import lists - Guards shared library code Issue: llvm#138916 --------- Co-authored-by: Hubert Tong <hubert.reinterpretcast@gmail.com>
Apologies for the ping everyone, I made a mistake and requested a mass review. You can ignore the request for review. |
GSoC 2025
@delcypher @Michael137
Ran the clang test suite before and after changes, and some (~5) test cases failed after my changes:
clang/test/CodeGen/ubsan-trap-debugloc.c
clang/test/CodeGen/bounds-checking-debuginfo.c
clang/test/CodeGen/cfi-icall-normalize2-debuginfo.c
clang/test/CodeGen/cfi-icall-generalize-debuginfo.c
clang/test/Driver/clang_f_opts_withspaces.c
Still need to modify the hard-coded strings after further discussion