• 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 
GetRelativePc(const std::shared_ptr<DfxElfMaps> head)125 uint64_t DfxFrame::GetRelativePc(const std::shared_ptr<DfxElfMaps> head)
126 {
127     if (head == nullptr) {
128         return 0;
129     }
130 
131     if (map_ == nullptr) {
132         if (!head->FindMapByAddr(pc_, map_)) {
133             return 0;
134         }
135     }
136 
137     if (!map_->IsValid()) {
138         DfxLogWarn("No elf map:%s.", map_->GetMapPath().c_str());
139         return 0;
140     }
141 
142     std::shared_ptr<DfxElfMap> map = nullptr;
143     if (!head->FindMapByPath(map_->GetMapPath(), map)) {
144         DfxLogWarn("Fail to find Map:%s.", map_->GetMapPath().c_str());
145         return 0;
146     }
147     return CalculateRelativePc(map);
148 }
149 
CalculateRelativePc(std::shared_ptr<DfxElfMap> elfMap)150 uint64_t DfxFrame::CalculateRelativePc(std::shared_ptr<DfxElfMap> elfMap)
151 {
152     if (elfMap == nullptr || map_ == nullptr) {
153         return 0;
154     }
155 
156     if (elfMap->GetMapImage() == nullptr) {
157         elfMap->SetMapImage(DfxElf::Create(elfMap->GetMapPath().c_str()));
158     }
159 
160     if (elfMap->GetMapImage() == nullptr) {
161         relativePc_ = pc_ - (map_->GetMapBegin() - map_->GetMapOffset());
162     } else {
163         relativePc_ = (pc_ - map_->GetMapBegin()) + elfMap->GetMapImage()->FindRealLoadOffset(map_->GetMapOffset());
164     }
165 
166 #ifdef __aarch64__
167     relativePc_ = relativePc_ - 4; // 4 : instr offset
168 #elif defined(__x86_64__)
169     relativePc_ = relativePc_ - 1; // 1 : instr offset
170 #endif
171     return relativePc_;
172 }
173 
PrintFrame() const174 std::string DfxFrame::PrintFrame() const
175 {
176     char buf[LOG_BUF_LEN] = {0};
177 
178     std::string mapName = frameMapName_;
179     if (mapName.empty()) {
180         mapName = "Unknown";
181     }
182 
183 #ifdef __LP64__
184     char frameFormatWithMapName[] = "#%02zu pc %016" PRIx64 " %s\n";
185     char frameFormatWithFuncName[] = "#%02zu pc %016" PRIx64 " %s(%s+%" PRIu64 ")\n";
186 #else
187     char frameFormatWithMapName[] = "#%02zu pc %08" PRIx64 " %s\n";
188     char frameFormatWithFuncName[] = "#%02zu pc %08" PRIx64 " %s(%s+%" PRIu64 ")\n";
189 #endif
190 
191     if (funcName_.empty()) {
192         int ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, frameFormatWithMapName, \
193             index_, relativePc_, mapName.c_str());
194         if (ret <= 0) {
195             DfxLogError("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
196         }
197         return std::string(buf);
198     }
199 
200     int ret = snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, \
201         frameFormatWithFuncName, index_, relativePc_, \
202         mapName.c_str(), funcName_.c_str(), funcOffset_);
203     if (ret <= 0) {
204         DfxLogError("%s :: snprintf_s failed, line: %d.", __func__, __LINE__);
205     }
206     return std::string(buf);
207 }
208 
ToString() const209 std::string DfxFrame::ToString() const
210 {
211     char buf[1024] = "\0"; // 1024 buffer length
212 #ifdef __LP64__
213     char format[] = "#%02zu pc %016" PRIx64 " %s";
214 #else
215     char format[] = "#%02zu pc %08" PRIx64 " %s";
216 #endif
217     if (snprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format,
218         index_,
219         relativePc_,
220         frameMapName_.c_str()) <= 0) {
221         return "Unknown";
222     }
223 
224     std::ostringstream ss;
225     ss << std::string(buf, strlen(buf));
226     if (funcName_.empty()) {
227         ss << std::endl;
228     } else {
229         ss << "(";
230         ss << funcName_;
231         ss << "+" << funcOffset_ << ")" << std::endl;
232     }
233     return ss.str();
234 }
235 
PrintFrames(std::vector<std::shared_ptr<DfxFrame>> frames)236 void PrintFrames(std::vector<std::shared_ptr<DfxFrame>> frames)
237 {
238     for (size_t i = 0; i < frames.size(); i++) {
239         frames[i]->PrintFrame();
240     }
241 }
242 } // namespace HiviewDFX
243 } // namespace OHOS
244