1#ifndef LLVM_PROFILEDATA_MEMPROFDATA_INC 2#define LLVM_PROFILEDATA_MEMPROFDATA_INC 3/*===-- MemProfData.inc - MemProf profiling runtime structures -*- C++ -*-=== *\ 4|* 5|* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6|* See https://llvm.org/LICENSE.txt for license information. 7|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8|* 9\*===----------------------------------------------------------------------===*/ 10/* 11 * This is the main file that defines all the data structure, signature, 12 * constant literals that are shared across profiling runtime library, 13 * and host tools (reader/writer). 14 * 15 * This file has two identical copies. The primary copy lives in LLVM and 16 * the other one sits in compiler-rt/include/profile directory. To make changes 17 * in this file, first modify the primary copy and copy it over to compiler-rt. 18 * Testing of any change in this file can start only after the two copies are 19 * synced up. 20 * 21\*===----------------------------------------------------------------------===*/ 22 23#ifdef _MSC_VER 24#define PACKED(...) __pragma(pack(push,1)) __VA_ARGS__ __pragma(pack(pop)) 25#else 26#define PACKED(...) __VA_ARGS__ __attribute__((__packed__)) 27#endif 28 29// A 64-bit magic number to uniquely identify the raw binary memprof profile file. 30#define MEMPROF_RAW_MAGIC_64 \ 31 ((uint64_t)255 << 56 | (uint64_t)'m' << 48 | (uint64_t)'p' << 40 | (uint64_t)'r' << 32 | \ 32 (uint64_t)'o' << 24 | (uint64_t)'f' << 16 | (uint64_t)'r' << 8 | (uint64_t)129) 33 34// The version number of the raw binary format. 35#define MEMPROF_RAW_VERSION 1ULL 36 37namespace llvm { 38namespace memprof { 39// A struct describing the header used for the raw binary memprof profile format. 40PACKED(struct Header { 41 uint64_t Magic; 42 uint64_t Version; 43 uint64_t TotalSize; 44 uint64_t SegmentOffset; 45 uint64_t MIBOffset; 46 uint64_t StackOffset; 47}); 48 49 50// A struct describing the information necessary to describe a /proc/maps 51// segment entry for a particular binary/library identified by its build id. 52PACKED(struct SegmentEntry { 53 uint64_t Start; 54 uint64_t End; 55 uint64_t Offset; 56 // This field is unused until sanitizer procmaps support for build ids for 57 // Linux-Elf is implemented. 58 uint8_t BuildId[32] = {0}; 59 60 SegmentEntry(uint64_t S, uint64_t E, uint64_t O) : 61 Start(S), End(E), Offset(O) {} 62 63 SegmentEntry(const SegmentEntry& S) { 64 Start = S.Start; 65 End = S.End; 66 Offset = S.Offset; 67 } 68 69 SegmentEntry& operator=(const SegmentEntry& S) { 70 Start = S.Start; 71 End = S.End; 72 Offset = S.Offset; 73 return *this; 74 } 75 76 bool operator==(const SegmentEntry& S) const { 77 return Start == S.Start && 78 End == S.End && 79 Offset == S.Offset; 80 } 81}); 82 83// A struct representing the heap allocation characteristics of a particular 84// runtime context. This struct is shared between the compiler-rt runtime and 85// the raw profile reader. The indexed format uses a separate, self-describing 86// backwards compatible format. 87PACKED(struct MemInfoBlock { 88 uint32_t alloc_count; 89 uint64_t total_access_count, min_access_count, max_access_count; 90 uint64_t total_size; 91 uint32_t min_size, max_size; 92 uint32_t alloc_timestamp, dealloc_timestamp; 93 uint64_t total_lifetime; 94 uint32_t min_lifetime, max_lifetime; 95 uint32_t alloc_cpu_id, dealloc_cpu_id; 96 uint32_t num_migrated_cpu; 97 98 // Only compared to prior deallocated object currently. 99 uint32_t num_lifetime_overlaps; 100 uint32_t num_same_alloc_cpu; 101 uint32_t num_same_dealloc_cpu; 102 103 uint64_t data_type_id; // TODO: hash of type name 104 105 MemInfoBlock() : alloc_count(0) {} 106 107 MemInfoBlock(uint32_t size, uint64_t access_count, uint32_t alloc_timestamp, 108 uint32_t dealloc_timestamp, uint32_t alloc_cpu, uint32_t dealloc_cpu) 109 : alloc_count(1), total_access_count(access_count), 110 min_access_count(access_count), max_access_count(access_count), 111 total_size(size), min_size(size), max_size(size), 112 alloc_timestamp(alloc_timestamp), dealloc_timestamp(dealloc_timestamp), 113 total_lifetime(dealloc_timestamp - alloc_timestamp), 114 min_lifetime(total_lifetime), max_lifetime(total_lifetime), 115 alloc_cpu_id(alloc_cpu), dealloc_cpu_id(dealloc_cpu), 116 num_lifetime_overlaps(0), num_same_alloc_cpu(0), 117 num_same_dealloc_cpu(0) { 118 num_migrated_cpu = alloc_cpu_id != dealloc_cpu_id; 119 } 120 121 void Merge(const MemInfoBlock &newMIB) { 122 alloc_count += newMIB.alloc_count; 123 124 total_access_count += newMIB.total_access_count; 125 min_access_count = newMIB.min_access_count < min_access_count ? newMIB.min_access_count : min_access_count; 126 max_access_count = newMIB.max_access_count < max_access_count ? newMIB.max_access_count : max_access_count; 127 128 total_size += newMIB.total_size; 129 min_size = newMIB.min_size < min_size ? newMIB.min_size : min_size; 130 max_size = newMIB.max_size < max_size ? newMIB.max_size : max_size; 131 132 total_lifetime += newMIB.total_lifetime; 133 min_lifetime = newMIB.min_lifetime < min_lifetime ? newMIB.min_lifetime : min_lifetime; 134 max_lifetime = newMIB.max_lifetime > max_lifetime ? newMIB.max_lifetime : max_lifetime; 135 136 // We know newMIB was deallocated later, so just need to check if it was 137 // allocated before last one deallocated. 138 num_lifetime_overlaps += newMIB.alloc_timestamp < dealloc_timestamp; 139 alloc_timestamp = newMIB.alloc_timestamp; 140 dealloc_timestamp = newMIB.dealloc_timestamp; 141 142 num_same_alloc_cpu += alloc_cpu_id == newMIB.alloc_cpu_id; 143 num_same_dealloc_cpu += dealloc_cpu_id == newMIB.dealloc_cpu_id; 144 alloc_cpu_id = newMIB.alloc_cpu_id; 145 dealloc_cpu_id = newMIB.dealloc_cpu_id; 146 } 147}); 148 149} // namespace memprof 150} // namespace llvm 151 152#endif 153