struct Metadata {
u64 state : 2;
- u32 requested_size; // Current use cases of hwasan do not expect sizes > 4G.
- u32 alloc_context_id;
- u32 free_context_id;
+ u64 requested_size : 31; // sizes are < 4G.
+ u32 alloc_context_id : 31;
};
bool HwasanChunkView::IsValid() const {
u32 HwasanChunkView::GetAllocStackId() const {
return metadata_->alloc_context_id;
}
-u32 HwasanChunkView::GetFreeStackId() const {
- return metadata_->free_context_id;
-}
struct HwasanMapUnmapCallback {
void OnMap(uptr p, uptr size) const {}
meta->state = CHUNK_FREE;
meta->requested_size = 0;
u32 free_context_id = StackDepotPut(*stack);
- meta->free_context_id = free_context_id;
+ u32 alloc_context_id = meta->alloc_context_id;
// This memory will not be reused by anyone else, so we are free to keep it
// poisoned.
Thread *t = GetCurrentThread();
AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
allocator.Deallocate(cache, untagged_ptr);
if (auto *ha = t->heap_allocations())
- ha->push({reinterpret_cast<uptr>(tagged_ptr), free_context_id,
- static_cast<u32>(size)});
+ ha->push({reinterpret_cast<uptr>(tagged_ptr), alloc_context_id,
+ free_context_id, static_cast<u32>(size)});
} else {
SpinMutexLock l(&fallback_mutex);
AllocatorCache *cache = &fallback_allocator_cache;
const char *Allocation() const { return Magenta(); }
const char *Origin() const { return Magenta(); }
const char *Name() const { return Green(); }
-};
-
-struct HeapAddressDescription {
- uptr addr;
- u32 alloc_stack_id;
- u32 free_stack_id;
-
- void Print() const {
- Decorator d;
- if (free_stack_id) {
- Printf("%sfreed here:%s\n", d.Allocation(), d.Default());
- GetStackTraceFromId(free_stack_id).Print();
- Printf("%spreviously allocated here:%s\n", d.Allocation(), d.Default());
- } else {
- Printf("%sallocated here:%s\n", d.Allocation(), d.Default());
- }
- GetStackTraceFromId(alloc_stack_id).Print();
- }
+ const char *Location() { return Green(); }
};
bool FindHeapAllocation(HeapAllocationsRingBuffer *rb,
return false;
}
-bool GetHeapAddressInformation(uptr addr, uptr access_size,
- HeapAddressDescription *description) {
- HwasanChunkView chunk = FindHeapChunkByAddress(addr);
- if (!chunk.IsValid())
- return false;
- description->addr = addr;
- description->alloc_stack_id = chunk.GetAllocStackId();
- description->free_stack_id = chunk.GetFreeStackId();
- return true;
-}
+void PrintAddressDescription(uptr tagged_addr, uptr access_size) {
+ int num_descriptions_printed = 0;
+ uptr untagged_addr = UntagAddr(tagged_addr);
+ Thread::VisitAllLiveThreads([&](Thread *t) {
+ Decorator d;
+ HeapAllocationRecord har;
+ if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har)) {
+ Printf("%s", d.Location());
+ Printf("%p is located %zd bytes inside of %zd-byte region [%p,%p)\n",
+ untagged_addr, untagged_addr - UntagAddr(har.tagged_addr),
+ har.requested_size, UntagAddr(har.tagged_addr),
+ UntagAddr(har.tagged_addr) + har.requested_size);
+ Printf("%s", d.Allocation());
+ Printf("freed by thread %p here:\n", t);
+ Printf("%s", d.Default());
+ GetStackTraceFromId(har.free_context_id).Print();
+
+ Printf("%s", d.Allocation());
+ Printf("previously allocated here:\n", t);
+ Printf("%s", d.Default());
+ GetStackTraceFromId(har.alloc_context_id).Print();
+
+ num_descriptions_printed++;
+ }
+ });
-void PrintAddressDescription(uptr addr, uptr access_size) {
- HeapAddressDescription heap_description;
- if (GetHeapAddressInformation(addr, access_size, &heap_description)) {
- heap_description.Print();
- return;
- }
- // We exhausted our possibilities. Bail out.
- Printf("HWAddressSanitizer can not describe address in more detail.\n");
+ if (!num_descriptions_printed)
+ // We exhausted our possibilities. Bail out.
+ Printf("HWAddressSanitizer can not describe address in more detail.\n");
}
void ReportInvalidAccess(StackTrace *stack, u32 origin) {
stack->Print();
- PrintAddressDescription(untagged_addr, 0);
+ PrintAddressDescription(tagged_addr, 0);
PrintTagsAroundAddr(tag_ptr);
stack->Print();
- PrintAddressDescription(untagged_addr, access_size);
-
- // Temporary functionality; to be folded into PrintAddressDescription.
- // TODOs:
- // * implement ThreadRegistry
- // * check all threads, not just the current one.
- // * remove reduntant fields from the allocator metadata
- // * use the allocations found in the ring buffer for the main report.
- HeapAllocationRecord har;
- Thread *t = GetCurrentThread();
- if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har))
- Printf("Address found in the ring buffer: %p %u %u\n", har.tagged_addr,
- har.free_context_id, har.requested_size);
-
+ PrintAddressDescription(tagged_addr, access_size);
PrintTagsAroundAddr(tag_ptr);