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 "dump_utils.h"
26 #include "executor/memory/get_cma_info.h"
27 #include "executor/memory/get_hardware_info.h"
28 #include "executor/memory/get_kernel_info.h"
29 #include "executor/memory/get_process_info.h"
30 #include "executor/memory/get_ram_info.h"
31 #include "executor/memory/memory_util.h"
32 #include "executor/memory/parse/meminfo_data.h"
33 #include "executor/memory/parse/parse_meminfo.h"
34 #include "executor/memory/parse/parse_smaps_rollup_info.h"
35 #include "executor/memory/parse/parse_smaps_info.h"
36 #include "hdf_base.h"
37 #include "hilog_wrapper.h"
38 #include "securec.h"
39 #include "string_ex.h"
40 #include "util/string_utils.h"
41
42 using namespace std;
43 using namespace OHOS::HDI::Memorytracker::V1_0;
44 namespace OHOS {
45 namespace HiviewDFX {
46 static constexpr int LINE_WIDTH = 12;
47 static constexpr int LINE_NAME_VAL_WIDTH = 60;
48 static constexpr int LINE_START_VAL_WIDTH = 18;
49 static constexpr int LINE_NAME_V_WIDTH = 16;
50 static constexpr int LINE_MEMORY_CLASS_WIDTH = 15;
51 static constexpr size_t TYPE_SIZE = 2;
52 static constexpr size_t TYPE_MIN_SIZE = 1;
53 static constexpr char BLANK = ' ';
SmapsMemoryInfo()54 SmapsMemoryInfo::SmapsMemoryInfo()
55 {
56 }
57
~SmapsMemoryInfo()58 SmapsMemoryInfo::~SmapsMemoryInfo()
59 {
60 }
61
InsertSmapsTitle(StringMatrix result,bool isShowSmapsInfo)62 void SmapsMemoryInfo::InsertSmapsTitle(StringMatrix result, bool isShowSmapsInfo)
63 {
64 vector<string> line1;
65 vector<string> line2;
66 vector<string> titleVec = isShowSmapsInfo ? MemoryFilter::GetInstance().TITLE_V_SMAPS_HAS_PID_ :
67 MemoryFilter::GetInstance().TITLE_SMAPS_HAS_PID_;
68 if (DumpUtils::IsUserMode()) {
69 titleVec.erase(std::remove(titleVec.begin(), titleVec.end(), "Perm"), titleVec.end());
70 titleVec.erase(std::remove(titleVec.begin(), titleVec.end(), "Start"), titleVec.end());
71 titleVec.erase(std::remove(titleVec.begin(), titleVec.end(), "End"), titleVec.end());
72 }
73 for (string str : titleVec) {
74 vector<string> types;
75 StringUtils::GetInstance().StringSplit(str, "_", types);
76 if (types.size() == TYPE_SIZE) {
77 string title1 = types.at(0);
78 StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, title1);
79 line1.push_back(title1);
80 string title2 = types.at(1);
81 StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, title2);
82 line2.push_back(title2);
83 } else if (types.size() == TYPE_MIN_SIZE) {
84 string title = types.at(0);
85 string space = " ";
86 StringUtils::GetInstance().SetWidth(LINE_WIDTH, BLANK, true, space);
87 line1.push_back(space);
88 constexpr int LINE_NAME_KEY_WIDTH = 22;
89 if (StringUtils::GetInstance().IsSameStr(title, "Name")) {
90 StringUtils::GetInstance().SetWidth(isShowSmapsInfo ? LINE_NAME_V_WIDTH : LINE_NAME_KEY_WIDTH,
91 BLANK, false, title);
92 } else if (StringUtils::GetInstance().IsSameStr(title, "Category")) {
93 StringUtils::GetInstance().SetWidth(LINE_MEMORY_CLASS_WIDTH, BLANK, true, title);
94 } else {
95 StringUtils::GetInstance().SetWidth(StringUtils::GetInstance().IsSameStr(title, "Start") ?
96 LINE_START_VAL_WIDTH : LINE_WIDTH, BLANK, true, title);
97 }
98 line2.push_back(title);
99 }
100 }
101 result->push_back(line1);
102 result->push_back(line2);
103 }
104
SetValueForRet(const std::string & value,const int & width,std::vector<std::string> & tempResult)105 void SmapsMemoryInfo::SetValueForRet(const std::string& value, const int &width, std::vector<std::string>& tempResult)
106 {
107 std::string tempStr = value;
108 StringUtils::GetInstance().SetWidth(width, BLANK, true, tempStr);
109 tempResult.push_back(tempStr);
110 }
111
SetOneRowMemInfo(const MemoryData & memInfo,bool isShowSmapsInfo,bool isSummary,StringMatrix result)112 void SmapsMemoryInfo::SetOneRowMemInfo(const MemoryData &memInfo, bool isShowSmapsInfo,
113 bool isSummary, StringMatrix result)
114 {
115 vector<string> tempResult;
116 SetValueForRet(to_string(memInfo.size), LINE_WIDTH, tempResult);
117 SetValueForRet(to_string(memInfo.rss), LINE_WIDTH, tempResult);
118 SetValueForRet(to_string(memInfo.pss), LINE_WIDTH, tempResult);
119 SetValueForRet(to_string(memInfo.sharedClean), LINE_WIDTH, tempResult);
120 SetValueForRet(to_string(memInfo.sharedDirty), LINE_WIDTH, tempResult);
121 SetValueForRet(to_string(memInfo.privateClean), LINE_WIDTH, tempResult);
122 SetValueForRet(to_string(memInfo.privateDirty), LINE_WIDTH, tempResult);
123 SetValueForRet(to_string(memInfo.swap), LINE_WIDTH, tempResult);
124 SetValueForRet(to_string(memInfo.swapPss), LINE_WIDTH, tempResult);
125 if (isShowSmapsInfo) {
126 if (!DumpUtils::IsUserMode()) {
127 SetValueForRet(memInfo.permission, LINE_WIDTH, tempResult);
128 SetValueForRet(memInfo.startAddr, LINE_START_VAL_WIDTH, tempResult);
129 SetValueForRet(memInfo.endAddr, LINE_WIDTH, tempResult);
130 }
131 } else {
132 SetValueForRet(to_string(memInfo.counts), LINE_WIDTH, tempResult);
133 }
134 // set memory class
135 string memoryClass = memInfo.memoryClass;
136 if (memoryClass == "other") {
137 if (memInfo.iNode == 0) {
138 memoryClass = "AnonPage other";
139 } else {
140 memoryClass = "FilePage other";
141 }
142 }
143 SetValueForRet(memoryClass, LINE_MEMORY_CLASS_WIDTH, tempResult);
144 // set name
145 string space = " ";
146 StringUtils::GetInstance().SetWidth(isShowSmapsInfo ? LINE_WIDTH : LINE_START_VAL_WIDTH, BLANK, false, space);
147 string value = isSummary ? "Summary" : memInfo.name;
148 value = space + value;
149 StringUtils::GetInstance().SetWidth(LINE_NAME_VAL_WIDTH, BLANK, true, value);
150 tempResult.push_back(value);
151
152 // set one row data
153 result->push_back(tempResult);
154 }
155
UpdateShowAddressMemInfoResult(const std::vector<MemoryData> & showAddressMemInfoVec,StringMatrix result)156 void SmapsMemoryInfo::UpdateShowAddressMemInfoResult(const std::vector<MemoryData>& showAddressMemInfoVec,
157 StringMatrix result)
158 {
159 MemoryData summary;
160 for (const auto &memInfo : showAddressMemInfoVec) {
161 summary.size += memInfo.size;
162 summary.rss += memInfo.rss;
163 summary.pss += memInfo.pss;
164 summary.sharedClean += memInfo.sharedClean;
165 summary.sharedDirty += memInfo.sharedDirty;
166 summary.privateClean += memInfo.privateClean;
167 summary.privateDirty += memInfo.privateDirty;
168 summary.swap += memInfo.swap;
169 summary.swapPss += memInfo.swapPss;
170 SetOneRowMemInfo(memInfo, true, false, result);
171 }
172 summary.pss += summary.swapPss;
173 SetOneRowMemInfo(summary, true, true, result);
174 }
175
UpdateCountSameNameMemResult(std::map<std::string,MemoryData> & countSameNameMemMap,StringMatrix result)176 void SmapsMemoryInfo::UpdateCountSameNameMemResult(std::map<std::string, MemoryData>& countSameNameMemMap,
177 StringMatrix result)
178 {
179 MemoryData summary;
180 for (const auto &memInfo : countSameNameMemMap) {
181 summary.size += memInfo.second.size;
182 summary.rss += memInfo.second.rss;
183 summary.pss += memInfo.second.pss;
184 summary.sharedClean += memInfo.second.sharedClean;
185 summary.sharedDirty += memInfo.second.sharedDirty;
186 summary.privateClean += memInfo.second.privateClean;
187 summary.privateDirty += memInfo.second.privateDirty;
188 summary.swap += memInfo.second.swap;
189 summary.swapPss += memInfo.second.swapPss;
190 summary.counts += memInfo.second.counts;
191 SetOneRowMemInfo(memInfo.second, false, false, result);
192 }
193 summary.pss += summary.swapPss;
194 SetOneRowMemInfo(summary, false, true, result);
195 }
196
ShowMemorySmapsByPid(const int & pid,StringMatrix result,bool isShowSmapsAddress)197 bool SmapsMemoryInfo::ShowMemorySmapsByPid(const int &pid, StringMatrix result, bool isShowSmapsAddress)
198 {
199 DUMPER_HILOGI(MODULE_SERVICE, "get smaps data begin, pid:%{public}d", pid);
200 std::map<std::string, MemoryData> countSameNameMemMap;
201 std::vector<MemoryData> showAddressMemInfoVec;
202 unique_ptr<ParseSmapsInfo> parseSmapsInfo = make_unique<ParseSmapsInfo>();
203 bool ret = parseSmapsInfo->GetSmapsData(pid, isShowSmapsAddress, countSameNameMemMap, showAddressMemInfoVec);
204 if (!ret) {
205 return false;
206 }
207 InsertSmapsTitle(result, isShowSmapsAddress);
208 if (isShowSmapsAddress) {
209 UpdateShowAddressMemInfoResult(showAddressMemInfoVec, result);
210 } else {
211 UpdateCountSameNameMemResult(countSameNameMemMap, result);
212 }
213 DUMPER_HILOGI(MODULE_SERVICE, "get smaps data end, pid:%{public}d", pid);
214 return true;
215 }
216 } // namespace HiviewDFX
217 } // namespace OHOS