• 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 /* This files contains process dump dfx maps module. */
17 #include "dfx_maps.h"
18 
19 #include <cinttypes>
20 #include <climits>
21 #include <cstdio>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25 #include <memory>
26 #include <securec.h>
27 #include <string>
28 #include <vector>
29 #include "dfx_define.h"
30 #include "dfx_elf.h"
31 #include "dfx_log.h"
32 #include "dfx_util.h"
33 
34 namespace OHOS {
35 namespace HiviewDFX {
36 static const int MAPINFO_SIZE = 256;
37 
Create(pid_t pid)38 std::shared_ptr<DfxElfMaps> DfxElfMaps::Create(pid_t pid)
39 {
40     auto dfxElfMaps = std::make_shared<DfxElfMaps>();
41 
42     char path[NAME_LEN] = {0};
43     if (snprintf_s(path, sizeof(path), sizeof(path) - 1, "/proc/%d/maps", pid) <= 0) {
44         DfxLogWarn("Fail to print path.");
45         return nullptr;
46     }
47 
48     char realPath[PATH_MAX] = {0};
49     if (realpath(path, realPath) == nullptr) {
50         DfxLogWarn("Maps path(%s) is not exist.", path);
51         return nullptr;
52     }
53 
54     FILE *fp = fopen(realPath, "r");
55     if (fp == nullptr) {
56         DfxLogWarn("Fail to open maps info.");
57         return nullptr;
58     }
59 
60     char mapInfo[MAPINFO_SIZE] = {0};
61     while (fgets(mapInfo, sizeof(mapInfo), fp) != nullptr) {
62         std::shared_ptr<DfxElfMap> map = DfxElfMap::Create(mapInfo, sizeof(mapInfo));
63         if (!map) {
64             DfxLogWarn("Fail to init map info:%s.", mapInfo);
65             continue;
66         } else {
67             dfxElfMaps->InsertMapToElfMaps(map);
68         }
69     }
70     int ret = fclose(fp);
71     if (ret < 0) {
72         DfxLogWarn("Fail to close maps info.");
73         return nullptr;
74     }
75     return dfxElfMaps;
76 }
77 
Create(const std::string mapInfo,int size)78 std::shared_ptr<DfxElfMap> DfxElfMap::Create(const std::string mapInfo, int size)
79 {
80     auto dfxElfMap = std::make_shared<DfxElfMap>();
81 
82     int pos = 0;
83     uint64_t begin = 0;
84     uint64_t end = 0;
85     uint64_t offset = 0;
86     char perms[5] = {0}; // 5:rwxp
87     std::string path = "";
88 
89     // 7658d38000-7658d40000 rw-p 00000000 00:00 0                              [anon:thread signal stack]
90     if (sscanf_s(mapInfo.c_str(), "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %*x:%*x %*d%n", &begin, &end,
91         &perms, sizeof(perms), &offset,
92         &pos) != 4) { // 4:scan size
93         DfxLogWarn("Fail to parse maps info.");
94         return nullptr;
95     }
96 
97     dfxElfMap->SetMapBegin(begin);
98     dfxElfMap->SetMapEnd(end);
99     dfxElfMap->SetMapOffset(offset);
100     dfxElfMap->SetMapPerms(perms, sizeof(perms));
101     TrimAndDupStr(mapInfo.substr(pos), path);
102     dfxElfMap->SetMapPath(path);
103     return dfxElfMap;
104 }
105 
InsertMapToElfMaps(std::shared_ptr<DfxElfMap> map)106 void DfxElfMaps::InsertMapToElfMaps(std::shared_ptr<DfxElfMap> map)
107 {
108     maps_.push_back(map);
109     return;
110 }
111 
112 
FindMapByPath(const std::string path,std::shared_ptr<DfxElfMap> & map) const113 bool DfxElfMaps::FindMapByPath(const std::string path, std::shared_ptr<DfxElfMap>& map) const
114 {
115     for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
116         if ((*iter)->GetMapPath() == "") {
117             continue;
118         }
119 
120         if (strcmp(path.c_str(), (*iter)->GetMapPath().c_str()) == 0) {
121             map = *iter;
122             return true;
123         }
124     }
125     return false;
126 }
127 
FindMapByAddr(uintptr_t address,std::shared_ptr<DfxElfMap> & map) const128 bool DfxElfMaps::FindMapByAddr(uintptr_t address, std::shared_ptr<DfxElfMap>& map) const
129 {
130     for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
131         if (((*iter)->GetMapBegin() < address) && ((*iter)->GetMapEnd() > address)) {
132             map = *iter;
133             return true;
134         }
135     }
136     return false;
137 }
138 
CheckPcIsValid(uint64_t pc) const139 bool DfxElfMaps::CheckPcIsValid(uint64_t pc) const
140 {
141     DfxLogDebug("%s :: pc(0x%x).", __func__, pc);
142 
143     bool ret = false;
144 
145     do {
146         if (pc == 0x0) {
147             break;
148         }
149 
150         std::shared_ptr<DfxElfMap> map = nullptr;
151         for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
152             if (((*iter)->GetMapBegin() < pc) && ((*iter)->GetMapEnd() > pc)) {
153                 map = *iter;
154                 break;
155             }
156         }
157 
158         if (map != nullptr) {
159             std::string perms = map->GetMapPerms();
160             if (perms.find("x") != std::string::npos) {
161                 ret = true;
162             }
163         }
164     } while (false);
165 
166     DfxLogDebug("%s :: ret(%d).", __func__, ret);
167     return ret;
168 }
169 
IsValid()170 bool DfxElfMap::IsValid()
171 {
172     if (path_.length() == 0) {
173         return false;
174     }
175 
176     if (strncmp(path_.c_str(), "/dev/", 5) == 0) { // 5:length of "/dev/"
177         return false;
178     }
179 
180     if (strncmp(path_.c_str(), "[anon:", 6) == 0) { // 6:length of "[anon:"
181         return false;
182     }
183 
184     if (strncmp(path_.c_str(), "/system/framework/", 18) == 0) { // 18:length of "/system/framework/"
185         return false;
186     }
187     return true;
188 }
189 
PrintMap()190 std::string DfxElfMap::PrintMap()
191 {
192     char buf[LOG_BUF_LEN] = {0};
193     int ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%" PRIx64 "-%" PRIx64 " %s %08" PRIx64 " %s\n", \
194         begin_, end_, perms_.c_str(), offset_, path_.c_str());
195     if (ret <= 0) {
196         DfxLogError("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
197     }
198     return std::string(buf);
199 }
200 
GetMapBegin() const201 uint64_t DfxElfMap::GetMapBegin() const
202 {
203     return begin_;
204 }
205 
GetMapEnd() const206 uint64_t DfxElfMap::GetMapEnd() const
207 {
208     return end_;
209 }
210 
GetMapOffset() const211 uint64_t DfxElfMap::GetMapOffset() const
212 {
213     return offset_;
214 }
215 
GetMapPerms() const216 std::string DfxElfMap::GetMapPerms() const
217 {
218     return perms_;
219 }
220 
GetMapPath() const221 std::string DfxElfMap::GetMapPath() const
222 {
223     return path_;
224 }
225 
GetMapImage() const226 std::shared_ptr<DfxElf> DfxElfMap::GetMapImage() const
227 {
228     return image_;
229 }
230 
SetMapBegin(uint64_t begin)231 void DfxElfMap::SetMapBegin(uint64_t begin)
232 {
233     begin_ = begin;
234 }
235 
SetMapEnd(uint64_t end)236 void DfxElfMap::SetMapEnd(uint64_t end)
237 {
238     end_ = end;
239 }
240 
SetMapOffset(uint64_t offset)241 void DfxElfMap::SetMapOffset(uint64_t offset)
242 {
243     offset_ = offset;
244 }
245 
SetMapPerms(const std::string perms,int size)246 void DfxElfMap::SetMapPerms(const std::string perms, int size)
247 {
248     perms_ = perms;
249 }
250 
SetMapPath(const std::string path)251 void DfxElfMap::SetMapPath(const std::string path)
252 {
253     path_ = path;
254 }
255 
SetMapImage(std::shared_ptr<DfxElf> image)256 void DfxElfMap::SetMapImage(std::shared_ptr<DfxElf> image)
257 {
258     image_ = image;
259 }
260 
GetValues() const261 std::vector<std::shared_ptr<DfxElfMap>> DfxElfMaps::GetValues() const
262 {
263     return maps_;
264 }
265 } // namespace HiviewDFX
266 } // namespace OHOS
267