1 /*
2 * Copyright (C) 2021-2022 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 #include "executor/memory/parse/parse_smaps_info.h"
17 #include <fstream>
18 #include "executor/memory/memory_util.h"
19 #include "hilog_wrapper.h"
20 #include "util/string_utils.h"
21 #include "util/file_utils.h"
22
23 using namespace std;
24 namespace OHOS {
25 namespace HiviewDFX {
ParseSmapsInfo()26 ParseSmapsInfo::ParseSmapsInfo()
27 {
28 }
29
~ParseSmapsInfo()30 ParseSmapsInfo::~ParseSmapsInfo()
31 {
32 }
33
GetHasPidValue(const string & str,string & type,uint64_t & value)34 bool ParseSmapsInfo::GetHasPidValue(const string &str, string &type, uint64_t &value)
35 {
36 bool success = false;
37 if (StringUtils::GetInstance().IsBegin(str, "R")) {
38 success = MemoryUtil::GetInstance().GetTypeAndValue(str, type, value);
39 if (success) {
40 if (type == "Rss") {
41 return true;
42 }
43 }
44 return false;
45 } else if (StringUtils::GetInstance().IsBegin(str, "P")) {
46 success = MemoryUtil::GetInstance().GetTypeAndValue(str, type, value);
47 if (success) {
48 if (type == "Pss" || type == "Private_Clean" || type == "Private_Dirty") {
49 return true;
50 }
51 }
52 return false;
53 } else if (StringUtils::GetInstance().IsBegin(str, "S")) {
54 success = MemoryUtil::GetInstance().GetTypeAndValue(str, type, value);
55 if (success) {
56 if (type == "Shared_Clean" || type == "Shared_Dirty" || type == "Swap" || type == "SwapPss" ||
57 type == "Size") {
58 return true;
59 }
60 }
61 return false;
62 }
63 return false;
64 }
65
GetNoPidValue(const string & str,string & type,uint64_t & value)66 bool ParseSmapsInfo::GetNoPidValue(const string &str, string &type, uint64_t &value)
67 {
68 if (StringUtils::GetInstance().IsBegin(str, "Pss") || StringUtils::GetInstance().IsBegin(str, "SwapPss")) {
69 return MemoryUtil::GetInstance().GetTypeAndValue(str, type, value);
70 }
71 return false;
72 }
73
GetValue(const MemoryFilter::MemoryType & memType,const string & str,string & type,uint64_t & value)74 bool ParseSmapsInfo::GetValue(const MemoryFilter::MemoryType &memType, const string &str, string &type, uint64_t &value)
75 {
76 if (memType == MemoryFilter::MemoryType::APPOINT_PID) {
77 return GetHasPidValue(str, type, value);
78 } else {
79 return GetNoPidValue(str, type, value);
80 }
81 }
82
GetSmapsValue(const MemoryFilter::MemoryType & memType,const string & str,string & type,uint64_t & value)83 bool ParseSmapsInfo::GetSmapsValue(const MemoryFilter::MemoryType &memType, const string &str, string &type,
84 uint64_t &value)
85 {
86 if (memType == MemoryFilter::MemoryType::APPOINT_PID) {
87 return GetHasPidValue(str, type, value);
88 }
89 return false;
90 }
91
92 /**
93 * @description: Parse smaps file
94 * @param {MemoryType} &memType-APPOINT_PID-Specify the PID,NOT_SPECIFIED_PID-No PID is specified
95 * @param {int} &pid-Pid
96 * @param {GroupMap} &result-The result of parsing
97 * @return bool-true:parse success,false-parse fail
98 */
GetInfo(const MemoryFilter::MemoryType & memType,const int & pid,GroupMap & nativeMap,GroupMap & result)99 bool ParseSmapsInfo::GetInfo(const MemoryFilter::MemoryType &memType, const int &pid,
100 GroupMap &nativeMap, GroupMap &result)
101 {
102 DUMPER_HILOGD(MODULE_SERVICE, "ParseSmapsInfo: GetInfo pid:(%{public}d) begin.\n", pid);
103 string path = "/proc/" + to_string(pid) + "/smaps";
104 bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, false, true, [&](const string& line) -> void {
105 string name;
106 uint64_t iNode = 0;
107 if (StringUtils::GetInstance().IsEnd(line, "B")) {
108 string type;
109 uint64_t value = 0;
110 if (GetValue(memType, line, type, value)) {
111 MemoryUtil::GetInstance().CalcGroup(memGroup_, type, value, result);
112 MemoryUtil::GetInstance().CalcGroup(nativeMemGroup_, type, value, nativeMap);
113 }
114 } else if (MemoryUtil::GetInstance().IsNameLine(line, name, iNode)) {
115 MemoryFilter::GetInstance().ParseMemoryGroup(name, memGroup_, iNode);
116 MemoryFilter::GetInstance().ParseNativeHeapMemoryGroup(name, nativeMemGroup_, iNode);
117 }
118 });
119 DUMPER_HILOGD(MODULE_SERVICE, "ParseSmapsInfo: GetInfo pid:(%{public}d) end,success!\n", pid);
120 return ret;
121 }
122
SetMapByNameLine(const string & group,const string & content)123 void ParseSmapsInfo::SetMapByNameLine(const string &group, const string &content)
124 {
125 memMap_.insert(pair<string, string>("Name", group));
126 vector<string> datas;
127 StringUtils::GetInstance().StringSplit(content, " ", datas);
128 vector<string> startAndEnd;
129 StringUtils::GetInstance().StringSplit(datas.at(0), "-", startAndEnd);
130 string startVal = startAndEnd.front();
131 string endVal = startAndEnd.back();
132 memMap_.insert(pair<string, string>("Start", startVal));
133 memMap_.insert(pair<string, string>("End", endVal));
134 memMap_.insert(pair<string, string>("Perm", datas.at(1)));
135 }
136
ShowSmapsData(const MemoryFilter::MemoryType & memType,const int & pid,GroupMap & result,bool isShowSmapsInfo,vector<map<string,string>> & vectMap)137 bool ParseSmapsInfo::ShowSmapsData(const MemoryFilter::MemoryType &memType, const int &pid, GroupMap &result,
138 bool isShowSmapsInfo, vector<map<string, string>> &vectMap)
139 {
140 string path = "/proc/" + to_string(pid) + "/smaps";
141 bool ret = FileUtils::GetInstance().LoadStringFromProcCb(path, false, true, [&](const string& line) -> void {
142 string name;
143 uint64_t iNode = 0;
144 if (StringUtils::GetInstance().IsEnd(line, "B")) {
145 string type;
146 uint64_t value = 0;
147 if (GetSmapsValue(memType, line, type, value)) {
148 MemoryUtil::GetInstance().CalcGroup(memGroup_, type, value, result);
149 memMap_.insert(pair<string, string>(type, to_string(value)));
150 }
151 } else if (MemoryUtil::GetInstance().IsNameLine(line, name, iNode)) {
152 memGroup_ = name;
153 if (!memMap_.empty()) {
154 vectMap.push_back(memMap_);
155 memMap_.clear();
156 }
157 if (result.find(memGroup_) != result.end()) {
158 result[memGroup_]["Counts"]++;
159 } else {
160 vector<string> datas;
161 StringUtils::GetInstance().StringSplit(line, " ", datas);
162 result[memGroup_].insert(pair<string, uint64_t>("Perm",
163 MemoryUtil::GetInstance().PermToInt(datas.at(1))));
164 result[memGroup_].insert(pair<string, uint64_t>("Counts", 1));
165 result[memGroup_].insert(pair<string, uint64_t>("Name", 0));
166 }
167 if (isShowSmapsInfo) {
168 SetMapByNameLine(memGroup_, line);
169 }
170 }
171 });
172 if (!memMap_.empty()) {
173 vectMap.push_back(memMap_);
174 memMap_.clear();
175 }
176 return ret;
177 }
178 } // namespace HiviewDFX
179 } // namespace OHOS
180