• 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 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