1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef SMAPS_STATS_H 17 #define SMAPS_STATS_H 18 19 #include <array> 20 #include <cinttypes> 21 #include <cstdio> 22 #include <fstream> 23 #include <inttypes.h> 24 #include <iostream> 25 #include <memory> 26 #include <string> 27 #include <sys/mman.h> 28 #include "logging.h" 29 30 struct MemUsageInfo { 31 uint64_t vss; 32 uint64_t rss; 33 uint64_t pss; 34 uint64_t uss; 35 36 uint64_t swap; 37 uint64_t swapPss; 38 39 uint64_t privateClean; 40 uint64_t privateDirty; 41 uint64_t sharedClean; 42 uint64_t sharedDirty; 43 }; 44 45 class StatsInfo { 46 public: 47 int pss_; 48 int swappablePss_; 49 int rss_; 50 int privateDirty_; 51 int sharedDirty_; 52 int privateClean_; 53 int sharedClean_; 54 int swappedOut_; 55 int swappedOutPss_; 56 StatsInfo()57 StatsInfo() 58 : pss_(0), 59 swappablePss_(0), 60 rss_(0), 61 privateDirty_(0), 62 sharedDirty_(0), 63 privateClean_(0), 64 sharedClean_(0), 65 swappedOut_(0), 66 swappedOutPss_(0) 67 { 68 } 69 StatsInfo(uint64_t swapablePss,const MemUsageInfo & usage)70 StatsInfo(uint64_t swapablePss, const MemUsageInfo& usage) 71 : pss_(usage.pss), 72 swappablePss_(swapablePss), 73 rss_(usage.rss), 74 privateDirty_(usage.privateDirty), 75 sharedDirty_(usage.sharedDirty), 76 privateClean_(usage.privateClean), 77 sharedClean_(usage.sharedClean), 78 swappedOut_(usage.swap), 79 swappedOutPss_(usage.swapPss) 80 { 81 } ~StatsInfo()82 ~StatsInfo() {} 83 84 void operator+=(const StatsInfo &S) 85 { 86 pss_ += S.pss_; 87 swappablePss_ += S.swappablePss_; 88 rss_ += S.rss_; 89 privateDirty_ += S.privateDirty_; 90 sharedDirty_ += S.sharedDirty_; 91 privateClean_ += S.privateClean_; 92 sharedClean_ += S.sharedClean_; 93 swappedOut_ += S.swappedOut_; 94 swappedOutPss_ += S.swappedOutPss_; 95 } 96 }; 97 98 enum NumType { 99 FIFTH_FIELD = 5, 100 HEX_BASE = 16, 101 DEC_BASE = 10, 102 }; 103 104 struct MapPiecesInfo { 105 uint64_t startAddr; 106 uint64_t endAddr; 107 108 std::string name; 109 }; 110 111 enum VmemifoType { 112 VMHEAP_NULL = -2, 113 VMHEAP_NEEDFIX = -1, 114 VMHEAP_UNKNOWN, 115 VMHEAP_SENSITIVE_VM, 116 VMHEAP_NATIVE, 117 118 VMHEAP_SENSITIVE_VM_OTHER, 119 VMHEAP_STACK, 120 VMHEAP_CURSOR, 121 VMHEAP_ASHMEM, 122 VMHEAP_GL_DEV, 123 VMHEAP_UNKNOWN_DEV, 124 VMHEAP_SO, 125 VMHEAP_JAR, 126 VMHEAP_TTF, 127 VMHEAP_SENSITIVE_JVBIN, 128 VMHEAP_OAT, 129 VMHEAP_HRT, 130 VMHEAP_UNKNOWN_MAP, 131 VMHEAP_GRAPHICS, 132 VMHEAP_GL, 133 VMHEAP_OTHER_MEMTRACK, 134 135 // extra sections (heap). 136 VMHEAP_SENSITIVE_VM_NORMAL, 137 VMHEAP_SENSITIVE_VM_LARGE, 138 VMHEAP_SENSITIVE_VM_ZYGOTE, 139 VMHEAP_SENSITIVE_VM_NON_MOVING, 140 141 // other extra sections. 142 VMHEAP_SENSITIVE_VM_OTHER_LINEARALLOC, 143 VMHEAP_SENSITIVE_VM_OTHER_ACCOUNTING, 144 VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE, 145 VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE, 146 VMHEAP_SENSITIVE_VM_OTHER_COMPILER_METADATA, 147 VMHEAP_SENSITIVE_VM_OTHER_INDIRECT_REFERENCE_TABLE, 148 149 VMHEAP_SENSITIVE_JVBIN_BOOT_VDEX, 150 VMHEAP_SENSITIVE_JVBIN_APP_SENSITIVE_JVBIN, 151 VMHEAP_SENSITIVE_JVBIN_APP_VDEX, 152 153 // App hrt, boot hrt. 154 VMHEAP_HRT_APP, 155 VMHEAP_HRT_BOOT, 156 157 VMHEAP_NUM_HEAP, 158 VMHEAP_NUM_EXCLUSIVE_HEAP = VMHEAP_OTHER_MEMTRACK + 1, 159 VMHEAP_NUM_CORE_HEAP = VMHEAP_NATIVE + 1 160 }; 161 162 enum OpsType { 163 OPS_START = 1, 164 OPS_END, 165 }; 166 167 struct VmeminfoAreaMapping { 168 int ops; 169 const char* heapstr; 170 int heapid[2]; 171 }; 172 173 constexpr VmeminfoAreaMapping g_vmaMemHeap[] = { 174 {OpsType::OPS_START, "[heap]", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 175 {OpsType::OPS_START, "[stack", {VmemifoType::VMHEAP_STACK, VmemifoType::VMHEAP_NULL}}, 176 }; 177 178 // [anon: 179 constexpr VmeminfoAreaMapping g_vmaMemAnon[] = { 180 {OpsType::OPS_START, "[anon:libc_malloc]", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 181 {OpsType::OPS_START, "[anon:native_heap:", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 182 {OpsType::OPS_START, "[anon:scudo:", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 183 {OpsType::OPS_START, "[anon:GWP-ASan", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 184 {OpsType::OPS_START, "[anon:stack_and_tls:", {VmemifoType::VMHEAP_STACK, VmemifoType::VMHEAP_NULL}}, 185 {OpsType::OPS_START, 186 "[anon:sensitive_vm-LinearAlloc", 187 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_LINEARALLOC}}, 188 {OpsType::OPS_START, 189 "[anon:sensitive_vm-alloc space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}}, 190 {OpsType::OPS_START, 191 "[anon:sensitive_vm-main space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}}, 192 {OpsType::OPS_START, 193 "[anon:sensitive_vm-large object space", 194 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}}, 195 {OpsType::OPS_START, 196 "[anon:sensitive_vm-free list large object space", 197 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}}, 198 {OpsType::OPS_START, 199 "[anon:sensitive_vm-non moving space", 200 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NON_MOVING}}, 201 {OpsType::OPS_START, 202 "[anon:sensitive_vm-zygote space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_ZYGOTE}}, 203 {OpsType::OPS_START, 204 "[anon:sensitive_vm-indirect ref", 205 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_INDIRECT_REFERENCE_TABLE}}, 206 {OpsType::OPS_START, 207 "[anon:sensitive_vm-jit-code-cache", 208 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 209 {OpsType::OPS_START, 210 "[anon:sensitive_vm-data-code-cache", 211 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 212 {OpsType::OPS_START, 213 "[anon:sensitive_vm-CompilerMetadata", 214 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_COMPILER_METADATA}}, 215 {OpsType::OPS_START, 216 "[anon:sensitive_vm-", 217 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ACCOUNTING}}, 218 {OpsType::OPS_START, "[anon:", {VmemifoType::VMHEAP_UNKNOWN, VmemifoType::VMHEAP_NULL}}, 219 }; 220 221 constexpr VmeminfoAreaMapping g_vmaMemFd[] = { 222 {OpsType::OPS_START, 223 "/memfd:jit-cache", 224 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 225 {OpsType::OPS_START, 226 "/memfd:jit-zygote-cache", 227 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}}, 228 }; 229 // dev 230 constexpr VmeminfoAreaMapping g_vmaMemDev[] = { 231 {OpsType::OPS_START, "/dev/kgsl-3d0", {VmemifoType::VMHEAP_GL_DEV, VmemifoType::VMHEAP_NULL}}, 232 {OpsType::OPS_START, "/dev/ashmem/CursorWindow", {VmemifoType::VMHEAP_CURSOR, VmemifoType::VMHEAP_NULL}}, 233 {OpsType::OPS_START, 234 "/dev/ashmem/jit-zygote-cache", 235 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}}, 236 {OpsType::OPS_START, "/dev/ashmem", {VmemifoType::VMHEAP_ASHMEM, VmemifoType::VMHEAP_NULL}}, 237 {OpsType::OPS_START, "/dev/", {VmemifoType::VMHEAP_UNKNOWN_DEV, VmemifoType::VMHEAP_NULL}}, 238 }; 239 240 constexpr VmeminfoAreaMapping g_vmaMemSuffix[] = { 241 {OpsType::OPS_END, ".so", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}}, 242 {OpsType::OPS_END, ".so.1", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}}, 243 {OpsType::OPS_END, ".jar", {VmemifoType::VMHEAP_JAR, VmemifoType::VMHEAP_NULL}}, 244 {OpsType::OPS_END, ".ttf", {VmemifoType::VMHEAP_TTF, VmemifoType::VMHEAP_NULL}}, 245 {OpsType::OPS_END, ".oat", {VmemifoType::VMHEAP_OAT, VmemifoType::VMHEAP_NULL}}, 246 247 {OpsType::OPS_END, 248 ".odex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_SENSITIVE_JVBIN_APP_SENSITIVE_JVBIN}}, 249 250 {OpsType::OPS_END, ".vdex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_NEEDFIX}}, 251 {OpsType::OPS_END, ".hrt", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}}, 252 {OpsType::OPS_END, ".hrt]", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}}, 253 }; 254 255 class SmapsStats { 256 public: SmapsStats()257 SmapsStats() {} SmapsStats(const std::string path)258 SmapsStats(const std::string path) : testpath_(path){}; ~SmapsStats()259 ~SmapsStats() {} 260 bool ParseMaps(int pid); 261 int GetProcessJavaHeap(); 262 int GetProcessNativeHeap(); 263 int GetProcessCode(); 264 int GetProcessStack(); 265 int GetProcessGraphics(); 266 int GetProcessPrivateOther(); 267 int GetProcessSystem(); 268 269 private: 270 std::array<StatsInfo, VMHEAP_NUM_HEAP> stats_; 271 bool lastline_ = false; 272 std::string testpath_; 273 274 int GetTotalPrivateClean(); 275 int GetTotalPrivateDirty(); 276 int GetPrivate(int type); 277 int GetTotalPss(); 278 int GetTotalSwappedOutPss(); 279 void ReviseStatsData(); 280 281 bool ReadVmemareasFile(const std::string& path); 282 bool ParseMapHead(std::string& line, MapPiecesInfo& head); 283 bool SetMapAddrInfo(std::string& line, MapPiecesInfo& head); 284 bool GetMemUsageField(std::string& line, MemUsageInfo& memusage); 285 void CollectVmemAreasData(const MapPiecesInfo& mempic, 286 const MemUsageInfo& memusage, 287 uint64_t& prevEnd, 288 int& prevHeap); 289 bool GetVmaIndex(std::string name, uint32_t namesz, int32_t heapIndex[2], bool& swappable); 290 uint64_t GetSwapablepssValue(const MemUsageInfo& memusage, bool swappable); 291 void SetVmemAreasData(int index, uint64_t swapablePss, const MemUsageInfo& usage); 292 void HeapIndexFix(std::string name, const char* key, int32_t heapIndex[2]); 293 bool GetVMAStuId(int ops, 294 std::string name, 295 const VmeminfoAreaMapping vma[], 296 int count, 297 int32_t heapIndex[2], 298 bool& swappable); 299 }; 300 301 #endif