• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2024 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 "printer.h"
17 
18 #include <cinttypes>
19 #include <dlfcn.h>
20 #include <map>
21 #include <string>
22 #include <fcntl.h>
23 #include <unistd.h>
24 
25 #include "dfx_config.h"
26 #include "dfx_frame_formatter.h"
27 #include "dfx_logger.h"
28 #include "dfx_ring_buffer_wrapper.h"
29 #include "dfx_signal.h"
30 #include "dfx_util.h"
31 #include "string_util.h"
32 
33 #ifndef PAGE_SIZE
34 constexpr size_t PAGE_SIZE = 4096;
35 #endif
36 
37 namespace OHOS {
38 namespace HiviewDFX {
PrintDumpHeader(std::shared_ptr<ProcessDumpRequest> request,std::shared_ptr<DfxProcess> process,std::shared_ptr<Unwinder> unwinder)39 void Printer::PrintDumpHeader(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process,
40                               std::shared_ptr<Unwinder> unwinder)
41 {
42     if (process == nullptr || request == nullptr) {
43         return;
44     }
45     std::stringstream headerInfo;
46     bool isCrash = (request->siginfo.si_signo != SIGDUMP);
47     if (isCrash) {
48         headerInfo << "Timestamp:" << GetCurrentTimeStr(request->timeStamp);
49         DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr(request->timeStamp));
50     } else {
51         headerInfo << "Timestamp:" << GetCurrentTimeStr();
52         DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr());
53     }
54     headerInfo << "Pid:" << process->processInfo_.pid << "\n" <<
55                   "Uid:" << process->processInfo_.uid << "\n" <<
56                   "Process name:" << process->processInfo_.processName << "\n";
57     DfxRingBufferWrapper::GetInstance().AppendBuf("Pid:%d\n", process->processInfo_.pid);
58     DfxRingBufferWrapper::GetInstance().AppendBuf("Uid:%d\n", process->processInfo_.uid);
59     DfxRingBufferWrapper::GetInstance().AppendBuf("Process name:%s\n", process->processInfo_.processName.c_str());
60     if (isCrash) {
61         DfxRingBufferWrapper::GetInstance().AppendBuf("Process life time:%s\n",
62             DfxProcess::GetProcessLifeCycle(process->processInfo_.pid).c_str());
63 
64         std::string reasonInfo;
65         PrintReason(request, process, unwinder, reasonInfo);
66         headerInfo << reasonInfo << "\n";
67         auto msg = process->GetFatalMessage();
68         if (!msg.empty()) {
69             headerInfo << "LastFatalMessage:" << msg.c_str() << "\n";
70             DfxRingBufferWrapper::GetInstance().AppendBuf("LastFatalMessage:%s\n", msg.c_str());
71         }
72 
73         auto traceId = request->traceInfo;
74         if (traceId.chainId != 0) {
75             headerInfo << "TraceId:" << std::hex << std::uppercase <<
76                           static_cast<unsigned long long>(traceId.chainId) << "\n";
77             DfxRingBufferWrapper::GetInstance().AppendBuf("TraceId:%llx\n",
78                 static_cast<unsigned long long>(traceId.chainId));
79         }
80 
81         headerInfo << "Fault thread info:\n";
82         DfxRingBufferWrapper::GetInstance().AppendMsg("Fault thread info:\n");
83     }
84     DfxRingBufferWrapper::GetInstance().AppendBaseInfo(headerInfo.str());
85 }
86 
PrintReason(std::shared_ptr<ProcessDumpRequest> request,std::shared_ptr<DfxProcess> process,std::shared_ptr<Unwinder> unwinder,std::string & reasonInfo)87 void Printer::PrintReason(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process,
88                           std::shared_ptr<Unwinder> unwinder, std::string& reasonInfo)
89 {
90     reasonInfo += "Reason:";
91     DfxRingBufferWrapper::GetInstance().AppendMsg("Reason:");
92     if (process == nullptr) {
93         DFXLOG_WARN("%s", "process is nullptr");
94         return;
95     }
96     process->reason += DfxSignal::PrintSignal(request->siginfo);
97     uint64_t addr = (uint64_t)(request->siginfo.si_addr);
98     if (request->siginfo.si_signo == SIGSEGV &&
99         (request->siginfo.si_code == SEGV_MAPERR || request->siginfo.si_code == SEGV_ACCERR)) {
100         if (addr < PAGE_SIZE) {
101             process->reason += " probably caused by NULL pointer dereference\n";
102             DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
103             reasonInfo += process->reason;
104             return;
105         }
106         if (unwinder == nullptr) {
107             DFXLOG_WARN("%s", "unwinder is nullptr");
108             return;
109         }
110         std::shared_ptr<DfxMaps> maps = unwinder->GetMaps();
111         std::vector<std::shared_ptr<DfxMap>> map;
112         if ((request->dumpMode == SPLIT_MODE && process->vmThread_ == nullptr) || process->keyThread_ == nullptr) {
113             DFXLOG_WARN("%s", "Thread_ is nullptr");
114             return;
115         }
116         auto regs = DfxRegs::CreateFromUcontext(request->context);
117         if (regs == nullptr) {
118             DFXLOG_WARN("%s", "regs is nullptr");
119             return;
120         }
121         std::string elfName = StringPrintf("[anon:stack:%d]", process->keyThread_->threadInfo_.tid);
122         if (maps != nullptr && maps->FindMapsByName(elfName, map)) {
123             if (map[0] != nullptr && (addr < map[0]->begin && map[0]->begin - addr <= PAGE_SIZE)) {
124                 process->reason += StringPrintf(
125 #if defined(__LP64__)
126                     " current thread stack low address = %#018lx, probably caused by stack-buffer-overflow",
127 #else
128                     " current thread stack low address = %#010llx, probably caused by stack-buffer-overflow",
129 #endif
130                     map[0]->begin);
131             }
132         }
133     }
134     process->reason += "\n";
135     DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
136     reasonInfo += process->reason;
137 }
138 
PrintProcessMapsByConfig(std::shared_ptr<DfxMaps> maps)139 void Printer::PrintProcessMapsByConfig(std::shared_ptr<DfxMaps> maps)
140 {
141     if (DfxConfig::GetConfig().displayMaps) {
142         if (maps == nullptr) {
143             return;
144         }
145         auto mapsVec = maps->GetMaps();
146         DfxRingBufferWrapper::GetInstance().AppendMsg("\nMaps:\n");
147         for (auto iter = mapsVec.begin(); iter != mapsVec.end() && (*iter) != nullptr; iter++) {
148             DfxRingBufferWrapper::GetInstance().AppendMsg((*iter)->ToString());
149         }
150     }
151 }
152 
PrintOtherThreadHeaderByConfig()153 void Printer::PrintOtherThreadHeaderByConfig()
154 {
155     if (DfxConfig::GetConfig().displayBacktrace) {
156         DfxRingBufferWrapper::GetInstance().AppendMsg("Other thread info:\n");
157     }
158 }
159 
PrintThreadHeaderByConfig(std::shared_ptr<DfxThread> thread)160 void Printer::PrintThreadHeaderByConfig(std::shared_ptr<DfxThread> thread)
161 {
162     std::stringstream headerInfo;
163     if (DfxConfig::GetConfig().displayBacktrace && thread != nullptr) {
164         DfxRingBufferWrapper::GetInstance().AppendBuf("Tid:%d, Name:%s\n",\
165             thread->threadInfo_.tid, thread->threadInfo_.threadName.c_str());
166         headerInfo << "Tid:" << thread->threadInfo_.tid << ", Name:" << thread->threadInfo_.threadName << "\n";
167     }
168     DfxRingBufferWrapper::GetInstance().AppendBaseInfo(headerInfo.str());
169 }
170 
IsLastValidFrame(const DfxFrame & frame)171 bool Printer::IsLastValidFrame(const DfxFrame& frame)
172 {
173     static uintptr_t libcStartPc = 0;
174     static uintptr_t libffrtStartEntry = 0;
175     if (((libcStartPc != 0) && (frame.pc == libcStartPc)) ||
176         ((libffrtStartEntry != 0) && (frame.pc == libffrtStartEntry))) {
177         return true;
178     }
179 
180     if (frame.mapName.find("ld-musl-aarch64.so.1") != std::string::npos &&
181         frame.funcName.find("start") != std::string::npos) {
182         libcStartPc = frame.pc;
183         return true;
184     }
185 
186     if (frame.mapName.find("libffrt") != std::string::npos &&
187         frame.funcName.find("CoStartEntry") != std::string::npos) {
188         libffrtStartEntry = frame.pc;
189         return true;
190     }
191 
192     return false;
193 }
194 
PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)195 void Printer::PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)
196 {
197     if (DfxConfig::GetConfig().displayBacktrace && thread != nullptr) {
198         const auto& frames = thread->GetFrames();
199         if (frames.size() == 0) {
200             return;
201         }
202         bool needSkip = false;
203         bool isSubmitter = true;
204         for (const auto& frame : frames) {
205             if (frame.index == 0) {
206                 isSubmitter = !isSubmitter;
207             }
208             if (isSubmitter) {
209                 DfxRingBufferWrapper::GetInstance().AppendMsg("========SubmitterStacktrace========\n");
210                 DfxRingBufferWrapper::GetInstance().AppendBaseInfo("========SubmitterStacktrace========\n");
211                 isSubmitter = false;
212                 needSkip = false;
213             }
214             if (needSkip) {
215                 continue;
216             }
217             DfxRingBufferWrapper::GetInstance().AppendMsg(DfxFrameFormatter::GetFrameStr(frame));
218             DfxRingBufferWrapper::GetInstance().AppendBaseInfo(DfxFrameFormatter::GetFrameStr(frame));
219 #if defined(__aarch64__)
220             if (IsLastValidFrame(frame)) {
221                 needSkip = true;
222             }
223 #endif
224         }
225     }
226 }
227 
PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)228 void Printer::PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)
229 {
230     if (thread == nullptr) {
231         return;
232     }
233     if (DfxConfig::GetConfig().displayRegister) {
234         auto regs = thread->GetThreadRegs();
235         if (regs != nullptr) {
236             DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs());
237         }
238     }
239 }
240 
PrintRegsByConfig(std::shared_ptr<DfxRegs> regs)241 void Printer::PrintRegsByConfig(std::shared_ptr<DfxRegs> regs)
242 {
243     if (regs == nullptr) {
244         return;
245     }
246     if (DfxConfig::GetConfig().displayRegister) {
247         DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs());
248         DfxRingBufferWrapper::GetInstance().AppendBaseInfo(regs->PrintRegs());
249     }
250 }
251 
PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process,std::shared_ptr<DfxThread> thread,std::shared_ptr<Unwinder> unwinder)252 void Printer::PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process, std::shared_ptr<DfxThread> thread,
253                                             std::shared_ptr<Unwinder> unwinder)
254 {
255     if (DfxConfig::GetConfig().displayFaultStack) {
256         if (process == nullptr || thread == nullptr) {
257             return;
258         }
259         thread->InitFaultStack();
260         auto faultStack = thread->GetFaultStack();
261         if (faultStack == nullptr) {
262             return;
263         }
264         faultStack->CollectRegistersBlock(thread->GetThreadRegs(), unwinder->GetMaps());
265         faultStack->Print();
266     }
267 }
268 
PrintThreadOpenFiles(std::shared_ptr<DfxProcess> process)269 void Printer::PrintThreadOpenFiles(std::shared_ptr<DfxProcess> process)
270 {
271     if (process == nullptr) {
272         return;
273     }
274 
275     DfxRingBufferWrapper::GetInstance().AppendMsg("OpenFiles:\n");
276     std::string infos = process->openFiles;
277     constexpr size_t step = 1024;
278     for (size_t i = 0; i < infos.size(); i += step) {
279         DfxRingBufferWrapper::GetInstance().AppendMsg(infos.substr(i, step));
280     }
281 }
282 } // namespace HiviewDFX
283 } // namespace OHOS
284