• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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     bool isCrash = (request->siginfo.si_signo != SIGDUMP);
43     if (isCrash) {
44         DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr(request->timeStamp));
45     } else {
46         DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr());
47     }
48     DfxRingBufferWrapper::GetInstance().AppendBuf("Pid:%d\n", process->processInfo_.pid);
49     DfxRingBufferWrapper::GetInstance().AppendBuf("Uid:%d\n", process->processInfo_.uid);
50     DfxRingBufferWrapper::GetInstance().AppendBuf("Process name:%s\n", process->processInfo_.processName.c_str());
51 
52     if (isCrash) {
53         PrintReason(request, process, unwinder);
54         auto msg = process->GetFatalMessage();
55         if (!msg.empty()) {
56             DfxRingBufferWrapper::GetInstance().AppendBuf("LastFatalMessage:%s\n", msg.c_str());
57         }
58 
59         auto traceId = request->traceInfo;
60         if (traceId.chainId != 0) {
61             DfxRingBufferWrapper::GetInstance().AppendBuf("TraceId:%llx\n",
62                 static_cast<unsigned long long>(traceId.chainId));
63         }
64 
65         if (process->vmThread_ != nullptr) {
66             DfxRingBufferWrapper::GetInstance().AppendMsg("Fault thread Info:\n");
67         }
68     }
69 }
70 
PrintReason(std::shared_ptr<ProcessDumpRequest> request,std::shared_ptr<DfxProcess> process,std::shared_ptr<Unwinder> unwinder)71 void Printer::PrintReason(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process,
72                           std::shared_ptr<Unwinder> unwinder)
73 {
74     DfxRingBufferWrapper::GetInstance().AppendMsg("Reason:");
75     process->reason += DfxSignal::PrintSignal(request->siginfo);
76     uint64_t addr = (uint64_t)(request->siginfo.si_addr);
77     if (request->siginfo.si_signo == SIGSEGV &&
78         (request->siginfo.si_code == SEGV_MAPERR || request->siginfo.si_code == SEGV_ACCERR)) {
79         if (addr < PAGE_SIZE) {
80             process->reason += " probably caused by NULL pointer dereference\n";
81             DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
82             return;
83         }
84         std::shared_ptr<DfxMaps> maps = unwinder->GetMaps();
85         std::vector<std::shared_ptr<DfxMap>> map;
86         if (process->vmThread_ == nullptr) {
87             DFXLOG_WARN("vmThread_ is nullptr");
88             return;
89         }
90         auto regs = DfxRegs::CreateFromUcontext(request->context);
91         if (regs == nullptr) {
92             DFXLOG_WARN("regs is nullptr");
93             return;
94         }
95         std::string elfName = StringPrintf("[anon:stack:%d]", process->keyThread_->threadInfo_.tid);
96         if (maps != nullptr && maps->FindMapsByName(elfName, map)) {
97             if (addr < map[0]->begin && map[0]->begin - addr <= PAGE_SIZE) {
98                 process->reason += StringPrintf(
99 #if defined(__LP64__)
100                     " current thread stack low address = %#018lx, probably caused by stack-buffer-overflow",
101 #else
102                     " current thread stack low address = %#010llx, probably caused by stack-buffer-overflow",
103 #endif
104                     map[0]->begin);
105             }
106         }
107     }
108     process->reason += "\n";
109     DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
110 }
111 
PrintProcessMapsByConfig(std::shared_ptr<DfxMaps> maps)112 void Printer::PrintProcessMapsByConfig(std::shared_ptr<DfxMaps> maps)
113 {
114     if (DfxConfig::GetConfig().displayMaps) {
115         if (maps == nullptr) {
116             return;
117         }
118         auto mapsVec = maps->GetMaps();
119         DfxRingBufferWrapper::GetInstance().AppendMsg("\nMaps:\n");
120         for (auto iter = mapsVec.begin(); iter != mapsVec.end(); iter++) {
121             DfxRingBufferWrapper::GetInstance().AppendMsg((*iter)->ToString());
122         }
123     }
124 }
125 
PrintOtherThreadHeaderByConfig()126 void Printer::PrintOtherThreadHeaderByConfig()
127 {
128     if (DfxConfig::GetConfig().displayBacktrace) {
129         DfxRingBufferWrapper::GetInstance().AppendMsg("Other thread info:\n");
130     }
131 }
132 
PrintThreadHeaderByConfig(std::shared_ptr<DfxThread> thread)133 void Printer::PrintThreadHeaderByConfig(std::shared_ptr<DfxThread> thread)
134 {
135     if (DfxConfig::GetConfig().displayBacktrace) {
136         DfxRingBufferWrapper::GetInstance().AppendBuf("Tid:%d, Name:%s\n",\
137             thread->threadInfo_.tid, thread->threadInfo_.threadName.c_str());
138     }
139 }
140 
IsLastValidFrame(const DfxFrame & frame)141 bool Printer::IsLastValidFrame(const DfxFrame& frame)
142 {
143     static uintptr_t libcStartPc = 0;
144     static uintptr_t libffrtStartEntry = 0;
145     if (((libcStartPc != 0) && (frame.pc == libcStartPc)) ||
146         ((libffrtStartEntry != 0) && (frame.pc == libffrtStartEntry))) {
147         return true;
148     }
149 
150     if (frame.mapName.find("ld-musl-aarch64.so.1") != std::string::npos &&
151         frame.funcName.find("start") != std::string::npos) {
152         libcStartPc = frame.pc;
153         return true;
154     }
155 
156     if (frame.mapName.find("libffrt") != std::string::npos &&
157         frame.funcName.find("CoStartEntry") != std::string::npos) {
158         libffrtStartEntry = frame.pc;
159         return true;
160     }
161 
162     return false;
163 }
164 
PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)165 void Printer::PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)
166 {
167     if (DfxConfig::GetConfig().displayBacktrace) {
168         const auto& frames = thread->GetFrames();
169         if (frames.size() == 0) {
170             return;
171         }
172         bool needBreak = false;
173         for (const auto& frame : frames) {
174             DfxRingBufferWrapper::GetInstance().AppendMsg(DfxFrameFormatter::GetFrameStr(frame));
175             if (needBreak) {
176                 break;
177             }
178 #if defined(__aarch64__)
179             if (IsLastValidFrame(frame)) {
180                 needBreak = true;
181             }
182 #endif
183         }
184     }
185 }
186 
PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)187 void Printer::PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)
188 {
189     if (DfxConfig::GetConfig().displayRegister) {
190         auto regs = thread->GetThreadRegs();
191         if (regs != nullptr) {
192             DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs());
193         }
194     }
195 }
196 
PrintRegsByConfig(std::shared_ptr<DfxRegs> regs)197 void Printer::PrintRegsByConfig(std::shared_ptr<DfxRegs> regs)
198 {
199     if (regs == nullptr) {
200         return;
201     }
202     if (DfxConfig::GetConfig().displayRegister) {
203         DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs());
204     }
205 }
206 
PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process,std::shared_ptr<DfxThread> thread,std::shared_ptr<Unwinder> unwinder)207 void Printer::PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process, std::shared_ptr<DfxThread> thread,
208                                             std::shared_ptr<Unwinder> unwinder)
209 {
210     if (DfxConfig::GetConfig().displayFaultStack) {
211         if (process == nullptr) {
212             return;
213         }
214         thread->InitFaultStack();
215         auto faultStack = thread->GetFaultStack();
216         faultStack->CollectRegistersBlock(thread->GetThreadRegs(), unwinder->GetMaps());
217         faultStack->Print();
218     }
219 }
220 } // namespace HiviewDFX
221 } // namespace OHOS
222