1 /*
2 * Copyright (c) 2023 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 "dfx_map.h"
17
18 #include <algorithm>
19 #include <securec.h>
20 #include <sstream>
21 #if is_mingw
22 #include "dfx_nonlinux_define.h"
23 #else
24 #include <sys/mman.h>
25 #endif
26
27 #include "dfx_define.h"
28 #include "dfx_elf.h"
29 #include "dfx_log.h"
30 #include "dfx_util.h"
31 #include "string_util.h"
32
33 namespace OHOS {
34 namespace HiviewDFX {
35 namespace {
36 #undef LOG_DOMAIN
37 #undef LOG_TAG
38 #define LOG_DOMAIN 0xD002D11
39 #define LOG_TAG "DfxMap"
40 }
41
Create(const std::string buf,int size)42 std::shared_ptr<DfxMap> DfxMap::Create(const std::string buf, int size)
43 {
44 auto map = std::make_shared<DfxMap>();
45 if (map->Parse(buf, size) == false) {
46 return nullptr;
47 }
48 return map;
49 }
50
Parse(const std::string buf,int size)51 bool DfxMap::Parse(const std::string buf, int size)
52 {
53 #if is_ohos
54 uint32_t pos = 0;
55 uint64_t begin = 0;
56 uint64_t end = 0;
57 uint64_t offset = 0;
58 uint64_t major = 0;
59 uint64_t minor = 0;
60 ino_t inode = 0;
61 char perms[5] = {0}; // 5:rwxp
62
63 // 7658d38000-7658d40000 rw-p 00000000 00:00 0 [anon:thread signal stack]
64 if (sscanf_s(buf.c_str(), "%" SCNxPTR "-%" SCNxPTR " %4s %" SCNxPTR " %x:%x %" SCNxPTR " %n",
65 &begin, &end, &perms, sizeof(perms), &offset, &major, &minor, &inode, &pos) != 7) { // 7:scan size
66 DFXLOG_WARN("Fail to parse maps info.");
67 return false;
68 }
69
70 this->begin = begin;
71 this->end = end;
72 this->offset = offset;
73 this->major = major;
74 this->minor = minor;
75 this->inode = inode;
76 this->perms = std::string(perms, sizeof(perms));
77 PermsToProts(this->perms, this->prots, this->flag);
78 TrimAndDupStr(buf.substr(pos), this->name);
79 return true;
80 #else
81 return false;
82 #endif
83 }
84
IsMapExec()85 bool DfxMap::IsMapExec()
86 {
87 if ((prots & PROT_EXEC) != 0) {
88 return true;
89 }
90 return false;
91 }
92
IsArkExecutable()93 bool DfxMap::IsArkExecutable()
94 {
95 if (name.length() == 0) {
96 return false;
97 }
98
99 if ((!StartsWith(name, "[anon:ArkTS Code]")) && (!StartsWith(name, "/dev/zero")) && (!EndsWith(name, ".an"))) {
100 return false;
101 }
102
103 if (!IsMapExec()) {
104 return false;
105 }
106 LOGU("current map is ark map: %s", name.c_str());
107 return true;
108 }
109
GetRelPc(uint64_t pc)110 uint64_t DfxMap::GetRelPc(uint64_t pc)
111 {
112 if (GetElf() != nullptr) {
113 return GetElf()->GetRelPc(pc, begin, offset);
114 }
115 return (pc - begin + offset);
116 }
117
ToString()118 std::string DfxMap::ToString()
119 {
120 char buf[LINE_BUF_SIZE] = {0};
121 int ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, "%" PRIx64 "-%" PRIx64 " %s %08" PRIx64 " %s\n", \
122 begin, end, perms.c_str(), offset, name.c_str());
123 if (ret <= 0) {
124 DFXLOG_ERROR("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
125 }
126 return std::string(buf);
127 }
128
PermsToProts(const std::string perms,uint32_t & prots,uint32_t & flag)129 void DfxMap::PermsToProts(const std::string perms, uint32_t& prots, uint32_t& flag)
130 {
131 // rwxp
132 if (perms.find("r") != std::string::npos) {
133 prots |= PROT_READ;
134 }
135
136 if (perms.find("w") != std::string::npos) {
137 prots |= PROT_WRITE;
138 }
139
140 if (perms.find("x") != std::string::npos) {
141 prots |= PROT_EXEC;
142 }
143
144 if (perms.find("p") != std::string::npos) {
145 flag = MAP_PRIVATE;
146 } else if (perms.find("s") != std::string::npos) {
147 flag = MAP_SHARED;
148 }
149 }
150
GetElf()151 const std::shared_ptr<DfxElf> DfxMap::GetElf()
152 {
153 if (elf == nullptr) {
154 if (name.empty()) {
155 LOGE("Invalid map, name empty.");
156 return nullptr;
157 }
158 LOGU("GetElf name: %s", name.c_str());
159 if (EndsWith(name, ".hap")) {
160 elf = DfxElf::CreateFromHap(name, prevMap, offset);
161 } else {
162 elf = DfxElf::Create(name);
163 }
164 }
165 return elf;
166 }
167
GetElfName()168 std::string DfxMap::GetElfName()
169 {
170 if (name.empty() || GetElf() == nullptr) {
171 return name;
172 }
173 std::string soName = name;
174 if (EndsWith(name, ".hap")) {
175 soName.append("!" + elf->GetElfName());
176 }
177 return soName;
178 }
179 } // namespace HiviewDFX
180 } // namespace OHOS
181