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