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:scudo:", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 182 {OpsType::OPS_START, "[anon:GWP-ASan", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}}, 183 {OpsType::OPS_START, "[anon:stack_and_tls:", {VmemifoType::VMHEAP_STACK, VmemifoType::VMHEAP_NULL}}, 184 {OpsType::OPS_START, 185 "[anon:sensitive_vm-LinearAlloc", 186 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_LINEARALLOC}}, 187 {OpsType::OPS_START, 188 "[anon:sensitive_vm-alloc space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}}, 189 {OpsType::OPS_START, 190 "[anon:sensitive_vm-main space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}}, 191 {OpsType::OPS_START, 192 "[anon:sensitive_vm-large object space", 193 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}}, 194 {OpsType::OPS_START, 195 "[anon:sensitive_vm-free list large object space", 196 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}}, 197 {OpsType::OPS_START, 198 "[anon:sensitive_vm-non moving space", 199 {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NON_MOVING}}, 200 {OpsType::OPS_START, 201 "[anon:sensitive_vm-zygote space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_ZYGOTE}}, 202 {OpsType::OPS_START, 203 "[anon:sensitive_vm-indirect ref", 204 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_INDIRECT_REFERENCE_TABLE}}, 205 {OpsType::OPS_START, 206 "[anon:sensitive_vm-jit-code-cache", 207 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 208 {OpsType::OPS_START, 209 "[anon:sensitive_vm-data-code-cache", 210 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 211 {OpsType::OPS_START, 212 "[anon:sensitive_vm-CompilerMetadata", 213 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_COMPILER_METADATA}}, 214 {OpsType::OPS_START, 215 "[anon:sensitive_vm-", 216 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ACCOUNTING}}, 217 {OpsType::OPS_START, "[anon:", {VmemifoType::VMHEAP_UNKNOWN, VmemifoType::VMHEAP_NULL}}, 218 }; 219 220 constexpr VmeminfoAreaMapping g_vmaMemFd[] = { 221 {OpsType::OPS_START, 222 "/memfd:jit-cache", 223 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}}, 224 {OpsType::OPS_START, 225 "/memfd:jit-zygote-cache", 226 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}}, 227 }; 228 // dev 229 constexpr VmeminfoAreaMapping g_vmaMemDev[] = { 230 {OpsType::OPS_START, "/dev/kgsl-3d0", {VmemifoType::VMHEAP_GL_DEV, VmemifoType::VMHEAP_NULL}}, 231 {OpsType::OPS_START, "/dev/ashmem/CursorWindow", {VmemifoType::VMHEAP_CURSOR, VmemifoType::VMHEAP_NULL}}, 232 {OpsType::OPS_START, 233 "/dev/ashmem/jit-zygote-cache", 234 {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}}, 235 {OpsType::OPS_START, "/dev/ashmem", {VmemifoType::VMHEAP_ASHMEM, VmemifoType::VMHEAP_NULL}}, 236 {OpsType::OPS_START, "/dev/", {VmemifoType::VMHEAP_UNKNOWN_DEV, VmemifoType::VMHEAP_NULL}}, 237 }; 238 239 constexpr VmeminfoAreaMapping g_vmaMemSuffix[] = { 240 {OpsType::OPS_END, ".so", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}}, 241 {OpsType::OPS_END, ".so.1", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}}, 242 {OpsType::OPS_END, ".jar", {VmemifoType::VMHEAP_JAR, VmemifoType::VMHEAP_NULL}}, 243 {OpsType::OPS_END, ".ttf", {VmemifoType::VMHEAP_TTF, VmemifoType::VMHEAP_NULL}}, 244 {OpsType::OPS_END, ".oat", {VmemifoType::VMHEAP_OAT, VmemifoType::VMHEAP_NULL}}, 245 246 {OpsType::OPS_END, 247 ".odex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_SENSITIVE_JVBIN_APP_SENSITIVE_JVBIN}}, 248 249 {OpsType::OPS_END, ".vdex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_NEEDFIX}}, 250 {OpsType::OPS_END, ".hrt", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}}, 251 {OpsType::OPS_END, ".hrt]", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}}, 252 }; 253 254 class SmapsStats { 255 public: SmapsStats()256 SmapsStats() {} SmapsStats(const std::string path)257 SmapsStats(const std::string path) : testpath_(path){}; ~SmapsStats()258 ~SmapsStats() {} 259 bool ParseMaps(int pid); 260 int GetProcessJavaHeap(); 261 int GetProcessNativeHeap(); 262 int GetProcessCode(); 263 int GetProcessStack(); 264 int GetProcessGraphics(); 265 int GetProcessPrivateOther(); 266 int GetProcessSystem(); 267 268 private: 269 std::array<StatsInfo, VMHEAP_NUM_HEAP> stats_; 270 bool lastline_ = false; 271 std::string testpath_; 272 273 int GetTotalPrivateClean(); 274 int GetTotalPrivateDirty(); 275 int GetPrivate(int type); 276 int GetTotalPss(); 277 int GetTotalSwappedOutPss(); 278 void ReviseStatsData(); 279 280 bool ReadVmemareasFile(const std::string& path); 281 bool ParseMapHead(std::string& line, MapPiecesInfo& head); 282 bool SetMapAddrInfo(std::string& line, MapPiecesInfo& head); 283 bool GetMemUsageField(std::string& line, MemUsageInfo& memusage); 284 void CollectVmemAreasData(const MapPiecesInfo& mempic, 285 const MemUsageInfo& memusage, 286 uint64_t& prevEnd, 287 int& prevHeap); 288 bool GetVmaIndex(std::string name, uint32_t namesz, int32_t heapIndex[2], bool& swappable); 289 uint64_t GetSwapablepssValue(const MemUsageInfo& memusage, bool swappable); 290 void SetVmemAreasData(int index, uint64_t swapablePss, const MemUsageInfo& usage); 291 void HeapIndexFix(std::string name, const char* key, int32_t heapIndex[2]); 292 bool GetVMAStuId(int ops, 293 std::string name, 294 const VmeminfoAreaMapping vma[], 295 int count, 296 int32_t heapIndex[2], 297 bool& swappable); 298 }; 299 300 #endif