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