• 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             if (dfxElfMaps != nullptr) {
68                 dfxElfMaps->InsertMapToElfMaps(map);
69             }
70         }
71     }
72     int ret = fclose(fp);
73     if (ret < 0) {
74         DfxLogWarn("Fail to close maps info.");
75         return nullptr;
76     }
77     return dfxElfMaps;
78 }
79 
Create(const std::string mapInfo,int size)80 std::shared_ptr<DfxElfMap> DfxElfMap::Create(const std::string mapInfo, int size)
81 {
82     auto dfxElfMap = std::make_shared<DfxElfMap>();
83 
84     int pos = 0;
85     uint64_t begin = 0;
86     uint64_t end = 0;
87     uint64_t offset = 0;
88     char perms[5] = {0}; // 5:rwxp
89     std::string path = "";
90 
91     // 7658d38000-7658d40000 rw-p 00000000 00:00 0                              [anon:thread signal stack]
92     if (sscanf_s(mapInfo.c_str(), "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %*x:%*x %*d%n", &begin, &end,
93         &perms, sizeof(perms), &offset,
94         &pos) != 4) { // 4:scan size
95         DfxLogWarn("Fail to parse maps info.");
96         return nullptr;
97     }
98     if (dfxElfMap != nullptr) {
99         dfxElfMap->SetMapBegin(begin);
100         dfxElfMap->SetMapEnd(end);
101         dfxElfMap->SetMapOffset(offset);
102         dfxElfMap->SetMapPerms(perms, sizeof(perms));
103         TrimAndDupStr(mapInfo.substr(pos), path);
104         dfxElfMap->SetMapPath(path);
105     }
106     return dfxElfMap;
107 }
108 
InsertMapToElfMaps(std::shared_ptr<DfxElfMap> map)109 void DfxElfMaps::InsertMapToElfMaps(std::shared_ptr<DfxElfMap> map)
110 {
111     maps_.push_back(map);
112     return;
113 }
114 
115 
FindMapByPath(const std::string path,std::shared_ptr<DfxElfMap> & map) const116 bool DfxElfMaps::FindMapByPath(const std::string path, std::shared_ptr<DfxElfMap>& map) const
117 {
118     for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
119         if ((*iter)->GetMapPath() == "") {
120             continue;
121         }
122 
123         if (strcmp(path.c_str(), (*iter)->GetMapPath().c_str()) == 0) {
124             map = *iter;
125             return true;
126         }
127     }
128     return false;
129 }
130 
FindMapByAddr(uintptr_t address,std::shared_ptr<DfxElfMap> & map) const131 bool DfxElfMaps::FindMapByAddr(uintptr_t address, std::shared_ptr<DfxElfMap>& map) const
132 {
133     for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
134         if (((*iter)->GetMapBegin() < address) && ((*iter)->GetMapEnd() > address)) {
135             map = *iter;
136             return true;
137         }
138     }
139     return false;
140 }
141 
CheckPcIsValid(uint64_t pc) const142 bool DfxElfMaps::CheckPcIsValid(uint64_t pc) const
143 {
144     DfxLogDebug("%s :: pc(0x%x).", __func__, pc);
145 
146     bool ret = false;
147 
148     do {
149         if (pc == 0x0) {
150             break;
151         }
152 
153         std::shared_ptr<DfxElfMap> map = nullptr;
154         for (auto iter = maps_.begin(); iter != maps_.end(); iter++) {
155             if (((*iter)->GetMapBegin() < pc) && ((*iter)->GetMapEnd() > pc)) {
156                 map = *iter;
157                 break;
158             }
159         }
160 
161         if (map != nullptr) {
162             std::string perms = map->GetMapPerms();
163             if (perms.find("x") != std::string::npos) {
164                 ret = true;
165             }
166         }
167     } while (false);
168 
169     DfxLogDebug("%s :: ret(%d).", __func__, ret);
170     return ret;
171 }
172 
IsValid()173 bool DfxElfMap::IsValid()
174 {
175     if (path_.length() == 0) {
176         return false;
177     }
178 
179     if (strncmp(path_.c_str(), "/dev/", 5) == 0) { // 5:length of "/dev/"
180         return false;
181     }
182 
183     if (strncmp(path_.c_str(), "[anon:", 6) == 0) { // 6:length of "[anon:"
184         return false;
185     }
186 
187     if (strncmp(path_.c_str(), "/system/framework/", 18) == 0) { // 18:length of "/system/framework/"
188         return false;
189     }
190     return true;
191 }
192 
PrintMap()193 std::string DfxElfMap::PrintMap()
194 {
195     char buf[LOG_BUF_LEN] = {0};
196     int ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%" PRIx64 "-%" PRIx64 " %s %08" PRIx64 " %s\n", \
197         begin_, end_, perms_.c_str(), offset_, path_.c_str());
198     if (ret <= 0) {
199         DfxLogError("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
200     }
201     return std::string(buf);
202 }
203 
GetMapBegin() const204 uint64_t DfxElfMap::GetMapBegin() const
205 {
206     return begin_;
207 }
208 
GetMapEnd() const209 uint64_t DfxElfMap::GetMapEnd() const
210 {
211     return end_;
212 }
213 
GetMapOffset() const214 uint64_t DfxElfMap::GetMapOffset() const
215 {
216     return offset_;
217 }
218 
GetMapPerms() const219 std::string DfxElfMap::GetMapPerms() const
220 {
221     return perms_;
222 }
223 
GetMapPath() const224 std::string DfxElfMap::GetMapPath() const
225 {
226     return path_;
227 }
228 
GetMapImage() const229 std::shared_ptr<DfxElf> DfxElfMap::GetMapImage() const
230 {
231     return image_;
232 }
233 
SetMapBegin(uint64_t begin)234 void DfxElfMap::SetMapBegin(uint64_t begin)
235 {
236     begin_ = begin;
237 }
238 
SetMapEnd(uint64_t end)239 void DfxElfMap::SetMapEnd(uint64_t end)
240 {
241     end_ = end;
242 }
243 
SetMapOffset(uint64_t offset)244 void DfxElfMap::SetMapOffset(uint64_t offset)
245 {
246     offset_ = offset;
247 }
248 
SetMapPerms(const std::string perms,int size)249 void DfxElfMap::SetMapPerms(const std::string perms, int size)
250 {
251     perms_ = perms;
252 }
253 
SetMapPath(const std::string path)254 void DfxElfMap::SetMapPath(const std::string path)
255 {
256     path_ = path;
257 }
258 
SetMapImage(std::shared_ptr<DfxElf> image)259 void DfxElfMap::SetMapImage(std::shared_ptr<DfxElf> image)
260 {
261     image_ = image;
262 }
263 
GetValues() const264 std::vector<std::shared_ptr<DfxElfMap>> DfxElfMaps::GetValues() const
265 {
266     return maps_;
267 }
268 } // namespace HiviewDFX
269 } // namespace OHOS
270