• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
26 #include <memory>
27 #include <string>
28 #include <sys/mman.h>
29 
30 #include "logging.h"
31 #include "memory_plugin_result.pb.h"
32 
33 struct MemUsageInfo {
34     uint64_t vss;
35     uint64_t rss;
36     uint64_t pss;
37     uint64_t uss;
38 
39     uint64_t swap;
40     uint64_t swapPss;
41 
42     uint64_t privateClean;
43     uint64_t privateDirty;
44     uint64_t sharedClean;
45     uint64_t sharedDirty;
46 };
47 
48 class StatsInfo {
49 public:
50     int pss_;
51     int swappablePss_;
52     int rss_;
53     int privateDirty_;
54     int sharedDirty_;
55     int privateClean_;
56     int sharedClean_;
57     int swappedOut_;
58     int swappedOutPss_;
59 
StatsInfo()60     StatsInfo()
61         : pss_(0),
62         swappablePss_(0),
63         rss_(0),
64         privateDirty_(0),
65         sharedDirty_(0),
66         privateClean_(0),
67         sharedClean_(0),
68         swappedOut_(0),
69         swappedOutPss_(0)
70     {
71     }
72 
StatsInfo(uint64_t swapablePss,const MemUsageInfo & usage)73     StatsInfo(uint64_t swapablePss, const MemUsageInfo& usage)
74         : pss_(usage.pss),
75         swappablePss_(swapablePss),
76         rss_(usage.rss),
77         privateDirty_(usage.privateDirty),
78         sharedDirty_(usage.sharedDirty),
79         privateClean_(usage.privateClean),
80         sharedClean_(usage.sharedClean),
81         swappedOut_(usage.swap),
82         swappedOutPss_(usage.swapPss)
83     {
84     }
~StatsInfo()85     ~StatsInfo() {}
86 
87     void operator+=(const StatsInfo &S)
88     {
89         pss_ += S.pss_;
90         swappablePss_ += S.swappablePss_;
91         rss_ += S.rss_;
92         privateDirty_ += S.privateDirty_;
93         sharedDirty_ += S.sharedDirty_;
94         privateClean_ += S.privateClean_;
95         sharedClean_ += S.sharedClean_;
96         swappedOut_ += S.swappedOut_;
97         swappedOutPss_ += S.swappedOutPss_;
98     }
99 };
100 
101 enum NumType {
102     FIFTH_FIELD = 5,
103     HEX_BASE = 16,
104     DEC_BASE = 10,
105 };
106 
107 struct MapPiecesInfo {
108     uint64_t startAddr;
109     uint64_t endAddr;
110 
111     std::string name;
112 };
113 
114 struct SmapsHeadInfo {
115     std::string startAddrStr;
116     std::string endAddrStr;
117     std::string permission;
118     std::string path;
119     int64_t iNode = -1;
120 };
121 
122 enum VmemifoType {
123     VMHEAP_NULL = -2,
124     VMHEAP_NEEDFIX = -1,
125     VMHEAP_UNKNOWN,
126     VMHEAP_SENSITIVE_VM,
127     VMHEAP_NATIVE,
128 
129     VMHEAP_SENSITIVE_VM_OTHER,
130     VMHEAP_STACK,
131     VMHEAP_CURSOR,
132     VMHEAP_ASHMEM,
133     VMHEAP_GL_DEV,
134     VMHEAP_UNKNOWN_DEV,
135     VMHEAP_SO,
136     VMHEAP_JAR,
137     VMHEAP_TTF,
138     VMHEAP_SENSITIVE_JVBIN,
139     VMHEAP_OAT,
140     VMHEAP_HRT,
141     VMHEAP_UNKNOWN_MAP,
142     VMHEAP_GRAPHICS,
143     VMHEAP_GL,
144     VMHEAP_OTHER_MEMTRACK,
145 
146     // extra sections (heap).
147     VMHEAP_SENSITIVE_VM_NORMAL,
148     VMHEAP_SENSITIVE_VM_LARGE,
149     VMHEAP_SENSITIVE_VM_ZYGOTE,
150     VMHEAP_SENSITIVE_VM_NON_MOVING,
151 
152     // other extra sections.
153     VMHEAP_SENSITIVE_VM_OTHER_LINEARALLOC,
154     VMHEAP_SENSITIVE_VM_OTHER_ACCOUNTING,
155     VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE,
156     VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE,
157     VMHEAP_SENSITIVE_VM_OTHER_COMPILER_METADATA,
158     VMHEAP_SENSITIVE_VM_OTHER_INDIRECT_REFERENCE_TABLE,
159 
160     VMHEAP_SENSITIVE_JVBIN_BOOT_VDEX,
161     VMHEAP_SENSITIVE_JVBIN_APP_SENSITIVE_JVBIN,
162     VMHEAP_SENSITIVE_JVBIN_APP_VDEX,
163 
164     // App hrt, boot hrt.
165     VMHEAP_HRT_APP,
166     VMHEAP_HRT_BOOT,
167 
168     VMHEAP_NUM_HEAP,
169     VMHEAP_NUM_EXCLUSIVE_HEAP = VMHEAP_OTHER_MEMTRACK + 1,
170     VMHEAP_NUM_CORE_HEAP = VMHEAP_NATIVE + 1
171 };
172 
173 enum OpsType {
174     OPS_START = 1,
175     OPS_END,
176 };
177 
178 struct VmeminfoAreaMapping {
179     int ops;
180     const char* heapstr;
181     int heapid[2];
182 };
183 
184 constexpr VmeminfoAreaMapping g_vmaMemHeap[] = {
185     {OpsType::OPS_START, "[heap]", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}},
186     {OpsType::OPS_START, "[stack", {VmemifoType::VMHEAP_STACK, VmemifoType::VMHEAP_NULL}},
187 };
188 
189 // [anon:
190 constexpr VmeminfoAreaMapping g_vmaMemAnon[] = {
191     {OpsType::OPS_START, "[anon:libc_malloc]", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}},
192     {OpsType::OPS_START, "[anon:native_heap:", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}},
193     {OpsType::OPS_START, "[anon:scudo:", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}},
194     {OpsType::OPS_START, "[anon:GWP-ASan", {VmemifoType::VMHEAP_NATIVE, VmemifoType::VMHEAP_NULL}},
195     {OpsType::OPS_START, "[anon:stack_and_tls:", {VmemifoType::VMHEAP_STACK, VmemifoType::VMHEAP_NULL}},
196     {OpsType::OPS_START,
197      "[anon:sensitive_vm-LinearAlloc",
198      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_LINEARALLOC}},
199     {OpsType::OPS_START,
200      "[anon:sensitive_vm-alloc space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}},
201     {OpsType::OPS_START,
202      "[anon:sensitive_vm-main space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NORMAL}},
203     {OpsType::OPS_START,
204      "[anon:sensitive_vm-large object space",
205      {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}},
206     {OpsType::OPS_START,
207      "[anon:sensitive_vm-free list large object space",
208      {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_LARGE}},
209     {OpsType::OPS_START,
210      "[anon:sensitive_vm-non moving space",
211      {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_NON_MOVING}},
212     {OpsType::OPS_START,
213      "[anon:sensitive_vm-zygote space", {VmemifoType::VMHEAP_SENSITIVE_VM, VmemifoType::VMHEAP_SENSITIVE_VM_ZYGOTE}},
214     {OpsType::OPS_START,
215      "[anon:sensitive_vm-indirect ref",
216      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_INDIRECT_REFERENCE_TABLE}},
217     {OpsType::OPS_START,
218      "[anon:sensitive_vm-jit-code-cache",
219      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}},
220     {OpsType::OPS_START,
221      "[anon:sensitive_vm-data-code-cache",
222      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}},
223     {OpsType::OPS_START,
224      "[anon:sensitive_vm-CompilerMetadata",
225      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_COMPILER_METADATA}},
226     {OpsType::OPS_START,
227      "[anon:sensitive_vm-",
228      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ACCOUNTING}},
229     {OpsType::OPS_START, "[anon:", {VmemifoType::VMHEAP_UNKNOWN, VmemifoType::VMHEAP_NULL}},
230 };
231 
232 constexpr VmeminfoAreaMapping g_vmaMemFd[] = {
233     {OpsType::OPS_START,
234      "/memfd:jit-cache",
235      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_APP_CODE_CACHE}},
236     {OpsType::OPS_START,
237      "/memfd:jit-zygote-cache",
238      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}},
239 };
240 // dev
241 constexpr VmeminfoAreaMapping g_vmaMemDev[] = {
242     {OpsType::OPS_START, "/dev/kgsl-3d0", {VmemifoType::VMHEAP_GL_DEV, VmemifoType::VMHEAP_NULL}},
243     {OpsType::OPS_START, "/dev/ashmem/CursorWindow", {VmemifoType::VMHEAP_CURSOR, VmemifoType::VMHEAP_NULL}},
244     {OpsType::OPS_START,
245      "/dev/ashmem/jit-zygote-cache",
246      {VmemifoType::VMHEAP_SENSITIVE_VM_OTHER, VmemifoType::VMHEAP_SENSITIVE_VM_OTHER_ZYGOTE_CODE_CACHE}},
247     {OpsType::OPS_START, "/dev/ashmem", {VmemifoType::VMHEAP_ASHMEM, VmemifoType::VMHEAP_NULL}},
248     {OpsType::OPS_START, "/dev/", {VmemifoType::VMHEAP_UNKNOWN_DEV, VmemifoType::VMHEAP_NULL}},
249 };
250 
251 constexpr VmeminfoAreaMapping g_vmaMemSuffix[] = {
252     {OpsType::OPS_END, ".so", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}},
253     {OpsType::OPS_END, ".so.1", {VmemifoType::VMHEAP_SO, VmemifoType::VMHEAP_NULL}},
254     {OpsType::OPS_END, ".jar", {VmemifoType::VMHEAP_JAR, VmemifoType::VMHEAP_NULL}},
255     {OpsType::OPS_END, ".ttf", {VmemifoType::VMHEAP_TTF, VmemifoType::VMHEAP_NULL}},
256     {OpsType::OPS_END, ".oat", {VmemifoType::VMHEAP_OAT, VmemifoType::VMHEAP_NULL}},
257 
258     {OpsType::OPS_END,
259      ".odex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_SENSITIVE_JVBIN_APP_SENSITIVE_JVBIN}},
260 
261     {OpsType::OPS_END, ".vdex", {VmemifoType::VMHEAP_SENSITIVE_JVBIN, VmemifoType::VMHEAP_NEEDFIX}},
262     {OpsType::OPS_END, ".hrt", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}},
263     {OpsType::OPS_END, ".hrt]", {VmemifoType::VMHEAP_HRT, VmemifoType::VMHEAP_NEEDFIX}},
264 };
265 
266 class SmapsStats {
267 public:
SmapsStats()268     SmapsStats() {}
SmapsStats(const std::string path)269     SmapsStats(const std::string path) : testpath_(path){};
~SmapsStats()270     ~SmapsStats() {}
271 
272     using MatchFunc = std::function<bool(const std::string& name, const char* str)>;
273 
274     bool ParseMaps(int pid, ProcessMemoryInfo& processinfo, bool isReportApp, bool isReportSmaps);
275     int GetProcessJavaHeap();
276     int GetProcessNativeHeap();
277     int GetProcessCode();
278     int GetProcessStack();
279     int GetProcessGraphics();
280     int GetProcessPrivateOther();
281     int GetProcessSystem();
282 private:
283     std::array<StatsInfo, VMHEAP_NUM_HEAP> stats_;
284     bool lastline_ = false;
285     std::string testpath_;
286 
287     int GetTotalPrivateClean();
288     int GetTotalPrivateDirty();
289     int GetPrivate(int type);
290     int GetTotalPss();
291     int GetTotalSwappedOutPss();
292     void ReviseStatsData();
293 
294     bool ReadVmemareasFile(const std::string& path, ProcessMemoryInfo& processinfo, bool isReportApp,
295                            bool isReportSmaps);
296     bool ParseMapHead(std::string& line, MapPiecesInfo& head, SmapsHeadInfo& smapsHeadInfo);
297     bool SetMapAddrInfo(std::string& line, MapPiecesInfo& head);
298     bool GetMemUsageField(std::string& line, MemUsageInfo& memusage);
299     void CollectVmemAreasData(const MapPiecesInfo& mempic,
300                               const MemUsageInfo& memusage,
301                               uint64_t& prevEnd,
302                               int& prevHeap);
303     bool GetVmaIndex(std::string name, uint32_t namesz, int32_t heapIndex[2], bool& swappable);
304     uint64_t GetSwapablepssValue(const MemUsageInfo& memusage, bool swappable);
305     void SetVmemAreasData(int index, uint64_t swapablePss, const MemUsageInfo& usage);
306     void HeapIndexFix(std::string name, const char* key, int32_t heapIndex[2]);
307     bool GetVMAStuId(int ops,
308                      std::string name,
309                      const VmeminfoAreaMapping vma[],
310                      int count,
311                      int32_t heapIndex[2],
312                      bool& swappable);
313     std::string ParseCategory(const SmapsHeadInfo& smapsHeadInfo);
314     bool GetCategoryFromMap(const std::string &name, std::string &group,
315                             const std::map<std::string, std::string> &map, MatchFunc func);
316     const std::map<std::string, std::string> beginMap_ = {
317         {"[heap]", "native heap"}, {"[stack]", "stack"}, {"[anon:stack", "stack"},
318         {"[anon:native_heap:", "native heap"}, {"[anon:ArkTS Heap]", "ark ts heap"},
319         {"[anon:guard", "guard"}, {"/dev", "dev"}, {"[anon:signal_stack", "stack"},
320         {"/dmabuf", "dmabuf"}, {"/data/storage", ".hap"}, {"[anon:libc_malloc", "native heap"},
321         {"[anon:scudo", "native heap"}, {"[anon:GWP-ASan", "native heap"},
322     };
323     const std::map<std::string, std::string> endMap_ = {
324         {".so", ".so"}, {".so.1", ".so"}, {".ttf", ".ttf"},
325         {".db", ".db"}, {".db-shm", ".db"},
326     };
327     const std::string FILE_PAGE_TAG = "FilePage other";
328     const std::string ANON_PAGE_TAG = "AnonPage other";
329 };
330 
331 #endif