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