You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[UBSan][BoundsSafety] Implement support for more expressive "trap reasons" (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)
Copy file name to clipboardExpand all lines: clang/docs/ReleaseNotes.rst
+24-9Lines changed: 24 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -366,18 +366,33 @@ Non-comprehensive list of changes in this release
366
366
correct method to check for these features is to test for the ``__PTRAUTH__``
367
367
macro.
368
368
369
-
- Trapping UBSan (e.g. ``-fsanitize-trap=undefined``) now emits a string describing the reason for
370
-
trapping into the generated debug info. This feature allows debuggers (e.g. LLDB) to display
371
-
the reason for trapping if the trap is reached. The string is currently encoded in the debug
372
-
info as an artificial frame that claims to be inlined at the trap location. The function used
373
-
for the artificial frame is an artificial function whose name encodes the reason for trapping.
374
-
The encoding used is currently the same as ``__builtin_verbose_trap`` but might change in the future.
375
-
This feature is enabled by default but can be disabled by compiling with
376
-
``-fno-sanitize-annotate-debug-info-traps``.
369
+
- Trapping UBSan (e.g. ``-fsanitize=undefined -fsanitize-trap=undefined``) now
370
+
emits a string describing the reason for trapping into the generated debug
371
+
info. This feature allows debuggers (e.g. LLDB) to display the reason for
372
+
trapping if the trap is reached. The string is currently encoded in the debug
373
+
info as an artificial frame that claims to be inlined at the trap location.
374
+
The function used for the artificial frame is an artificial function whose
375
+
name encodes the reason for trapping. The encoding used is currently the same
376
+
as ``__builtin_verbose_trap`` but might change in the future. This feature is
377
+
enabled by default but can be disabled by compiling with
378
+
``-fno-sanitize-debug-trap-reasons``. The feature has a ``basic`` and
379
+
``detailed`` mode (the default). The ``basic`` mode emits a hard-coded string
380
+
per trap kind (e.g. ``Integer addition overflowed``) and the ``detailed`` mode
381
+
emits a more descriptive string describing each individual trap (e.g. ``signed
382
+
integer addition overflow in 'a + b'``). The ``detailed`` mode produces larger
383
+
debug info than ``basic`` but is more helpful for debugging. The
384
+
``-fsanitize-debug-trap-reasons=`` flag can be used to switch between the
385
+
different modes or disable the feature entirely. Note due to trap merging in
386
+
optimized builds (i.e. in each function all traps of the same kind get merged
387
+
into the same trap instruction) the trap reasons might be removed. To prevent
388
+
this build without optimizations (i.e. use `-O0` or use the `optnone` function
389
+
attribute) or use the `fno-sanitize-merge=` flag in optimized builds.
377
390
378
391
New Compiler Flags
379
392
------------------
380
-
- New option ``-fno-sanitize-annotate-debug-info-traps`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
393
+
- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
394
+
- New option ``-fsanitize-debug-trap-reasons=`` added to control emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
395
+
381
396
382
397
- New option ``-Wundef-true`` added and enabled by default to warn when `true` is used in the C preprocessor without being defined before C23.
ENUM_CODEGENOPT(SanitizeDebugTrapReasons, SanitizeDebugTrapReasonKind, 2, SanitizeDebugTrapReasonKind::Detailed, Benign) ///< Control how "trap reasons" are emitted in debug info
310
310
CODEGENOPT(SimplifyLibCalls , 1, 1, Benign) ///< Set when -fbuiltin is enabled.
0 commit comments