[compiler-rt] DO_NOT_MERGE (PR #66682)
Vitaly Buka via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 21 14:59:57 PDT 2023
https://github.com/vitalybuka updated https://github.com/llvm/llvm-project/pull/66682
>From 04087c211f642980f3c7d81b860053151cc83b67 Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Wed, 20 Sep 2023 22:41:09 -0700
Subject: [PATCH 1/2] [NFC][hwasan] Find mismatch offset early (#66682)
---
compiler-rt/lib/hwasan/hwasan_report.cpp | 65 +++++++++++++++---------
1 file changed, 40 insertions(+), 25 deletions(-)
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 34d756c9d9ede62..3c20effdd318b93 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -395,6 +395,7 @@ class BaseReport {
access_size(access_size),
untagged_addr(UntagAddr(tagged_addr)),
ptr_tag(GetTagFromPointer(tagged_addr)),
+ mismatch_offset(FindMismatchOffset()),
heap(CopyHeapChunk()),
allocations(CopyAllocations()),
candidate(FindBufferOverflowCandidate()),
@@ -442,6 +443,7 @@ class BaseReport {
tag_t short_tags[ARRAY_SIZE(tags)] = {};
};
+ sptr FindMismatchOffset() const;
Shadow CopyShadow() const;
tag_t GetTagCopy(uptr addr) const;
tag_t GetShortTagCopy(uptr addr) const;
@@ -461,6 +463,7 @@ class BaseReport {
const uptr access_size = 0;
const uptr untagged_addr = 0;
const tag_t ptr_tag = 0;
+ const sptr mismatch_offset = 0;
const HeapChunk heap;
const Allocations allocations;
@@ -469,6 +472,37 @@ class BaseReport {
const Shadow shadow;
};
+sptr BaseReport::FindMismatchOffset() const {
+ if (!access_size)
+ return 0;
+ sptr offset =
+ __hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
+ CHECK_GE(offset, 0);
+ CHECK_LT(offset, static_cast<sptr>(access_size));
+ tag_t *tag_ptr =
+ reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
+ tag_t mem_tag = *tag_ptr;
+
+ if (mem_tag && mem_tag < kShadowAlignment) {
+ tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) &
+ ~(kShadowAlignment - 1));
+ // If offset is 0, (untagged_addr + offset) is not aligned to granules.
+ // This is the offset of the leftmost accessed byte within the bad granule.
+ u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1);
+ tag_t short_tag = granule_ptr[kShadowAlignment - 1];
+ // The first mismatch was a short granule that matched the ptr_tag.
+ if (short_tag == ptr_tag) {
+ // If the access starts after the end of the short granule, then the first
+ // bad byte is the first byte of the access; otherwise it is the first
+ // byte past the end of the short granule
+ if (mem_tag > in_granule_offset) {
+ offset += mem_tag - in_granule_offset;
+ }
+ }
+ }
+ return offset;
+}
+
BaseReport::Shadow BaseReport::CopyShadow() const {
Shadow result;
if (!MemIsApp(untagged_addr))
@@ -917,31 +951,12 @@ TagMismatchReport::~TagMismatchReport() {
Thread *t = GetCurrentThread();
- sptr offset =
- __hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
- CHECK_GE(offset, 0);
- CHECK_LT(offset, static_cast<sptr>(access_size));
- tag_t *tag_ptr =
- reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
- tag_t mem_tag = *tag_ptr;
+ tag_t mem_tag = GetTagCopy(MemToShadow(untagged_addr + mismatch_offset));
Printf("%s", d.Access());
if (mem_tag && mem_tag < kShadowAlignment) {
- tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) &
- ~(kShadowAlignment - 1));
- // If offset is 0, (untagged_addr + offset) is not aligned to granules.
- // This is the offset of the leftmost accessed byte within the bad granule.
- u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1);
- tag_t short_tag = granule_ptr[kShadowAlignment - 1];
- // The first mismatch was a short granule that matched the ptr_tag.
- if (short_tag == ptr_tag) {
- // If the access starts after the end of the short granule, then the first
- // bad byte is the first byte of the access; otherwise it is the first
- // byte past the end of the short granule
- if (mem_tag > in_granule_offset) {
- offset += mem_tag - in_granule_offset;
- }
- }
+ tag_t short_tag =
+ GetShortTagCopy(MemToShadow(untagged_addr + mismatch_offset));
Printf(
"%s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n",
is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
@@ -951,8 +966,8 @@ TagMismatchReport::~TagMismatchReport() {
is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
mem_tag, t->unique_id());
}
- if (offset != 0)
- Printf("Invalid access starting at offset %zu\n", offset);
+ if (mismatch_offset)
+ Printf("Invalid access starting at offset %zu\n", mismatch_offset);
Printf("%s", d.Default());
stack->Print();
@@ -960,7 +975,7 @@ TagMismatchReport::~TagMismatchReport() {
PrintAddressDescription();
t->Announce();
- PrintTags(untagged_addr + offset);
+ PrintTags(untagged_addr + mismatch_offset);
if (registers_frame)
ReportRegisters(registers_frame, pc);
>From b405e721c9fda68b8e2dffbb0b9f782ed32baaaf Mon Sep 17 00:00:00 2001
From: Vitaly Buka <vitalybuka at google.com>
Date: Thu, 21 Sep 2023 13:27:43 -0700
Subject: [PATCH 2/2] [hwasan] Optimize shadow shapshot size (#66682)
Now we copy only tags we will print.
CHECKs in GetTagCopy and GetShortTagCopy ensure that.
---
compiler-rt/lib/hwasan/hwasan_report.cpp | 39 ++++++++++++++++++------
1 file changed, 29 insertions(+), 10 deletions(-)
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cpp b/compiler-rt/lib/hwasan/hwasan_report.cpp
index 3c20effdd318b93..06cf75330bc6aa4 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_report.cpp
@@ -323,6 +323,22 @@ static uptr GetGlobalSizeFromDescriptor(uptr ptr) {
void ReportStats() {}
+constexpr uptr kShadowDumpWidth = 16;
+constexpr uptr kShadowDumpHeight = 17;
+constexpr uptr kShadowDumpSize = kShadowDumpHeight * kShadowDumpWidth;
+
+constexpr uptr kShortDumpHeight = 3;
+constexpr uptr kShortDumpSize = kShortDumpHeight * kShadowDumpWidth;
+constexpr uptr kShortDumpOffset =
+ (kShadowDumpHeight - kShortDumpHeight) / 2 * kShadowDumpWidth;
+
+static uptr GetPrintTagStart(uptr addr) {
+ addr = MemToShadow(addr);
+ addr = RoundDownTo(addr, kShadowDumpWidth);
+ addr -= kShadowDumpWidth * (kShadowDumpHeight / 2);
+ return addr;
+}
+
template <typename PrintTag>
static void PrintTagInfoAroundAddr(uptr addr, uptr num_rows,
InternalScopedString &s,
@@ -352,7 +368,7 @@ static void PrintTagsAroundAddr(uptr addr, GetTag get_tag,
"Memory tags around the buggy address (one tag corresponds to %zd "
"bytes):\n",
kShadowAlignment);
- PrintTagInfoAroundAddr(addr, 17, s,
+ PrintTagInfoAroundAddr(addr, kShadowDumpHeight, s,
[&](InternalScopedString &s, uptr tag_addr) {
tag_t tag = get_tag(tag_addr);
s.AppendF("%02x", tag);
@@ -362,7 +378,7 @@ static void PrintTagsAroundAddr(uptr addr, GetTag get_tag,
"Tags for short granules around the buggy address (one tag corresponds "
"to %zd bytes):\n",
kShadowAlignment);
- PrintTagInfoAroundAddr(addr, 3, s,
+ PrintTagInfoAroundAddr(addr, kShortDumpHeight, s,
[&](InternalScopedString &s, uptr tag_addr) {
tag_t tag = get_tag(tag_addr);
if (tag >= 1 && tag <= kShadowAlignment) {
@@ -439,8 +455,8 @@ class BaseReport {
struct Shadow {
uptr addr = 0;
- tag_t tags[512] = {};
- tag_t short_tags[ARRAY_SIZE(tags)] = {};
+ tag_t tags[kShadowDumpSize] = {};
+ tag_t short_tags[kShortDumpSize] = {};
};
sptr FindMismatchOffset() const;
@@ -508,16 +524,19 @@ BaseReport::Shadow BaseReport::CopyShadow() const {
if (!MemIsApp(untagged_addr))
return result;
- result.addr = MemToShadow(untagged_addr) - ARRAY_SIZE(result.tags) / 2;
- for (uptr i = 0; i < ARRAY_SIZE(result.tags); ++i) {
- uptr tag_addr = result.addr + i;
+ result.addr = GetPrintTagStart(untagged_addr + mismatch_offset);
+ uptr tag_addr = result.addr;
+ uptr short_end = kShortDumpOffset + ARRAY_SIZE(shadow.short_tags);
+ for (uptr i = 0; i < ARRAY_SIZE(result.tags); ++i, ++tag_addr) {
if (!MemIsShadow(tag_addr))
continue;
result.tags[i] = *reinterpret_cast<tag_t *>(tag_addr);
+ if (i < kShortDumpOffset || i >= short_end)
+ continue;
uptr granule_addr = ShadowToMem(tag_addr);
if (1 <= result.tags[i] && result.tags[i] <= kShadowAlignment &&
IsAccessibleMemoryRange(granule_addr, kShadowAlignment)) {
- result.short_tags[i] =
+ result.short_tags[i - kShortDumpOffset] =
*reinterpret_cast<tag_t *>(granule_addr + kShadowAlignment - 1);
}
}
@@ -532,8 +551,8 @@ tag_t BaseReport::GetTagCopy(uptr addr) const {
}
tag_t BaseReport::GetShortTagCopy(uptr addr) const {
- CHECK_GE(addr, shadow.addr);
- uptr idx = addr - shadow.addr;
+ CHECK_GE(addr, shadow.addr + kShortDumpOffset);
+ uptr idx = addr - shadow.addr - kShortDumpOffset;
CHECK_LT(idx, ARRAY_SIZE(shadow.short_tags));
return shadow.short_tags[idx];
}
More information about the llvm-commits
mailing list