• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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