brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 3396fc2 Raw
125 lines · cpp
1//===-- asan_memory_profile.cpp ----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of AddressSanitizer, an address sanity checker.10//11// This file implements __sanitizer_print_memory_profile.12//===----------------------------------------------------------------------===//13 14#include "asan/asan_allocator.h"15#include "lsan/lsan_common.h"16#include "sanitizer_common/sanitizer_common.h"17#include "sanitizer_common/sanitizer_stackdepot.h"18#include "sanitizer_common/sanitizer_stacktrace.h"19 20#if CAN_SANITIZE_LEAKS21 22namespace __asan {23 24struct AllocationSite {25  u32 id;26  uptr total_size;27  uptr count;28};29 30class HeapProfile {31 public:32  HeapProfile() { allocations_.reserve(1024); }33 34  void ProcessChunk(const AsanChunkView &cv) {35    if (cv.IsAllocated()) {36      total_allocated_user_size_ += cv.UsedSize();37      total_allocated_count_++;38      u32 id = cv.GetAllocStackId();39      if (id)40        Insert(id, cv.UsedSize());41    } else if (cv.IsQuarantined()) {42      total_quarantined_user_size_ += cv.UsedSize();43      total_quarantined_count_++;44    } else {45      total_other_count_++;46    }47  }48 49  void Print(uptr top_percent, uptr max_number_of_contexts) {50    Sort(allocations_.data(), allocations_.size(),51         [](const AllocationSite &a, const AllocationSite &b) {52           return a.total_size > b.total_size;53         });54    CHECK(total_allocated_user_size_);55    uptr total_shown = 0;56    Printf("Live Heap Allocations: %zd bytes in %zd chunks; quarantined: "57           "%zd bytes in %zd chunks; %zd other chunks; total chunks: %zd; "58           "showing top %zd%% (at most %zd unique contexts)\n",59           total_allocated_user_size_, total_allocated_count_,60           total_quarantined_user_size_, total_quarantined_count_,61           total_other_count_, total_allocated_count_ +62           total_quarantined_count_ + total_other_count_, top_percent,63           max_number_of_contexts);64    for (uptr i = 0; i < Min(allocations_.size(), max_number_of_contexts);65         i++) {66      auto &a = allocations_[i];67      Printf("%zd byte(s) (%zd%%) in %zd allocation(s)\n", a.total_size,68             a.total_size * 100 / total_allocated_user_size_, a.count);69      StackDepotGet(a.id).Print();70      total_shown += a.total_size;71      if (total_shown * 100 / total_allocated_user_size_ > top_percent)72        break;73    }74  }75 76 private:77  uptr total_allocated_user_size_ = 0;78  uptr total_allocated_count_ = 0;79  uptr total_quarantined_user_size_ = 0;80  uptr total_quarantined_count_ = 0;81  uptr total_other_count_ = 0;82  InternalMmapVector<AllocationSite> allocations_;83 84  void Insert(u32 id, uptr size) {85    // Linear lookup will be good enough for most cases (although not all).86    for (uptr i = 0; i < allocations_.size(); i++) {87      if (allocations_[i].id == id) {88        allocations_[i].total_size += size;89        allocations_[i].count++;90        return;91      }92    }93    allocations_.push_back({id, size, 1});94  }95};96 97static void ChunkCallback(uptr chunk, void *arg) {98  reinterpret_cast<HeapProfile*>(arg)->ProcessChunk(99      FindHeapChunkByAllocBeg(chunk));100}101 102static void MemoryProfileCB(uptr top_percent, uptr max_number_of_contexts) {103  HeapProfile hp;104  __lsan::LockAllocator();105  __lsan::ForEachChunk(ChunkCallback, &hp);106  __lsan::UnlockAllocator();107  hp.Print(top_percent, max_number_of_contexts);108 109  if (Verbosity())110    __asan_print_accumulated_stats();111}112}  // namespace __asan113 114#endif  // CAN_SANITIZE_LEAKS115 116extern "C" {117SANITIZER_INTERFACE_ATTRIBUTE118void __sanitizer_print_memory_profile(uptr top_percent,119                                      uptr max_number_of_contexts) {120#if CAN_SANITIZE_LEAKS121  __asan::MemoryProfileCB(top_percent, max_number_of_contexts);122#endif  // CAN_SANITIZE_LEAKS123}124}  // extern "C"125