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_emulator.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_format.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)39 void Printer::PrintDumpHeader(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process)
40 {
41 bool isCrash = (request->siginfo.si_signo != SIGDUMP);
42 if (isCrash) {
43 DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr(request->timeStamp));
44 } else {
45 DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr());
46 }
47 DfxRingBufferWrapper::GetInstance().AppendBuf("Pid:%d\n", process->processInfo_.pid);
48 DfxRingBufferWrapper::GetInstance().AppendBuf("Uid:%d\n", process->processInfo_.uid);
49 DfxRingBufferWrapper::GetInstance().AppendBuf("Process name:%s\n", process->processInfo_.processName.c_str());
50
51 if (isCrash) {
52 PrintReason(request, process);
53 auto msg = process->GetFatalMessage();
54 if (!msg.empty()) {
55 DfxRingBufferWrapper::GetInstance().AppendBuf("LastFatalMessage:%s\n", msg.c_str());
56 }
57
58 auto traceId = request->traceInfo;
59 if (traceId.chainId != 0) {
60 DfxRingBufferWrapper::GetInstance().AppendBuf("TraceId:%llx\n",
61 static_cast<unsigned long long>(traceId.chainId));
62 }
63
64 if (process->vmThread_ != nullptr) {
65 DfxRingBufferWrapper::GetInstance().AppendMsg("Fault thread Info:\n");
66 }
67 }
68 }
PrintReason(std::shared_ptr<ProcessDumpRequest> request,std::shared_ptr<DfxProcess> process)69 void Printer::PrintReason(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process)
70 {
71 DfxRingBufferWrapper::GetInstance().AppendMsg("Reason:");
72 process->reason += DfxSignal::PrintSignal(request->siginfo);
73 uint64_t addr = (uint64_t)(request->siginfo.si_addr);
74 process->InitProcessMaps();
75 if (request->siginfo.si_signo == SIGSEGV &&
76 (request->siginfo.si_code == SEGV_MAPERR || request->siginfo.si_code == SEGV_ACCERR)) {
77 if (addr < PAGE_SIZE) {
78 process->reason += " probably caused by NULL pointer dereference\n";
79 DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
80 return;
81 }
82 std::shared_ptr<DfxElfMaps> maps = process->GetMaps();
83 std::shared_ptr<DfxElfMap> map;
84 if (process->vmThread_ == nullptr) {
85 DFXLOG_WARN("vmThread_ is nullptr");
86 return;
87 }
88 auto regs = process->vmThread_->GetThreadRegs();
89 if (regs == nullptr) {
90 DFXLOG_WARN("regs is nullptr");
91 return;
92 }
93 uintptr_t sp = regs->sp_;
94 if (maps != nullptr && maps->FindMapByAddr(sp, map)) {
95 std::string guardMapName = StringPrintf("[anon:guard:%d]", process->keyThread_->threadInfo_.tid);
96 if ((addr < map->begin && map->begin - addr <= PAGE_SIZE) || (map->path.compare(guardMapName) == 0)) {
97 process->reason += StringPrintf(
98 #if defined(__LP64__)
99 " current thread stack low address = %#018lx, probably caused by stack-buffer-overflow",
100 #else
101 " current thread stack low address = %#010llx, probably caused by stack-buffer-overflow",
102 #endif
103 map->begin);
104 }
105 }
106 }
107 process->reason += "\n";
108 DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason);
109 }
PrintProcessMapsByConfig(std::shared_ptr<DfxProcess> process)110 void Printer::PrintProcessMapsByConfig(std::shared_ptr<DfxProcess> process)
111 {
112 if (DfxConfig::GetConfig().displayMaps) {
113 process->InitProcessMaps();
114 if (process->GetMaps() == nullptr) {
115 DFXLOG_WARN("Pid:%d maps is null", process->processInfo_.pid);
116 return;
117 }
118 DfxRingBufferWrapper::GetInstance().AppendMsg("\nMaps:\n");
119 auto maps = process->GetMaps()->GetMaps();
120 for (auto iter = maps.begin(); iter != maps.end(); iter++) {
121 DfxRingBufferWrapper::GetInstance().AppendMsg((*iter)->PrintMap());
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
PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)141 void Printer::PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread)
142 {
143 if (DfxConfig::GetConfig().displayBacktrace) {
144 const auto& frames = thread->GetFrames();
145 if (frames.size() == 0) {
146 DFXLOG_WARN("Tid:%d frame is null", thread->threadInfo_.tid);
147 return;
148 }
149 for (const auto& frame : frames) {
150 DfxRingBufferWrapper::GetInstance().AppendMsg(DfxFrameFormat::GetFrameStr(frame));
151 }
152 }
153 }
154
PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)155 void Printer::PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread)
156 {
157 if (DfxConfig::GetConfig().displayRegister) {
158 std::shared_ptr<DfxRegs> regs = thread->GetThreadRegs();
159 if (regs != nullptr) {
160 DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs());
161 }
162 }
163 }
164
PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process,std::shared_ptr<DfxThread> thread)165 void Printer::PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process, std::shared_ptr<DfxThread> thread)
166 {
167 if (DfxConfig::GetConfig().displayFaultStack) {
168 if (process == nullptr) {
169 return;
170 }
171 thread->InitFaultStack();
172 auto faultStack = thread->GetFaultStack();
173 process->InitProcessMaps();
174 faultStack->CollectRegistersBlock(thread->GetThreadRegs(), process->GetMaps());
175 faultStack->Print();
176 }
177 }
178 } // namespace HiviewDFX
179 } // namespace OHOS
180