summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libartbase/base/memory_tool.h2
-rw-r--r--runtime/gc/collector/mark_compact-inl.h21
2 files changed, 16 insertions, 7 deletions
diff --git a/libartbase/base/memory_tool.h b/libartbase/base/memory_tool.h
index 675ceb2cfd..4a93a9642f 100644
--- a/libartbase/base/memory_tool.h
+++ b/libartbase/base/memory_tool.h
@@ -68,10 +68,12 @@ constexpr size_t kMemoryToolStackGuardSizeScale = 1;
#if __has_feature(hwaddress_sanitizer)
# define HWADDRESS_SANITIZER
+constexpr bool kHwAsanEnabled = true;
// NB: The attribute also implies NO_INLINE. If inlined, the hwasan attribute would be lost.
// If method is also separately marked as ALWAYS_INLINE, the NO_INLINE takes precedence.
# define ATTRIBUTE_NO_SANITIZE_HWADDRESS __attribute__((no_sanitize("hwaddress"), noinline))
#else
+constexpr bool kHwAsanEnabled = false;
# define ATTRIBUTE_NO_SANITIZE_HWADDRESS
#endif
diff --git a/runtime/gc/collector/mark_compact-inl.h b/runtime/gc/collector/mark_compact-inl.h
index 18095e8b58..24d47638b1 100644
--- a/runtime/gc/collector/mark_compact-inl.h
+++ b/runtime/gc/collector/mark_compact-inl.h
@@ -266,9 +266,10 @@ inline bool MarkCompact::VerifyRootSingleUpdate(void* root,
mirror::Object* old_ref,
const RootInfo& info) {
// ASAN promotes stack-frames to heap in order to detect
- // stack-use-after-return issues. So skip using this double-root update
- // detection on ASAN as well.
- if (kIsDebugBuild && !kMemoryToolIsAvailable) {
+ // stack-use-after-return issues. And HWASAN has pointers tagged, which makes
+ // it difficult to recognize and prevent stack pointers from being checked.
+ // So skip using double-root update detection on ASANs.
+ if (kIsDebugBuild && !kMemoryToolIsAvailable && !kHwAsanEnabled) {
void* stack_low_addr = stack_low_addr_;
void* stack_high_addr = stack_high_addr_;
if (!HasAddress(old_ref)) {
@@ -279,15 +280,21 @@ inline bool MarkCompact::VerifyRootSingleUpdate(void* root,
stack_low_addr = self->GetStackEnd();
stack_high_addr = reinterpret_cast<char*>(stack_low_addr) + self->GetStackSize();
}
- if (root < stack_low_addr || root > stack_high_addr) {
+ if (std::less<void*>{}(root, stack_low_addr) || std::greater<void*>{}(root, stack_high_addr)) {
bool inserted;
{
MutexLock mu(self, lock_);
inserted = updated_roots_->insert(root).second;
}
- DCHECK(inserted) << "root=" << root << " old_ref=" << old_ref
- << " stack_low_addr=" << stack_low_addr
- << " stack_high_addr=" << stack_high_addr;
+ if (!inserted) {
+ std::ostringstream oss;
+ heap_->DumpSpaces(oss);
+ MemMap::DumpMaps(oss, /* terse= */ true);
+ CHECK(inserted) << "root=" << root << " old_ref=" << old_ref
+ << " stack_low_addr=" << stack_low_addr
+ << " stack_high_addr=" << stack_high_addr << " maps\n"
+ << oss.str();
+ }
}
DCHECK(reinterpret_cast<uint8_t*>(old_ref) >= black_allocations_begin_ ||
live_words_bitmap_->Test(old_ref))