[compiler-rt] a1584dd - [hwasan] Store some report data early (#66682)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 21 15:27:08 PDT 2023


Author: Vitaly Buka
Date: 2023-09-21T15:27:03-07:00
New Revision: a1584dd2013e408fd040f487d4b989fcf389af59

URL: https://github.com/llvm/llvm-project/commit/a1584dd2013e408fd040f487d4b989fcf389af59
DIFF: https://github.com/llvm/llvm-project/commit/a1584dd2013e408fd040f487d4b989fcf389af59.diff

LOG: [hwasan] Store some report data early (#66682)

Please review them one by one in order, and let me know which are OK.
It's mostly code shuffling.

The goal is to make HWASA collect all needed info the first, and
printout later.
This way we avoid the printing changes HWASAN metadata.

Added: 
    

Modified: 
    compiler-rt/lib/hwasan/hwasan_report.cpp

Removed: 
    


################################################################################
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);


        


More information about the llvm-commits mailing list