1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2023-2024 Huawei Device Co., Ltd. 3800b99b8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4800b99b8Sopenharmony_ci * you may not use this file except in compliance with the License. 5800b99b8Sopenharmony_ci * You may obtain a copy of the License at 6800b99b8Sopenharmony_ci * 7800b99b8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8800b99b8Sopenharmony_ci * 9800b99b8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10800b99b8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11800b99b8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12800b99b8Sopenharmony_ci * See the License for the specific language governing permissions and 13800b99b8Sopenharmony_ci * limitations under the License. 14800b99b8Sopenharmony_ci */ 15800b99b8Sopenharmony_ci 16800b99b8Sopenharmony_ci#include "printer.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cinttypes> 19800b99b8Sopenharmony_ci#include <dlfcn.h> 20800b99b8Sopenharmony_ci#include <map> 21800b99b8Sopenharmony_ci#include <string> 22800b99b8Sopenharmony_ci#include <fcntl.h> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci 25800b99b8Sopenharmony_ci#include "dfx_config.h" 26800b99b8Sopenharmony_ci#include "dfx_frame_formatter.h" 27800b99b8Sopenharmony_ci#include "dfx_logger.h" 28800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h" 29800b99b8Sopenharmony_ci#include "dfx_signal.h" 30800b99b8Sopenharmony_ci#include "dfx_util.h" 31800b99b8Sopenharmony_ci#include "string_printf.h" 32800b99b8Sopenharmony_ci#include "string_util.h" 33800b99b8Sopenharmony_ci#ifndef is_ohos_lite 34800b99b8Sopenharmony_ci#include "parameter.h" 35800b99b8Sopenharmony_ci#include "parameters.h" 36800b99b8Sopenharmony_ci#endif 37800b99b8Sopenharmony_ci 38800b99b8Sopenharmony_ci#ifndef PAGE_SIZE 39800b99b8Sopenharmony_ciconstexpr size_t PAGE_SIZE = 4096; 40800b99b8Sopenharmony_ci#endif 41800b99b8Sopenharmony_ci 42800b99b8Sopenharmony_cinamespace OHOS { 43800b99b8Sopenharmony_cinamespace HiviewDFX { 44800b99b8Sopenharmony_civoid Printer::PrintDumpHeader(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process, 45800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder) 46800b99b8Sopenharmony_ci{ 47800b99b8Sopenharmony_ci if (process == nullptr || request == nullptr) { 48800b99b8Sopenharmony_ci return; 49800b99b8Sopenharmony_ci } 50800b99b8Sopenharmony_ci std::string headerInfo; 51800b99b8Sopenharmony_ci bool isCrash = (request->siginfo.si_signo != SIGDUMP); 52800b99b8Sopenharmony_ci#ifndef is_ohos_lite 53800b99b8Sopenharmony_ci if (isCrash) { 54800b99b8Sopenharmony_ci std::string buildInfo = OHOS::system::GetParameter("const.product.software.version", "Unknown"); 55800b99b8Sopenharmony_ci headerInfo = "Build info:" + buildInfo + "\n"; 56800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Build info:" + buildInfo + "\n"); 57800b99b8Sopenharmony_ci } 58800b99b8Sopenharmony_ci#endif 59800b99b8Sopenharmony_ci headerInfo += "Timestamp:" + GetCurrentTimeStr(request->timeStamp); 60800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Timestamp:" + GetCurrentTimeStr(request->timeStamp)); 61800b99b8Sopenharmony_ci headerInfo += "Pid:" + std::to_string(process->processInfo_.pid) + "\n" + 62800b99b8Sopenharmony_ci "Uid:" + std::to_string(process->processInfo_.uid) + "\n" + 63800b99b8Sopenharmony_ci "Process name:" + process->processInfo_.processName + "\n"; 64800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("Pid:%d\n", process->processInfo_.pid); 65800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("Uid:%d\n", process->processInfo_.uid); 66800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("Process name:%s\n", process->processInfo_.processName.c_str()); 67800b99b8Sopenharmony_ci if (isCrash) { 68800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("Process life time:%s\n", 69800b99b8Sopenharmony_ci DfxProcess::GetProcessLifeCycle(process->processInfo_.pid).c_str()); 70800b99b8Sopenharmony_ci 71800b99b8Sopenharmony_ci std::string reasonInfo; 72800b99b8Sopenharmony_ci PrintReason(request, process, unwinder, reasonInfo); 73800b99b8Sopenharmony_ci headerInfo += reasonInfo + "\n"; 74800b99b8Sopenharmony_ci auto msg = process->GetFatalMessage(); 75800b99b8Sopenharmony_ci if (!msg.empty()) { 76800b99b8Sopenharmony_ci headerInfo += "LastFatalMessage:" + msg + "\n"; 77800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("LastFatalMessage:%s\n", msg.c_str()); 78800b99b8Sopenharmony_ci } 79800b99b8Sopenharmony_ci 80800b99b8Sopenharmony_ci auto traceId = request->traceInfo; 81800b99b8Sopenharmony_ci if (traceId.chainId != 0) { 82800b99b8Sopenharmony_ci headerInfo += StringPrintf("TraceId:%" PRIX64"\n", traceId.chainId); 83800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("TraceId:%llx\n", 84800b99b8Sopenharmony_ci static_cast<unsigned long long>(traceId.chainId)); 85800b99b8Sopenharmony_ci } 86800b99b8Sopenharmony_ci 87800b99b8Sopenharmony_ci headerInfo += "Fault thread info:\n"; 88800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Fault thread info:\n"); 89800b99b8Sopenharmony_ci } 90800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBaseInfo(headerInfo); 91800b99b8Sopenharmony_ci} 92800b99b8Sopenharmony_ci 93800b99b8Sopenharmony_cistatic void FillReasonAccordingMsgType(const ProcessDumpRequest &request, std::string& reason) 94800b99b8Sopenharmony_ci{ 95800b99b8Sopenharmony_ci switch (request.msg.type) { 96800b99b8Sopenharmony_ci case MESSAGE_FDSAN_DEBUG: 97800b99b8Sopenharmony_ci reason += "DEBUG SIGNAL(FDSAN)"; 98800b99b8Sopenharmony_ci break; 99800b99b8Sopenharmony_ci case MESSAGE_JEMALLOC: 100800b99b8Sopenharmony_ci reason += "DEBUG SIGNAL(JEMALLOC)"; 101800b99b8Sopenharmony_ci break; 102800b99b8Sopenharmony_ci case MESSAGE_BADFD: 103800b99b8Sopenharmony_ci reason += "DEBUG SIGNAL(BADFD)"; 104800b99b8Sopenharmony_ci break; 105800b99b8Sopenharmony_ci default: 106800b99b8Sopenharmony_ci reason += DfxSignal::PrintSignal(request.siginfo); 107800b99b8Sopenharmony_ci break; 108800b99b8Sopenharmony_ci } 109800b99b8Sopenharmony_ci} 110800b99b8Sopenharmony_ci 111800b99b8Sopenharmony_civoid Printer::PrintReason(std::shared_ptr<ProcessDumpRequest> request, std::shared_ptr<DfxProcess> process, 112800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder, std::string& reasonInfo) 113800b99b8Sopenharmony_ci{ 114800b99b8Sopenharmony_ci reasonInfo += "Reason:"; 115800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Reason:"); 116800b99b8Sopenharmony_ci if (process == nullptr) { 117800b99b8Sopenharmony_ci DFXLOGW("process is nullptr"); 118800b99b8Sopenharmony_ci return; 119800b99b8Sopenharmony_ci } 120800b99b8Sopenharmony_ci FillReasonAccordingMsgType(*request, process->reason); 121800b99b8Sopenharmony_ci uint64_t addr = (uint64_t)(request->siginfo.si_addr); 122800b99b8Sopenharmony_ci if (request->siginfo.si_signo == SIGSEGV && 123800b99b8Sopenharmony_ci (request->siginfo.si_code == SEGV_MAPERR || request->siginfo.si_code == SEGV_ACCERR)) { 124800b99b8Sopenharmony_ci if (addr < PAGE_SIZE) { 125800b99b8Sopenharmony_ci process->reason += " probably caused by NULL pointer dereference\n"; 126800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason); 127800b99b8Sopenharmony_ci reasonInfo += process->reason; 128800b99b8Sopenharmony_ci return; 129800b99b8Sopenharmony_ci } 130800b99b8Sopenharmony_ci bool keyThreadEmpty = (request->dumpMode == SPLIT_MODE && process->vmThread_ == nullptr) || 131800b99b8Sopenharmony_ci process->keyThread_ == nullptr; 132800b99b8Sopenharmony_ci if (unwinder == nullptr || keyThreadEmpty) { 133800b99b8Sopenharmony_ci DFXLOGW("%{public}s is nullptr", unwinder == nullptr ? "unwinder" : "keyThread_"); 134800b99b8Sopenharmony_ci return; 135800b99b8Sopenharmony_ci } 136800b99b8Sopenharmony_ci std::shared_ptr<DfxMaps> maps = unwinder->GetMaps(); 137800b99b8Sopenharmony_ci std::vector<std::shared_ptr<DfxMap>> map; 138800b99b8Sopenharmony_ci if (DfxRegs::CreateFromUcontext(request->context) == nullptr) { 139800b99b8Sopenharmony_ci DFXLOGW("regs is nullptr"); 140800b99b8Sopenharmony_ci return; 141800b99b8Sopenharmony_ci } 142800b99b8Sopenharmony_ci std::string elfName = StringPrintf("[anon:stack:%d]", process->keyThread_->threadInfo_.tid); 143800b99b8Sopenharmony_ci if (maps != nullptr && maps->FindMapsByName(elfName, map)) { 144800b99b8Sopenharmony_ci if (map[0] != nullptr && (addr < map[0]->begin && map[0]->begin - addr <= PAGE_SIZE)) { 145800b99b8Sopenharmony_ci process->reason += StringPrintf( 146800b99b8Sopenharmony_ci " current thread stack low address = %" PRIX64_ADDR ", probably caused by stack-buffer-overflow", 147800b99b8Sopenharmony_ci map[0]->begin); 148800b99b8Sopenharmony_ci } 149800b99b8Sopenharmony_ci } 150800b99b8Sopenharmony_ci } else if (request->siginfo.si_signo == SIGSYS && request->siginfo.si_code == SYS_SECCOMP) { 151800b99b8Sopenharmony_ci process->reason += StringPrintf(" syscall number is %d", request->siginfo.si_syscall); 152800b99b8Sopenharmony_ci } 153800b99b8Sopenharmony_ci process->reason += "\n"; 154800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(process->reason); 155800b99b8Sopenharmony_ci reasonInfo += process->reason; 156800b99b8Sopenharmony_ci} 157800b99b8Sopenharmony_ci 158800b99b8Sopenharmony_civoid Printer::PrintProcessMapsByConfig(std::shared_ptr<DfxMaps> maps) 159800b99b8Sopenharmony_ci{ 160800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayMaps) { 161800b99b8Sopenharmony_ci if (maps == nullptr) { 162800b99b8Sopenharmony_ci return; 163800b99b8Sopenharmony_ci } 164800b99b8Sopenharmony_ci auto mapsVec = maps->GetMaps(); 165800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("\nMaps:\n"); 166800b99b8Sopenharmony_ci for (auto iter = mapsVec.begin(); iter != mapsVec.end() && (*iter) != nullptr; iter++) { 167800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg((*iter)->ToString()); 168800b99b8Sopenharmony_ci } 169800b99b8Sopenharmony_ci } 170800b99b8Sopenharmony_ci} 171800b99b8Sopenharmony_ci 172800b99b8Sopenharmony_civoid Printer::PrintOtherThreadHeaderByConfig() 173800b99b8Sopenharmony_ci{ 174800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayBacktrace) { 175800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Other thread info:\n"); 176800b99b8Sopenharmony_ci } 177800b99b8Sopenharmony_ci} 178800b99b8Sopenharmony_ci 179800b99b8Sopenharmony_civoid Printer::PrintThreadHeaderByConfig(std::shared_ptr<DfxThread> thread, bool isKeyThread) 180800b99b8Sopenharmony_ci{ 181800b99b8Sopenharmony_ci std::string headerInfo; 182800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayBacktrace && thread != nullptr) { 183800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBuf("Tid:%d, Name:%s\n",\ 184800b99b8Sopenharmony_ci thread->threadInfo_.tid, thread->threadInfo_.threadName.c_str()); 185800b99b8Sopenharmony_ci headerInfo = "Tid:" + std::to_string(thread->threadInfo_.tid) + 186800b99b8Sopenharmony_ci ", Name:" + thread->threadInfo_.threadName + "\n"; 187800b99b8Sopenharmony_ci } 188800b99b8Sopenharmony_ci if (isKeyThread) { 189800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBaseInfo(headerInfo); 190800b99b8Sopenharmony_ci } 191800b99b8Sopenharmony_ci} 192800b99b8Sopenharmony_ci 193800b99b8Sopenharmony_cibool Printer::IsLastValidFrame(const DfxFrame& frame) 194800b99b8Sopenharmony_ci{ 195800b99b8Sopenharmony_ci static uintptr_t libcStartPc = 0; 196800b99b8Sopenharmony_ci static uintptr_t libffrtStartEntry = 0; 197800b99b8Sopenharmony_ci if (((libcStartPc != 0) && (frame.pc == libcStartPc)) || 198800b99b8Sopenharmony_ci ((libffrtStartEntry != 0) && (frame.pc == libffrtStartEntry))) { 199800b99b8Sopenharmony_ci return true; 200800b99b8Sopenharmony_ci } 201800b99b8Sopenharmony_ci 202800b99b8Sopenharmony_ci if (frame.mapName.find("ld-musl-aarch64.so.1") != std::string::npos && 203800b99b8Sopenharmony_ci frame.funcName.find("start") != std::string::npos) { 204800b99b8Sopenharmony_ci libcStartPc = frame.pc; 205800b99b8Sopenharmony_ci return true; 206800b99b8Sopenharmony_ci } 207800b99b8Sopenharmony_ci 208800b99b8Sopenharmony_ci if (frame.mapName.find("libffrt") != std::string::npos && 209800b99b8Sopenharmony_ci frame.funcName.find("CoStartEntry") != std::string::npos) { 210800b99b8Sopenharmony_ci libffrtStartEntry = frame.pc; 211800b99b8Sopenharmony_ci return true; 212800b99b8Sopenharmony_ci } 213800b99b8Sopenharmony_ci 214800b99b8Sopenharmony_ci return false; 215800b99b8Sopenharmony_ci} 216800b99b8Sopenharmony_ci 217800b99b8Sopenharmony_civoid Printer::PrintThreadBacktraceByConfig(std::shared_ptr<DfxThread> thread, bool isKeyThread) 218800b99b8Sopenharmony_ci{ 219800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayBacktrace && thread != nullptr) { 220800b99b8Sopenharmony_ci const auto& frames = thread->GetFrames(); 221800b99b8Sopenharmony_ci if (frames.size() == 0) { 222800b99b8Sopenharmony_ci return; 223800b99b8Sopenharmony_ci } 224800b99b8Sopenharmony_ci bool needSkip = false; 225800b99b8Sopenharmony_ci bool isSubmitter = true; 226800b99b8Sopenharmony_ci for (const auto& frame : frames) { 227800b99b8Sopenharmony_ci if (frame.index == 0) { 228800b99b8Sopenharmony_ci isSubmitter = !isSubmitter; 229800b99b8Sopenharmony_ci } 230800b99b8Sopenharmony_ci if (isSubmitter) { 231800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("========SubmitterStacktrace========\n"); 232800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBaseInfo("========SubmitterStacktrace========\n"); 233800b99b8Sopenharmony_ci isSubmitter = false; 234800b99b8Sopenharmony_ci needSkip = false; 235800b99b8Sopenharmony_ci } 236800b99b8Sopenharmony_ci if (needSkip) { 237800b99b8Sopenharmony_ci continue; 238800b99b8Sopenharmony_ci } 239800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(DfxFrameFormatter::GetFrameStr(frame)); 240800b99b8Sopenharmony_ci if (isKeyThread) { 241800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBaseInfo(DfxFrameFormatter::GetFrameStr(frame)); 242800b99b8Sopenharmony_ci } 243800b99b8Sopenharmony_ci#if defined(__aarch64__) 244800b99b8Sopenharmony_ci if (IsLastValidFrame(frame)) { 245800b99b8Sopenharmony_ci needSkip = true; 246800b99b8Sopenharmony_ci } 247800b99b8Sopenharmony_ci#endif 248800b99b8Sopenharmony_ci } 249800b99b8Sopenharmony_ci } 250800b99b8Sopenharmony_ci} 251800b99b8Sopenharmony_ci 252800b99b8Sopenharmony_civoid Printer::PrintThreadRegsByConfig(std::shared_ptr<DfxThread> thread) 253800b99b8Sopenharmony_ci{ 254800b99b8Sopenharmony_ci if (thread == nullptr) { 255800b99b8Sopenharmony_ci return; 256800b99b8Sopenharmony_ci } 257800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayRegister) { 258800b99b8Sopenharmony_ci auto regs = thread->GetThreadRegs(); 259800b99b8Sopenharmony_ci if (regs != nullptr) { 260800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs()); 261800b99b8Sopenharmony_ci } 262800b99b8Sopenharmony_ci } 263800b99b8Sopenharmony_ci} 264800b99b8Sopenharmony_ci 265800b99b8Sopenharmony_civoid Printer::PrintRegsByConfig(std::shared_ptr<DfxRegs> regs) 266800b99b8Sopenharmony_ci{ 267800b99b8Sopenharmony_ci if (regs == nullptr) { 268800b99b8Sopenharmony_ci return; 269800b99b8Sopenharmony_ci } 270800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayRegister) { 271800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(regs->PrintRegs()); 272800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendBaseInfo(regs->PrintRegs()); 273800b99b8Sopenharmony_ci } 274800b99b8Sopenharmony_ci} 275800b99b8Sopenharmony_ci 276800b99b8Sopenharmony_civoid Printer::PrintThreadFaultStackByConfig(std::shared_ptr<DfxProcess> process, std::shared_ptr<DfxThread> thread, 277800b99b8Sopenharmony_ci std::shared_ptr<Unwinder> unwinder) 278800b99b8Sopenharmony_ci{ 279800b99b8Sopenharmony_ci if (DfxConfig::GetConfig().displayFaultStack) { 280800b99b8Sopenharmony_ci if (process == nullptr || thread == nullptr) { 281800b99b8Sopenharmony_ci return; 282800b99b8Sopenharmony_ci } 283800b99b8Sopenharmony_ci thread->InitFaultStack(); 284800b99b8Sopenharmony_ci auto faultStack = thread->GetFaultStack(); 285800b99b8Sopenharmony_ci if (faultStack == nullptr) { 286800b99b8Sopenharmony_ci return; 287800b99b8Sopenharmony_ci } 288800b99b8Sopenharmony_ci if (process->regs_ == nullptr) { 289800b99b8Sopenharmony_ci DFXLOGE("process regs is nullptr"); 290800b99b8Sopenharmony_ci return; 291800b99b8Sopenharmony_ci } 292800b99b8Sopenharmony_ci faultStack->CollectRegistersBlock(process->regs_, unwinder->GetMaps()); 293800b99b8Sopenharmony_ci faultStack->Print(); 294800b99b8Sopenharmony_ci } 295800b99b8Sopenharmony_ci} 296800b99b8Sopenharmony_ci 297800b99b8Sopenharmony_civoid Printer::PrintThreadOpenFiles(std::shared_ptr<DfxProcess> process) 298800b99b8Sopenharmony_ci{ 299800b99b8Sopenharmony_ci if (process == nullptr || process->openFiles.empty()) { 300800b99b8Sopenharmony_ci return; 301800b99b8Sopenharmony_ci } 302800b99b8Sopenharmony_ci 303800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("OpenFiles:\n"); 304800b99b8Sopenharmony_ci std::string infos = process->openFiles; 305800b99b8Sopenharmony_ci constexpr size_t step = 1024; 306800b99b8Sopenharmony_ci for (size_t i = 0; i < infos.size(); i += step) { 307800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(infos.substr(i, step)); 308800b99b8Sopenharmony_ci } 309800b99b8Sopenharmony_ci} 310800b99b8Sopenharmony_ci} // namespace HiviewDFX 311800b99b8Sopenharmony_ci} // namespace OHOS 312