-
Notifications
You must be signed in to change notification settings - Fork 13.5k
Modify BoundsSan to improve debuggability #65972
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
CC: @vitalybuka I addressed some but not all comments pending further clarification :) |
@llvm/pr-subscribers-clang ChangesContext Problem Godbolt example of the optimization: https://godbolt.org/z/6qjax9z1b This Diff
|
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.
the code LGTM,
but llvm-project/llvm/test/Instrumentation/BoundsChecking/ test is needed
Maybe just extend llvm-project/llvm/test/Instrumentation/BoundsChecking/simple.ll
@@ -0,0 +1,83 @@ | |||
; RUN: llc -O3 -mtriple arm64-linux -filetype asm -o - %s | FileCheck %s -check-prefix CHECK-ASM | |||
; What this test does is check that even with nomerge, the functions still get merged in | |||
; compiled code as the ubsantrap call gets lowered to a single instruction: brk. |
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.
you don't change MC, so I don't think we need the test here
However we need a test in llvm-project/llvm/test/Instrumentation/BoundsChecking/
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.
I understood your comment on the Phabricator diff as a request for this test:
can you please create a test where bounds-checking-single-trap=0 and setCannotMerge produce invalid result.
I will also add a test in llvm/test/Instrumentation/BoundsChecking/
7469d00
to
6018564
Compare
@vitalybuka Thank you for reviewing! Can you merge this? I don't have write access (yet!) |
@oskarwirga I'd like to use this feature but without counter, preserving ubsan IDs Also I think in the current the counter has limited use: in optimized code, after inlining, it will have a lot of same ids, like 0, 1 from different functions. So I propose to undo that part of the patch. WDYT? |
So long as the debuggability is preserved so that it is possible to attribute crashes to specific lines of code, I am fine! Do you have an alternate solution? |
In IR these traps are not de-duplicated with -ubsan-unique-traps |
This test demonstrates that UBSan does not add the nomerge annotation. This is significant because it results in them being merged by the backend. N.B. llvm#65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of llvm#53011. llvm#101549 fixed that limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."); planned upcoming will add nomerge for ubsan.
llvm#65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of llvm#53011. Instead, it added a counter (based on TrapBB->getParent()->size()) to each ubsantrap call. However, this counter is not guaranteed to be unique after inlining, as shown by llvm#83470, which can result in ubsantraps being merged by the backend. llvm#101549 fixed has since fixed the nomerge limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."). This patch therefore takes advantage of nomerge instead of using the counter, guaranteeing that the ubsantraps are not merged. This patch is equivalent to llvm#83470 but also adds nomerge and updates the test that was precommitted in llvm#117649.
…single-trap.ll (#117642) llvm/test/MC/AArch64/local-bounds-single-trap.ll was introduced in #65972 to demonstrate that nomerge did not work properly, which is documented in the header comment. #101549 fixed nomerge for trap builtins and ae6dc64 updated the test assertions, but not the header comment. This patch updates the header comment accordingly.
…117649) This test (copied from #83470) demonstrates that UBSan does not add the nomerge annotation. This is significant because it can result in them being merged by the backend, even when -ubsan-unique-traps is enabled. N.B. #65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of #53011. #101549 fixed that limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."); planned upcoming work (#117651) will add nomerge for ubsan.
llvm#65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of llvm#53011. Instead, it added a counter (based on TrapBB->getParent()->size()) to each ubsantrap call. However, this counter is not guaranteed to be unique after inlining, as shown by llvm#83470, which can result in ubsantraps being merged by the backend. llvm#101549 fixed has since fixed the nomerge limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."). This patch therefore takes advantage of nomerge instead of using the counter, guaranteeing that the ubsantraps are not merged. This patch is equivalent to llvm#83470 but also adds nomerge and updates the test that was precommitted in llvm#117649.
…nomerge" (llvm#117804) This reverts commit c8bdb31. It was reverted because I forgot to update the auto-generated assertions after adding the target triple. Original commit message: This test (copied from llvm#83470) demonstrates that UBSan does not add the nomerge annotation. This is significant because it can result in them being merged by the backend, even when -ubsan-unique-traps is enabled. N.B. llvm#65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of llvm#53011. llvm#101549 fixed that limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."); planned upcoming work (llvm#117651) will add nomerge for ubsan.
…nomerge" (#117804) (#117805) This reverts commit c8bdb31. It was reverted because I forgot to update the auto-generated assertions after adding the target triple. Original commit message: This test (copied from #83470) demonstrates that UBSan does not add the nomerge annotation. This is significant because it can result in them being merged by the backend, even when -ubsan-unique-traps is enabled. N.B. #65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of #53011. #101549 fixed that limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."); planned upcoming work (#117651) will add nomerge for ubsan.
llvm#65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of llvm#53011. Instead, it added a counter (based on TrapBB->getParent()->size()) to each ubsantrap call. However, this counter is not guaranteed to be unique after inlining, as shown by llvm#83470, which can result in ubsantraps being merged by the backend. llvm#101549 fixed has since fixed the nomerge limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."). This patch therefore takes advantage of nomerge instead of using the counter, guaranteeing that the ubsantraps are not merged. This patch is equivalent to llvm#83470 but also adds nomerge and updates the test that was precommitted in llvm#117649.
…117651) #65972 (continuation of https://reviews.llvm.org/D148654) had considered adding nomerge to ubsantrap, but did not proceed with that because of #53011. Instead, it added a counter (based on TrapBB->getParent()->size()) to each ubsantrap call. However, this counter is not guaranteed to be unique after inlining, as shown by #83470, which can result in ubsantraps being merged by the backend. #101549 has since fixed the nomerge limitation ("It sets nomerge flag for the node if the instruction has nomerge arrtibute."). This patch therefore takes advantage of nomerge instead of using the counter, guaranteeing that the ubsantraps are not merged. This patch is equivalent to #83470 but also adds nomerge and updates tests (#117649: ubsan-trap-merge.c; #117657: ubsan-trap-merge.ll, ubsan-trap-nomerge.ll; catch-undef-behavior.c).
…d-handlers) '-mllvm -ubsan-unique-traps' (llvm#65972) applies to all UBSan checks. This patch introduces -fsanitize-nonmerged-handlers and -fno-sanitize-nonmerged-handlers, which allows selectively applying non-merged handlers to a subset of UBSan checks. N.B. we use "non-merged handlers" instead of "unique traps", since llvm#119302 has generalized it to work for non-trap mode as well (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-non-merged-handlers.
'-mllvm -ubsan-unique-traps' (#65972) applies to all UBSan checks. This patch introduces -fsanitize-merge (defaults to on, maintaining the status quo behavior) and -fno-sanitize-merge (equivalent to '-mllvm -ubsan-unique-traps'), with the option to selectively applying non-merged handlers to a subset of UBSan checks (e.g., -fno-sanitize-merge=bool,enum). N.B. we do not use "trap" in the argument name since #119302 has generalized -ubsan-unique-traps to work for non-trap modes (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-merge.
…#120464)" This reverts commit 2691b96. This reapply fixes the buildbot breakage of the original patch, by updating clang/test/CodeGen/ubsan-trap-debugloc.c to specify -fsanitize-merge (the default, which is merge, is applied by the driver but not clang_cc1). This reapply also expands clang/test/CodeGen/ubsan-trap-merge.c. Original commit message: '-mllvm -ubsan-unique-traps' (llvm#65972) applies to all UBSan checks. This patch introduces -fsanitize-merge (defaults to on, maintaining the status quo behavior) and -fno-sanitize-merge (equivalent to '-mllvm -ubsan-unique-traps'), with the option to selectively applying non-merged handlers to a subset of UBSan checks (e.g., -fno-sanitize-merge=bool,enum). N.B. we do not use "trap" in the argument name since llvm#119302 has generalized -ubsan-unique-traps to work for non-trap modes (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-merge.
…464)" (#120511) This reverts commit 2691b96. This reapply fixes the buildbot breakage of the original patch, by updating clang/test/CodeGen/ubsan-trap-debugloc.c to specify -fsanitize-merge (the default, which is merge, is applied by the driver but not clang_cc1). This reapply also expands clang/test/CodeGen/ubsan-trap-merge.c. ---- Original commit message: '-mllvm -ubsan-unique-traps' (#65972) applies to all UBSan checks. This patch introduces -fsanitize-merge (defaults to on, maintaining the status quo behavior) and -fno-sanitize-merge (equivalent to '-mllvm -ubsan-unique-traps'), with the option to selectively applying non-merged handlers to a subset of UBSan checks (e.g., -fno-sanitize-merge=bool,enum). N.B. we do not use "trap" in the argument name since #119302 has generalized -ubsan-unique-traps to work for non-trap modes (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-merge.
… applicable llvm#65972 introduced -ubsan-unique-traps and -bounds-checking-unique-traps, which attach the function size to the ubsantrap intrinsic. llvm#117651 changed ubsan-unique-traps to use nomerge instead of the function size, but did not update -bounds-checking-unique-traps. This patch adds nomerge to bounds-checking-unique-traps.
… applicable llvm#65972 introduced -ubsan-unique-traps and -bounds-checking-unique-traps, which attach the function size to the ubsantrap intrinsic. llvm#117651 changed ubsan-unique-traps to use nomerge instead of the function size, but did not update -bounds-checking-unique-traps. This patch adds nomerge to bounds-checking-unique-traps.
… applicable (#120620) #65972 introduced -ubsan-unique-traps and -bounds-checking-unique-traps, which attach the function size to the ubsantrap intrinsic. #117651 changed ubsan-unique-traps to use nomerge instead of the function size, but did not update -bounds-checking-unique-traps. This patch adds nomerge to bounds-checking-unique-traps.
…20464) '-mllvm -ubsan-unique-traps' (llvm/llvm-project#65972) applies to all UBSan checks. This patch introduces -fsanitize-merge (defaults to on, maintaining the status quo behavior) and -fno-sanitize-merge (equivalent to '-mllvm -ubsan-unique-traps'), with the option to selectively applying non-merged handlers to a subset of UBSan checks (e.g., -fno-sanitize-merge=bool,enum). N.B. we do not use "trap" in the argument name since llvm/llvm-project#119302 has generalized -ubsan-unique-traps to work for non-trap modes (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-merge.
…erge) (#120…464)" (#120511) This reverts commit 2691b96. This reapply fixes the buildbot breakage of the original patch, by updating clang/test/CodeGen/ubsan-trap-debugloc.c to specify -fsanitize-merge (the default, which is merge, is applied by the driver but not clang_cc1). This reapply also expands clang/test/CodeGen/ubsan-trap-merge.c. ---- Original commit message: '-mllvm -ubsan-unique-traps' (llvm/llvm-project#65972) applies to all UBSan checks. This patch introduces -fsanitize-merge (defaults to on, maintaining the status quo behavior) and -fno-sanitize-merge (equivalent to '-mllvm -ubsan-unique-traps'), with the option to selectively applying non-merged handlers to a subset of UBSan checks (e.g., -fno-sanitize-merge=bool,enum). N.B. we do not use "trap" in the argument name since llvm/llvm-project#119302 has generalized -ubsan-unique-traps to work for non-trap modes (min-rt and regular rt). This patch does not remove the -ubsan-unique-traps flag; that will override -f(no-)sanitize-merge.
…ibute where applicable (#120620) llvm/llvm-project#65972 introduced -ubsan-unique-traps and -bounds-checking-unique-traps, which attach the function size to the ubsantrap intrinsic. llvm/llvm-project#117651 changed ubsan-unique-traps to use nomerge instead of the function size, but did not update -bounds-checking-unique-traps. This patch adds nomerge to bounds-checking-unique-traps.
Context
BoundsSanitizer is a mitigation that is part of UBSAN. It can be enabled in "trap" mode to crash on OOB array accesses.
Problem
BoundsSan has zero false positives meaning every crash is a OOB array access, unfortunately optimizations cause these crashes in production builds to be a bit useless because we only know which function is crashing but not which line of code.
Godbolt example of the optimization: https://godbolt.org/z/6qjax9z1b
This Diff
I wanted to provide a way to know exactly which LOC is responsible for the crash. What we do here is use the size of the basic block as an iterator to an immediate value for the ubsan trap.
Previous discussion: https://reviews.llvm.org/D148654