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 processdump frame module. */
17
18 #include "dfx_frame.h"
19 #include <cinttypes>
20 #include <cstdio>
21 #include <cstring>
22 #include <memory>
23 #include <ostream>
24 #include <securec.h>
25 #include <sstream>
26 #include <string>
27 #include "dfx_define.h"
28 #include "dfx_elf.h"
29 #include "dfx_log.h"
30 #include "dfx_maps.h"
31
32 static const int FAULT_STACK_SHOW_FLOOR = 4;
33 namespace OHOS {
34 namespace HiviewDFX {
SetFrameIndex(size_t index)35 void DfxFrame::SetFrameIndex(size_t index)
36 {
37 index_ = index;
38 }
39
GetFrameIndex() const40 size_t DfxFrame::GetFrameIndex() const
41 {
42 return index_;
43 }
44
SetFrameFuncOffset(uint64_t funcOffset)45 void DfxFrame::SetFrameFuncOffset(uint64_t funcOffset)
46 {
47 funcOffset_ = funcOffset;
48 }
49
GetFrameFuncOffset() const50 uint64_t DfxFrame::GetFrameFuncOffset() const
51 {
52 return funcOffset_;
53 }
54
SetFramePc(uint64_t pc)55 void DfxFrame::SetFramePc(uint64_t pc)
56 {
57 pc_ = pc;
58 }
59
GetFramePc() const60 uint64_t DfxFrame::GetFramePc() const
61 {
62 return pc_;
63 }
64
SetFrameLr(uint64_t lr)65 void DfxFrame::SetFrameLr(uint64_t lr)
66 {
67 lr_ = lr;
68 }
69
GetFrameLr() const70 uint64_t DfxFrame::GetFrameLr() const
71 {
72 return lr_;
73 }
74
SetFrameSp(uint64_t sp)75 void DfxFrame::SetFrameSp(uint64_t sp)
76 {
77 sp_ = sp;
78 }
79
GetFrameSp() const80 uint64_t DfxFrame::GetFrameSp() const
81 {
82 return sp_;
83 }
84
SetFrameRelativePc(uint64_t relativePc)85 void DfxFrame::SetFrameRelativePc(uint64_t relativePc)
86 {
87 relativePc_ = relativePc;
88 }
89
GetFrameRelativePc() const90 uint64_t DfxFrame::GetFrameRelativePc() const
91 {
92 return relativePc_;
93 }
94
SetFrameFuncName(const std::string & funcName)95 void DfxFrame::SetFrameFuncName(const std::string &funcName)
96 {
97 funcName_ = funcName;
98 }
99
GetFrameFuncName() const100 std::string DfxFrame::GetFrameFuncName() const
101 {
102 return funcName_;
103 }
104
SetFrameMap(const std::shared_ptr<DfxElfMap> map)105 void DfxFrame::SetFrameMap(const std::shared_ptr<DfxElfMap> map)
106 {
107 map_ = map;
108 }
109
GetFrameMap() const110 std::shared_ptr<DfxElfMap> DfxFrame::GetFrameMap() const
111 {
112 return map_;
113 }
114
SetFrameMapName(const std::string & mapName)115 void DfxFrame::SetFrameMapName(const std::string &mapName)
116 {
117 frameMapName_ = mapName;
118 }
119
GetFrameMapName() const120 std::string DfxFrame::GetFrameMapName() const
121 {
122 return frameMapName_;
123 }
124
SetBuildId(const std::string & buildId)125 void DfxFrame::SetBuildId(const std::string &buildId)
126 {
127 buildId_ = buildId;
128 }
129
GetBuildId() const130 std::string DfxFrame::GetBuildId() const
131 {
132 return buildId_;
133 }
134
GetRelativePc(const std::shared_ptr<DfxElfMaps> head)135 uint64_t DfxFrame::GetRelativePc(const std::shared_ptr<DfxElfMaps> head)
136 {
137 if (head == nullptr) {
138 return 0;
139 }
140
141 if (map_ == nullptr) {
142 if (!head->FindMapByAddr(pc_, map_)) {
143 return 0;
144 }
145 }
146
147 if (!map_->IsValid()) {
148 DfxLogWarn("No elf map:%s.", map_->GetMapPath().c_str());
149 return 0;
150 }
151
152 std::shared_ptr<DfxElfMap> map = nullptr;
153 if (!head->FindMapByPath(map_->GetMapPath(), map)) {
154 DfxLogWarn("Fail to find Map:%s.", map_->GetMapPath().c_str());
155 return 0;
156 }
157 return CalculateRelativePc(map);
158 }
159
CalculateRelativePc(std::shared_ptr<DfxElfMap> elfMap)160 uint64_t DfxFrame::CalculateRelativePc(std::shared_ptr<DfxElfMap> elfMap)
161 {
162 if (elfMap == nullptr || map_ == nullptr) {
163 return 0;
164 }
165
166 if (elfMap->GetMapImage() == nullptr) {
167 elfMap->SetMapImage(DfxElf::Create(elfMap->GetMapPath().c_str()));
168 }
169
170 if (elfMap->GetMapImage() == nullptr) {
171 relativePc_ = pc_ - (map_->GetMapBegin() - map_->GetMapOffset());
172 } else {
173 relativePc_ = (pc_ - map_->GetMapBegin()) + elfMap->GetMapImage()->FindRealLoadOffset(map_->GetMapOffset());
174 }
175
176 #ifdef __aarch64__
177 relativePc_ = relativePc_ - 4; // 4 : instr offset
178 #elif defined(__x86_64__)
179 relativePc_ = relativePc_ - 1; // 1 : instr offset
180 #endif
181 return relativePc_;
182 }
183
PrintFrame() const184 std::string DfxFrame::PrintFrame() const
185 {
186 char buf[LOG_BUF_LEN] = {0};
187
188 std::string mapName = frameMapName_;
189 if (mapName.empty()) {
190 mapName = "Unknown";
191 }
192
193 #ifdef __LP64__
194 char frameFormatWithMapName[] = "#%02zu pc %016" PRIx64 " %s";
195 char frameFormatWithFuncName[] = "#%02zu pc %016" PRIx64 " %s(%s+%" PRIu64 ")";
196 #else
197 char frameFormatWithMapName[] = "#%02zu pc %08" PRIx64 " %s";
198 char frameFormatWithFuncName[] = "#%02zu pc %08" PRIx64 " %s(%s+%" PRIu64 ")";
199 #endif
200
201 int ret = 0;
202 if (funcName_.empty()) {
203 ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, frameFormatWithMapName, \
204 index_, relativePc_, mapName.c_str());
205 } else {
206 ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, \
207 frameFormatWithFuncName, index_, relativePc_, \
208 mapName.c_str(), funcName_.c_str(), funcOffset_);
209 }
210 if (ret <= 0) {
211 DfxLogError("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
212 }
213 std::ostringstream ss;
214 ss << std::string(buf, strlen(buf));
215 if (!buildId_.empty()) {
216 ss << " (" << buildId_ << ")";
217 }
218 ss << std::endl;
219 return ss.str();
220 }
221
ToString() const222 std::string DfxFrame::ToString() const
223 {
224 char buf[1024] = "\0"; // 1024 buffer length
225 #ifdef __LP64__
226 char format[] = "#%02zu pc %016" PRIx64 " %s";
227 #else
228 char format[] = "#%02zu pc %08" PRIx64 " %s";
229 #endif
230 if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format,
231 index_,
232 relativePc_,
233 frameMapName_.c_str()) <= 0) {
234 return "Unknown";
235 }
236
237 std::ostringstream ss;
238 ss << std::string(buf, strlen(buf));
239 if (!funcName_.empty()) {
240 ss << "(";
241 ss << funcName_;
242 ss << "+" << funcOffset_ << ")";
243 }
244 if (!buildId_.empty()) {
245 ss << " (" << buildId_ << ")";
246 }
247 ss << std::endl;
248 return ss.str();
249 }
250
PrintFrames(std::vector<std::shared_ptr<DfxFrame>> frames)251 void PrintFrames(std::vector<std::shared_ptr<DfxFrame>> frames)
252 {
253 for (size_t i = 0; i < frames.size(); i++) {
254 frames[i]->PrintFrame();
255 }
256 }
257 } // namespace HiviewDFX
258 } // namespace OHOS
259