Skip to content

Conversation

@delcypher
Copy link

@delcypher delcypher commented Sep 9, 2025

This PR cherry-picks llvm#154618 and a bunch of patches that change depends on.

These changes include work done by @anthonyhatran as part of his GSoC 2025 project.

rdar://158612755

anthonyhatran and others added 4 commits September 8, 2025 16:38
This patch adds a human readable trap category and message to UBSan
traps. The category and message are encoded in a fake frame in the debug
info where the function is a fake inline function where the name encodes
the trap category and message. This is the same mechanism used by
Clang’s `__builtin_verbose_trap()`.

This change allows consumers of binaries built with trapping UBSan to
more easily identify the reason for trapping. In particular LLDB already
has a frame recognizer that recognizes the fake function names emitted
in debug info by this patch. A patch testing this behavior in LLDB will
be added in a separately.

The human readable trap messages are based on the messages currently
emitted by the userspace runtime for UBSan in compiler-rt. Note the
wording is not identical because the userspace UBSan runtime has access
to dynamic information that is not available during Clang’s codegen.

Test cases for each UBSan trap kind are included.

This complements the [`-fsanitize-annotate-debug-info`
feature](llvm#141997). While
`-fsanitize-annotate-debug-info` attempts to annotate all UBSan-added
instructions, this feature (`-fsanitize-debug-trap-reasons`) only
annotates the final trap instruction using SanitizerHandler information.

This work is part of a GSoc 2025 project.

(cherry picked from commit ba477b9)
(cherry picked from commit 29992cf)
…#151231)

In llvm#145967 Clang was taught to emit trap reasons on UBSan traps in debug
info using the same method as `__builtin_verbose_trap`. This patch adds
a test case to make sure that the existing "Verbose Trap StackFrame
Recognizer" recognizes the trap reason and sets the stop reason and
stack frame appropriately.

Part of a GSoC 2025 Project.

(cherry picked from commit a8d0ae3)
Same reason we skip the other verbose_trap tests.

Fails on Windows CI

(cherry picked from commit 21bf2fa)
…lvm#154628)

When trying to add a new diagnostic category (e.g. llvm#154618) I discovered
`clang-format` really wanted to reformat these files.

My initial attempt was just to suppress the reformatting with `//
clang-format (on|off)` directives but reviewers preferred just
reformatting the files so these two files have been completely
reformatted.

`clang-format` has been disabled for the enum that declares the
`DIAG_START_*` constants because its much less readable after
formatting.

(cherry picked from commit 0961200)

Conflicts:
	clang/include/clang/Basic/DiagnosticIDs.h
@delcypher
Copy link
Author

@swift-ci test llvm

@delcypher
Copy link
Author

@swift-ci test

…sons" (llvm#154618)

In 29992cf (llvm#145967) support was added
for "trap reasons" on traps emitted in UBSan in trapping mode (e.g.
`-fsanitize-trap=undefined`). This improved the debugging experience by
attaching the reason for trapping as a string on the debug info on trap
instructions. Consumers such as LLDB can display this trap reason string
when the trap is reached.

A limitation of that patch is that the trap reason string is hard-coded
for each `SanitizerKind` even though the compiler actually has much more
information about the trap available at compile time that could be shown
to the user.

This patch is an incremental step in fixing that. It consists of two
main steps.

**1. Introduce infrastructure for building trap reason strings**

To make it convenient to construct trap reason strings this patch
re-uses Clang's powerful diagnostic infrastructure to provide a
convenient API for constructing trap reason strings. This is achieved
by:

* Introducing a new `Trap` diagnostic kind to represent trap diagnostics
in TableGen files.
* Adding a new `Trap` diagnostic component. While this part probably
isn't technically necessary it seemed like I should follow the existing
convention used by the diagnostic system.
* Adding `DiagnosticTrapKinds.td` to describe the different trap
reasons.
* Add the `TrapReasonBuilder` and `TrapReason` classes to provide an
interface for constructing trap reason strings and the trap category.
Note this API while similar to `DiagnosticBuilder` has different
semantics which are described in the code comments. In particular the
behavior when the destructor is called is very different.
* Adding `CodeGenModule::BuildTrapReason()` as a convenient constructor
for the `TrapReasonBuilder`.

This use of the diagnostic system is a little unusual in that the
emitted trap diagnostics aren't actually consumed by normal diagnostic
consumers (e.g. the console). Instead the `TrapReasonBuilder` is just
used to format a string, so in effect the builder is somewhat analagous
to "printf". However, re-using the diagnostics system in this way brings
a several benefits:

* The powerful diagnostic templating languge (e.g. `%select`) can be
used.
* Formatting Clang data types (e.g. `Type`, `Expr`, etc.) just work
out-of-the-box.
* Describing trap reasons in tablegen files opens the door for
translation to different languages in the future.
* The `TrapReasonBuilder` API is very similar to `DiagnosticBuilder`
which makes it easy to use by anyone already familiar with Clang's
diagnostic system.

While UBSan is the first consumer of this new infrastructure the intent
is to use this to overhaul how trap reasons are implemented in the
`-fbounds-safety` implementation (currently exists downstream).

**2. Apply the new infrastructure to UBSan checks for arithmetic
overflow**

To demonstrate using `TrapReasonBuilder` this patch applies it to UBSan
traps for arithmetic overflow. The intention is that we would
iteratively switch to using the `TrapReasonBuilder` for all UBSan traps
where it makes sense in future patches.

Previously for code like

```
int test(int a, int b) { return a + b; }
```

The trap reason string looked like

```
Undefined Behavior Sanitizer: Integer addition overflowed
```

now the trap message looks like:

```
Undefined Behavior Sanitizer: signed integer addition overflow in 'a + b'
```

This string is much more specific because

* It explains if signed or unsigned overflow occurred
* It actually shows the expression that overflowed

One possible downside of this approach is it may blow up Debug info size
because now there can be many more distinct trap reason strings. To
allow users to avoid this a new driver/cc1 flag
`-fsanitize-debug-trap-reasons=` has been added which can either be
`none` (disable trap reasons entirely), `basic` (use the per
`SanitizerKind` hard coded strings), and `detailed` (use the new
expressive trap reasons implemented in this patch). The default is
`detailed` to give the best out-of-the-box debugging experience. The
existing `-fsanitize-debug-trap-reasons` and
`-fno-sanitize-debug-trap-reasons` have been kept for compatibility and
are aliases of the new flag with `detailed` and `none` arguments passed
respectively.

rdar://158612755

Conflicts:
	clang/include/clang/Basic/AllDiagnosticKinds.inc
	clang/include/clang/Basic/DiagnosticIDs.h
	clang/lib/Basic/DiagnosticIDs.cpp
	clang/lib/CodeGen/CGExpr.cpp
	clang/lib/CodeGen/CodeGenFunction.h
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticIDs.h

rdar://159302620

(cherry picked from commit 6d385c3)
(cherry picked from commit f1ee047)
@delcypher delcypher force-pushed the dliew/rdar/159302620 branch from a486999 to 4a7139b Compare September 9, 2025 00:09
@delcypher
Copy link
Author

@swift-ci test llvm

@delcypher
Copy link
Author

@swift-ci test

@delcypher
Copy link
Author

Given that these changes were already approved upstream I intend to merge once CI checks look good.

@delcypher
Copy link
Author

Seems I broke CAS diagnostic emission for some reason.

[2025-09-09T00:50:05.788Z] clang: /home/build-user/llvm-project/clang/lib/Basic/DiagnosticIDs.cpp:230: const {anonymous}::StaticDiagInfoRec* GetDiagInfo(unsigned int): Assertion `ID < StaticDiagInfoSize && Offset < StaticDiagInfoSize' failed.
[2025-09-09T00:50:05.788Z] PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
[2025-09-09T00:50:05.788Z] Stack dump:
[2025-09-09T00:50:05.788Z] 0.	Program arguments: /home/build-user/llvm-project/build/bin/clang -cc1depscan -o - -cc1-args -cc1 -triple x86_64-apple-darwin10 -debug-info-kind=standalone -dwarf-version=4 -debugger-tuning=lldb -emit-obj -fcas-backend -fcas-path /home/build-user/llvm-project/build/tools/clang/test/CAS/Output/depscan-update-mccas.c.tmp/cas -fcas-emit-casid-file -mllvm -cas-friendly-debug-info /home/build-user/llvm-project/clang/test/CAS/depscan-update-mccas.c
[2025-09-09T00:50:05.788Z]  #0 0x000055a56de6d110 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/build-user/llvm-project/build/bin/clang+0x2afb110)
[2025-09-09T00:50:05.788Z]  #1 0x000055a56de69dbf llvm::sys::RunSignalHandlers() (/home/build-user/llvm-project/build/bin/clang+0x2af7dbf)
[2025-09-09T00:50:05.788Z]  #2 0x000055a56de69f12 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
[2025-09-09T00:50:05.788Z]  #3 0x00007f5831ef9520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
[2025-09-09T00:50:05.788Z]  #4 0x00007f5831f4d9fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
[2025-09-09T00:50:05.788Z]  #5 0x00007f5831ef9476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
[2025-09-09T00:50:05.788Z]  #6 0x00007f5831edf7f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
[2025-09-09T00:50:05.788Z]  #7 0x00007f5831edf71b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
[2025-09-09T00:50:05.788Z]  #8 0x00007f5831ef0e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
[2025-09-09T00:50:05.788Z]  #9 0x000055a56e09cbab (/home/build-user/llvm-project/build/bin/clang+0x2d2abab)
[2025-09-09T00:50:05.788Z] #10 0x000055a56e09f61f clang::DiagnosticIDs::getDiagnosticLevel(unsigned int, clang::SourceLocation, clang::DiagnosticsEngine const&) const (/home/build-user/llvm-project/build/bin/clang+0x2d2d61f)
[2025-09-09T00:50:05.788Z] #11 0x000055a56e090c14 clang::DiagnosticsEngine::ProcessDiag(clang::DiagnosticBuilder const&) (/home/build-user/llvm-project/build/bin/clang+0x2d1ec14)
[2025-09-09T00:50:05.788Z] #12 0x000055a56c0caff1 clang::DiagnosticBuilder::~DiagnosticBuilder() (/home/build-user/llvm-project/build/bin/clang+0xd58ff1)
[2025-09-09T00:50:05.788Z] #13 0x000055a56c0e9ab8 scanAndUpdateCC1(char const*, llvm::ArrayRef<char const*>, llvm::SmallVectorImpl<char const*>&, clang::DiagnosticsEngine&, llvm::opt::ArgList const&, clang::CASOptions const&, std::optional<llvm::cas::CASID>&) cc1depscan_main.cpp:0:0
[2025-09-09T00:50:05.788Z] #14 0x000055a56c0ec6da cc1depscan_main(llvm::ArrayRef<char const*>, char const*, void*) (/home/build-user/llvm-project/build/bin/clang+0xd7a6da)
[2025-09-09T00:50:05.788Z] #15 0x000055a56c0be1fa ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) driver.cpp:0:0
[2025-09-09T00:50:05.788Z] #16 0x000055a56c0c2916 clang_main(int, char**, llvm::ToolContext const&) (/home/build-user/llvm-project/build/bin/clang+0xd50916)
[2025-09-09T00:50:05.788Z] #17 0x000055a56bfcc2eb main (/home/build-user/llvm-project/build/bin/clang+0xc5a2eb)
[2025-09-09T00:50:05.788Z] #18 0x00007f5831ee0d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
[2025-09-09T00:50:05.788Z] #19 0x00007f5831ee0e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
[2025-09-09T00:50:05.788Z] #20 0x000055a56c0bcca5 _start (/home/build-user/llvm-project/build/bin/clang+0xd4aca5)
[2025-09-09T00:50:05.789Z] FileCheck error: '<stdin>' is empty.
[2025-09-09T00:50:05.789Z] FileCheck command line:  /home/build-user/llvm-project/build/bin/FileCheck /home/build-user/llvm-project/clang/test/CAS/depscan-update-mccas.c --check-prefix=MCCAS_ON

Accidentally broken by recent merge resolution.

(cherry picked from commit 9cf7934)
@delcypher
Copy link
Author

@swift-ci test

@delcypher
Copy link
Author

@swift-ci test llvm

@delcypher
Copy link
Author

Linux:

[2025-09-09T02:20:16.173Z] ********************
[2025-09-09T02:20:16.173Z] Failed Tests (10):
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-attr-exception.m
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-block-descriptor-pointer.m
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-block-isa.m
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-class-ro.m
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-objc-isa-super.m
[2025-09-09T02:20:16.173Z]   Clang :: CodeGenObjC/ptrauth-objc-method-list-pointer.m
[2025-09-09T02:20:16.173Z]   Clang :: Sema/ptrauth-qualifier.c
[2025-09-09T02:20:16.173Z]   Clang :: SemaCXX/attr-transparent-stepping-method.cpp
[2025-09-09T02:20:16.173Z]   Clang :: SemaObjC/ptrauth-qualifier.m

macOS:

[2025-09-09T03:10:17.291Z] ********************
[2025-09-09T03:10:17.291Z] Failed Tests (10):
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenCXX/ptrauth-explicit-vtable-pointer-control.cpp
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-attr-exception.m
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-block-descriptor-pointer.m
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-block-isa.m
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-class-ro.m
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-objc-isa-super.m
[2025-09-09T03:10:17.291Z]   Clang :: CodeGenObjC/ptrauth-objc-method-list-pointer.m
[2025-09-09T03:10:17.291Z]   Clang :: Sema/ptrauth-qualifier.c
[2025-09-09T03:10:17.291Z]   Clang :: SemaCXX/attr-transparent-stepping-method.cpp
[2025-09-09T03:10:17.291Z]   Clang :: SemaObjC/ptrauth-qualifier.m
[2025-09-09T03:10:17.291Z] 
[2025-09-09T04:55:09.670Z] ********************
[2025-09-09T04:55:09.670Z] Failed Tests (1):
[2025-09-09T04:55:09.670Z]   Swift-validation(iphonesimulator-x86_64) :: compiler_crashers_2/a79aa9924bdc378.swift

@delcypher
Copy link
Author

Failures appear unrelated to my changes so going to merge.

@delcypher delcypher merged commit 5abacac into swiftlang:stable/21.x Sep 9, 2025
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants