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