Skip to content

Commit a1584dd

Browse files
authored
[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.
1 parent 700baeb commit a1584dd

File tree

1 file changed

+40
-25
lines changed

1 file changed

+40
-25
lines changed

compiler-rt/lib/hwasan/hwasan_report.cpp

+40-25
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ class BaseReport {
395395
access_size(access_size),
396396
untagged_addr(UntagAddr(tagged_addr)),
397397
ptr_tag(GetTagFromPointer(tagged_addr)),
398+
mismatch_offset(FindMismatchOffset()),
398399
heap(CopyHeapChunk()),
399400
allocations(CopyAllocations()),
400401
candidate(FindBufferOverflowCandidate()),
@@ -442,6 +443,7 @@ class BaseReport {
442443
tag_t short_tags[ARRAY_SIZE(tags)] = {};
443444
};
444445

446+
sptr FindMismatchOffset() const;
445447
Shadow CopyShadow() const;
446448
tag_t GetTagCopy(uptr addr) const;
447449
tag_t GetShortTagCopy(uptr addr) const;
@@ -461,6 +463,7 @@ class BaseReport {
461463
const uptr access_size = 0;
462464
const uptr untagged_addr = 0;
463465
const tag_t ptr_tag = 0;
466+
const sptr mismatch_offset = 0;
464467

465468
const HeapChunk heap;
466469
const Allocations allocations;
@@ -469,6 +472,37 @@ class BaseReport {
469472
const Shadow shadow;
470473
};
471474

475+
sptr BaseReport::FindMismatchOffset() const {
476+
if (!access_size)
477+
return 0;
478+
sptr offset =
479+
__hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
480+
CHECK_GE(offset, 0);
481+
CHECK_LT(offset, static_cast<sptr>(access_size));
482+
tag_t *tag_ptr =
483+
reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
484+
tag_t mem_tag = *tag_ptr;
485+
486+
if (mem_tag && mem_tag < kShadowAlignment) {
487+
tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) &
488+
~(kShadowAlignment - 1));
489+
// If offset is 0, (untagged_addr + offset) is not aligned to granules.
490+
// This is the offset of the leftmost accessed byte within the bad granule.
491+
u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1);
492+
tag_t short_tag = granule_ptr[kShadowAlignment - 1];
493+
// The first mismatch was a short granule that matched the ptr_tag.
494+
if (short_tag == ptr_tag) {
495+
// If the access starts after the end of the short granule, then the first
496+
// bad byte is the first byte of the access; otherwise it is the first
497+
// byte past the end of the short granule
498+
if (mem_tag > in_granule_offset) {
499+
offset += mem_tag - in_granule_offset;
500+
}
501+
}
502+
}
503+
return offset;
504+
}
505+
472506
BaseReport::Shadow BaseReport::CopyShadow() const {
473507
Shadow result;
474508
if (!MemIsApp(untagged_addr))
@@ -917,31 +951,12 @@ TagMismatchReport::~TagMismatchReport() {
917951

918952
Thread *t = GetCurrentThread();
919953

920-
sptr offset =
921-
__hwasan_test_shadow(reinterpret_cast<void *>(tagged_addr), access_size);
922-
CHECK_GE(offset, 0);
923-
CHECK_LT(offset, static_cast<sptr>(access_size));
924-
tag_t *tag_ptr =
925-
reinterpret_cast<tag_t *>(MemToShadow(untagged_addr + offset));
926-
tag_t mem_tag = *tag_ptr;
954+
tag_t mem_tag = GetTagCopy(MemToShadow(untagged_addr + mismatch_offset));
927955

928956
Printf("%s", d.Access());
929957
if (mem_tag && mem_tag < kShadowAlignment) {
930-
tag_t *granule_ptr = reinterpret_cast<tag_t *>((untagged_addr + offset) &
931-
~(kShadowAlignment - 1));
932-
// If offset is 0, (untagged_addr + offset) is not aligned to granules.
933-
// This is the offset of the leftmost accessed byte within the bad granule.
934-
u8 in_granule_offset = (untagged_addr + offset) & (kShadowAlignment - 1);
935-
tag_t short_tag = granule_ptr[kShadowAlignment - 1];
936-
// The first mismatch was a short granule that matched the ptr_tag.
937-
if (short_tag == ptr_tag) {
938-
// If the access starts after the end of the short granule, then the first
939-
// bad byte is the first byte of the access; otherwise it is the first
940-
// byte past the end of the short granule
941-
if (mem_tag > in_granule_offset) {
942-
offset += mem_tag - in_granule_offset;
943-
}
944-
}
958+
tag_t short_tag =
959+
GetShortTagCopy(MemToShadow(untagged_addr + mismatch_offset));
945960
Printf(
946961
"%s of size %zu at %p tags: %02x/%02x(%02x) (ptr/mem) in thread T%zd\n",
947962
is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
@@ -951,16 +966,16 @@ TagMismatchReport::~TagMismatchReport() {
951966
is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
952967
mem_tag, t->unique_id());
953968
}
954-
if (offset != 0)
955-
Printf("Invalid access starting at offset %zu\n", offset);
969+
if (mismatch_offset)
970+
Printf("Invalid access starting at offset %zu\n", mismatch_offset);
956971
Printf("%s", d.Default());
957972

958973
stack->Print();
959974

960975
PrintAddressDescription();
961976
t->Announce();
962977

963-
PrintTags(untagged_addr + offset);
978+
PrintTags(untagged_addr + mismatch_offset);
964979

965980
if (registers_frame)
966981
ReportRegisters(registers_frame, pc);

0 commit comments

Comments
 (0)