[compiler-rt] [hwasan] Fix stack tag mismatch report (PR #81939)
Florian Mayer via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 15 16:02:38 PST 2024
================
@@ -230,33 +230,70 @@ static void PrintStackAllocations(const StackAllocationsRingBuffer *sa,
tag_t obj_tag = base_tag ^ local.tag_offset;
if (obj_tag != addr_tag)
continue;
- // Guess top bits of local variable from the faulting address, because
- // we only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
- uptr local_beg = (fp + local.frame_offset) |
- (untagged_addr & ~(uptr(kRecordFPModulus) - 1));
- uptr local_end = local_beg + local.size;
+
+ // We only store bits 4-19 of FP (bits 0-3 are guaranteed to be zero).
+ // So we know only `FP % kRecordFPModulus`, and we can only calculate
+ // `local_beg % kRecordFPModulus`.
+ // Out of all possible `local_beg` we will only consider two candidates
+ // nearest to the `untagged_addr`.
+ uptr local_beg_mod = (fp + local.frame_offset) % kRecordFPModulus;
+ // Pick `local_beg` in the same 1 MiB block as `untagged_addr`.
+ uptr local_beg =
+ RoundDownTo(untagged_addr, kRecordFPModulus) + local_beg_mod;
+ // Pick the largest `local_beg <= untagged_addr`. It's either the current
+ // one or the one before.
+ if (local_beg > untagged_addr)
+ local_beg -= kRecordFPModulus;
+
+ uptr offset = -1ull;
+ const char *whence;
+ const char *cause = nullptr;
+ uptr best_beg;
+
+ // Try two 1 MiB blocks options and pick nearest one.
+ for (uptr i = 0; i < 2; ++i, local_beg += kRecordFPModulus) {
+ uptr local_end = local_beg + local.size;
+ if (local_beg > local_end)
+ continue; // This is a wraparound.
+ if (local_beg <= untagged_addr && untagged_addr < local_end) {
----------------
fmayer wrote:
> (and negligibly faster)
if you can figure it out, clang should be able to too.
https://github.com/llvm/llvm-project/pull/81939
More information about the llvm-commits
mailing list