[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