1 /*
2  * Copyright (c) 2023 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 #include "executor/memory/smaps_memory_info.h"
16 
17 #include <cinttypes>
18 #include <fstream>
19 #include <numeric>
20 #include <thread>
21 #include <v1_0/imemory_tracker_interface.h>
22 #include <cstring>
23 
24 #include "dump_common_utils.h"
25 #include "executor/memory/get_cma_info.h"
26 #include "executor/memory/get_hardware_info.h"
27 #include "executor/memory/get_kernel_info.h"
28 #include "executor/memory/get_process_info.h"
29 #include "executor/memory/get_ram_info.h"
30 #include "executor/memory/memory_util.h"
31 #include "executor/memory/parse/meminfo_data.h"
32 #include "executor/memory/parse/parse_meminfo.h"
33 #include "executor/memory/parse/parse_smaps_rollup_info.h"
34 #include "executor/memory/parse/parse_smaps_info.h"
35 #include "hdf_base.h"
36 #include "hilog_wrapper.h"
37 #include "securec.h"
38 #include "string_ex.h"
39 #include "util/string_utils.h"
40 
41 using namespace std;
42 using namespace OHOS::HDI::Memorytracker::V1_0;
43 namespace OHOS {
44 namespace HiviewDFX {
45 static constexpr int LINE_WIDTH = 12;
46 static constexpr int LINE_NAME_VAL_WIDTH = 60;
47 static constexpr int LINE_START_VAL_WIDTH = 18;
48 static constexpr int LINE_NAME_V_WIDTH = 16;
49 static constexpr size_t TYPE_SIZE = 2;
50 static constexpr size_t TYPE_MIN_SIZE = 1;
51 static constexpr char BLANK = ' ';
SmapsMemoryInfo()52 SmapsMemoryInfo::SmapsMemoryInfo()
53 {
54     sMapsMethodVec_.clear();
55     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_RSS,
56         bind(&SmapsMemoryInfo::SetRss, this, placeholders::_1, placeholders::_2)));
57     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_PSS,
58         bind(&SmapsMemoryInfo::SetPss, this, placeholders::_1, placeholders::_2)));
59     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_SHARED_CLEAN,
60         bind(&SmapsMemoryInfo::SetSharedClean, this, placeholders::_1, placeholders::_2)));
61     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_SHARED_DIRTY,
62         bind(&SmapsMemoryInfo::SetSharedDirty, this, placeholders::_1, placeholders::_2)));
63     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_PRIVATE_CLEAN,
64         bind(&SmapsMemoryInfo::SetPrivateClean, this, placeholders::_1, placeholders::_2)));
65     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_PRIVATE_DIRTY,
66         bind(&SmapsMemoryInfo::SetPrivateDirty, this, placeholders::_1, placeholders::_2)));
67     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_SWAP,
68         bind(&SmapsMemoryInfo::SetSwap, this, placeholders::_1, placeholders::_2)));
69     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_SWAP_PSS,
70         bind(&SmapsMemoryInfo::SetSwapPss, this, placeholders::_1, placeholders::_2)));
71     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_SIZE,
72         bind(&SmapsMemoryInfo::SetSize, this, placeholders::_1, placeholders::_2)));
73     sMapsMethodVec_.push_back(make_pair(SMAPS_MEMINFO_COUNTS,
74         bind(&SmapsMemoryInfo::SetCounts, this, placeholders::_1, placeholders::_2)));
75 }
76 
~SmapsMemoryInfo()77 SmapsMemoryInfo::~SmapsMemoryInfo()
78 {
79 }
80 
InsertSmapsTitle(StringMatrix result,bool isShowSmapsInfo)81 void SmapsMemoryInfo::InsertSmapsTitle(StringMatrix result, bool isShowSmapsInfo)
82 {
83     vector<string> line1;
84     vector<string> line2;
85     vector<string> titleVec = isShowSmapsInfo ? MemoryFilter::GetInstance().TITLE_V_SMAPS_HAS_PID_ :
86         MemoryFilter::GetInstance().TITLE_SMAPS_HAS_PID_;
87     for (string str : titleVec) {
88         vector<string> types;
89         StringUtils::GetInstance().StringSplit(str, "_", types);
90         if (types.size() == TYPE_SIZE) {
91             string title1 = types.at(0);
92             StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, title1);
93             line1.push_back(title1);
94             string title2 = types.at(1);
95             StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, title2);
96             line2.push_back(title2);
97         } else if (types.size() == TYPE_MIN_SIZE) {
98             string title = types.at(0);
99             string space = " ";
100             StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, space);
101             line1.push_back(space);
102             constexpr int LINE_NAME_KEY_WIDTH = 22;
103             if (StringUtils::GetInstance().IsSameStr(title, "Name")) {
104                 StringUtils::GetInstance().SetWidth(isShowSmapsInfo ? LINE_NAME_V_WIDTH : LINE_NAME_KEY_WIDTH,
105                     BLANK, false, title);
106             } else {
107                 StringUtils::GetInstance().SetWidth(StringUtils::GetInstance().IsSameStr(title, "Start") ?
108                     LINE_START_VAL_WIDTH : LINE_WIDTH, BLANK, true, title);
109             }
110             line2.push_back(title);
111         }
112     }
113     result->push_back(line1);
114     result->push_back(line2);
115 }
116 
BuildSmapsInfo(StringMatrix result,vector<map<string,string>> vectMap)117 void SmapsMemoryInfo::BuildSmapsInfo(StringMatrix result, vector<map<string, string>> vectMap)
118 {
119     for (auto obj : vectMap) {
120         vector<string> tempResult;
121         for (const auto &tag : MemoryFilter::GetInstance().VALUE_SMAPS_V_WITH_PID_) {
122             string value = obj.at(tag);
123             if (StringUtils::GetInstance().IsSameStr(tag, "Name")) {
124                 string space = " ";
125                 StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, false, space);
126                 value = space + value;
127                 StringUtils::GetInstance().SetWidth(LINE_NAME_VAL_WIDTH, BLANK, true, value);
128             } else {
129                 StringUtils::GetInstance().SetWidth(StringUtils::GetInstance().IsSameStr(tag, "Start") ?
130                     LINE_START_VAL_WIDTH : LINE_WIDTH, BLANK, true, value);
131             }
132             tempResult.push_back(value);
133         }
134         result->push_back(tempResult);
135     }
136 }
137 
BuildSmapsResult(const GroupMap & infos,StringMatrix result,bool isShowSmapsInfo,vector<map<string,string>> vectMap)138 void SmapsMemoryInfo::BuildSmapsResult(const GroupMap &infos, StringMatrix result, bool isShowSmapsInfo,
139     vector<map<string, string>> vectMap)
140 {
141     InsertSmapsTitle(result, isShowSmapsInfo);
142     if (isShowSmapsInfo) {
143         BuildSmapsInfo(result, vectMap);
144         return;
145     }
146     for (const auto &info : infos) {
147         vector<string> tempResult;
148         auto &valueMap = info.second;
149         for (const auto &tag : MemoryFilter::GetInstance().TITLE_SMAPS_HAS_PID_) {
150             auto it = valueMap.find(tag);
151             string value = "0";
152             if (it != valueMap.end()) {
153                 if (StringUtils::GetInstance().IsSameStr(tag, "Name")) {
154                     value = info.first;
155                 } else {
156                     value = to_string(it->second);
157                 }
158             }
159             if (StringUtils::GetInstance().IsSameStr(tag, "Name")) {
160                 string space = " ";
161                 StringUtils::GetInstance().SetWidth(LINE_START_VAL_WIDTH, BLANK, false, space);
162                 value = space + value;
163                 StringUtils::GetInstance().SetWidth(LINE_NAME_VAL_WIDTH, BLANK, true, value);
164             } else {
165                 StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, value);
166             }
167             tempResult.push_back(value);
168         }
169         result->push_back(tempResult);
170     }
171 }
172 
CalcSmapsStatData(MemInfoData::MemSmapsInfo & memSmapsInfo,const GroupMap & infos)173 bool SmapsMemoryInfo::CalcSmapsStatData(MemInfoData::MemSmapsInfo &memSmapsInfo, const GroupMap &infos)
174 {
175     for (const auto &info : infos) {
176         auto &valueMap = info.second;
177         for (const auto &method : sMapsMethodVec_) {
178             auto it = valueMap.find(method.first);
179             if (it != valueMap.end()) {
180                 method.second(memSmapsInfo, it->second);
181             }
182         }
183     }
184     return true;
185 }
186 
CalcSmapsInfo(MemInfoData::MemSmapsInfo & memSmapsInfo,vector<map<string,string>> vectMap)187 bool SmapsMemoryInfo::CalcSmapsInfo(MemInfoData::MemSmapsInfo &memSmapsInfo, vector<map<string, string>> vectMap)
188 {
189     for (auto obj : vectMap) {
190         for (const auto &method : sMapsMethodVec_) {
191             string key = method.first;
192             if (obj.find(key) != obj.end()) {
193                 constexpr int BASE = 10;
194                 method.second(memSmapsInfo, strtoull(obj.at(key).c_str(), nullptr, BASE));
195             }
196         }
197     }
198     return true;
199 }
200 
CalcSmapsGroup(const GroupMap & infos,StringMatrix result,MemInfoData::MemSmapsInfo & memSmapsInfo,bool isShowSmapsInfo,vector<map<string,string>> vectMap)201 void SmapsMemoryInfo::CalcSmapsGroup(const GroupMap &infos, StringMatrix result,
202     MemInfoData::MemSmapsInfo &memSmapsInfo, bool isShowSmapsInfo, vector<map<string, string>> vectMap)
203 {
204     bool flag = isShowSmapsInfo ? CalcSmapsInfo(memSmapsInfo, vectMap) : CalcSmapsStatData(memSmapsInfo, infos);
205     if (!flag) {
206         return;
207     }
208     vector<string> lines;
209     vector<string> values;
210     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.size), lines, values, true);
211     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.rss), lines, values, true);
212     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.pss + memSmapsInfo.swapPss), lines, values, true);
213     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.sharedClean), lines, values, true);
214     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.sharedDirty), lines, values, true);
215     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.privateClean), lines, values, true);
216     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.privateDirty), lines, values, true);
217     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.swap), lines, values, true);
218     MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.swapPss), lines, values, true);
219     if (!isShowSmapsInfo) {
220         MemoryUtil::GetInstance().SetMemTotalValue(to_string(memSmapsInfo.counts), lines, values, true);
221     } else {
222         MemoryUtil::GetInstance().SetMemTotalValue("", lines, values, true);
223         MemoryUtil::GetInstance().SetMemTotalValue("", lines, values, true);
224         MemoryUtil::GetInstance().SetMemTotalValue("", lines, values, true);
225     }
226     MemoryUtil::GetInstance().SetMemTotalValue("Summary", lines, values, true);
227     result->push_back(lines);
228     result->push_back(values);
229 }
230 
ShowMemorySmapsByPid(const int & pid,StringMatrix result,bool isShowSmapsInfo)231 bool SmapsMemoryInfo::ShowMemorySmapsByPid(const int &pid, StringMatrix result, bool isShowSmapsInfo)
232 {
233     GroupMap groupMap;
234     MemInfoData::MemSmapsInfo memSmapsinfo;
235     vector<map<string, string>> vectMap;
236     MemoryUtil::GetInstance().InitMemSmapsInfo(memSmapsinfo);
237     unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
238     if (!parseSmapsInfo->ShowSmapsData(MemoryFilter::APPOINT_PID, pid, groupMap, isShowSmapsInfo, vectMap)) {
239         DUMPER_HILOGE(MODULE_SERVICE, "parse smaps info fail");
240         return false;
241     }
242     BuildSmapsResult(groupMap, result, isShowSmapsInfo, vectMap);
243     CalcSmapsGroup(groupMap, result, memSmapsinfo, isShowSmapsInfo, vectMap);
244     return true;
245 }
246 
SetPss(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)247 void SmapsMemoryInfo::SetPss(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
248 {
249     meminfo.pss += value;
250 }
251 
SetRss(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)252 void SmapsMemoryInfo::SetRss(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
253 {
254     meminfo.rss += value;
255 }
256 
SetSharedClean(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)257 void SmapsMemoryInfo::SetSharedClean(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
258 {
259     meminfo.sharedClean += value;
260 }
261 
SetSharedDirty(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)262 void SmapsMemoryInfo::SetSharedDirty(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
263 {
264     meminfo.sharedDirty += value;
265 }
266 
SetPrivateClean(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)267 void SmapsMemoryInfo::SetPrivateClean(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
268 {
269     meminfo.privateClean += value;
270 }
271 
SetPrivateDirty(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)272 void SmapsMemoryInfo::SetPrivateDirty(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
273 {
274     meminfo.privateDirty += value;
275 }
276 
SetSwap(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)277 void SmapsMemoryInfo::SetSwap(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
278 {
279     meminfo.swap += value;
280 }
281 
SetSwapPss(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)282 void SmapsMemoryInfo::SetSwapPss(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
283 {
284     meminfo.swapPss += value;
285 }
286 
SetSize(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)287 void SmapsMemoryInfo::SetSize(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
288 {
289     meminfo.size += value;
290 }
291 
SetName(MemInfoData::MemSmapsInfo & meminfo,const string & value)292 void SmapsMemoryInfo::SetName(MemInfoData::MemSmapsInfo &meminfo, const string &value)
293 {
294     meminfo.name = value;
295 }
296 
SetCounts(MemInfoData::MemSmapsInfo & meminfo,uint64_t value)297 void SmapsMemoryInfo::SetCounts(MemInfoData::MemSmapsInfo &meminfo, uint64_t value)
298 {
299     meminfo.counts += value;
300 }
301 } // namespace HiviewDFX
302 } // namespace OHOS
303