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