• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 #include "decorative_dump_info.h"
16 #include <cinttypes>
17 #include <dlfcn.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 
21 #include "dfx_buffer_writer.h"
22 #include "dfx_log.h"
23 #include "dfx_signal.h"
24 #include "dfx_util.h"
25 #include "dump_utils.h"
26 #include "crash_exception.h"
27 #include "string_printf.h"
28 #ifndef is_ohos_lite
29 #include "parameter.h"
30 #include "parameters.h"
31 #include "hitrace/hitracechainc.h"
32 #endif
33 #include "procinfo.h"
34 #include "info/fatal_message.h"
35 namespace OHOS {
36 namespace HiviewDFX {
37 namespace {
38 #ifndef PAGE_SIZE
39 constexpr size_t PAGE_SIZE = 4096;
40 #endif
41 }
42 REGISTER_DUMP_INFO_CLASS(DumpInfoHeader);
43 
Print(DfxProcess & process,const ProcessDumpRequest & request,Unwinder & unwinder)44 void DumpInfoHeader::Print(DfxProcess& process, const ProcessDumpRequest& request, Unwinder& unwinder)
45 {
46     std::string headerInfo;
47     if (request.type != ProcessDumpType::DUMP_TYPE_DUMP_CATCH) {
48 #ifndef is_ohos_lite
49         std::string buildInfo = OHOS::system::GetParameter("const.product.software.version", "Unknown");
50         headerInfo = "Build info:" + buildInfo + "\n";
51 #endif
52         headerInfo += GetCrashLogConfigInfo(request, process);
53     }
54     headerInfo += "Timestamp:" + GetCurrentTimeStr(request.timeStamp);
55     headerInfo += StringPrintf("Pid:%d\nUid:%d\n", process.GetProcessInfo().pid, process.GetProcessInfo().uid);
56 #ifndef is_ohos_lite
57     if (request.type == ProcessDumpType::DUMP_TYPE_CPP_CRASH && request.hitraceId.valid == HITRACE_ID_VALID) {
58         headerInfo += StringPrintf("HiTraceId:%" PRIx64 "\n", static_cast<uint64_t>(request.hitraceId.chainId));
59     }
60 #endif
61     headerInfo += StringPrintf("Process name:%s\n", process.GetProcessInfo().processName.c_str());
62     if (request.type != ProcessDumpType::DUMP_TYPE_DUMP_CATCH) {
63         headerInfo += ("Process life time:" + process.GetProcessLifeCycle() + "\n");
64         if (process.GetProcessLifeCycle().empty()) {
65             ReportCrashException(CrashExceptionCode::CRASH_LOG_EPROCESS_LIFECYCLE);
66         }
67         headerInfo += StringPrintf("Process Memory(kB): %" PRIu64 "(Rss)\n",
68             GetProcRssMemInfo(process.GetProcessInfo().pid));
69         headerInfo += ("Reason:" + GetReasonInfo(request, process, *unwinder.GetMaps()));
70         process.AppendFatalMessage(GetLastFatalMsg(process, request));
71         auto msg = process.GetFatalMessage();
72         if (!msg.empty()) {
73             headerInfo += "LastFatalMessage:" + msg + "\n";
74         }
75     }
76     DfxBufferWriter::GetInstance().AppendBriefDumpInfo(headerInfo);
77     DfxBufferWriter::GetInstance().WriteMsg(headerInfo);
78     DecorativeDumpInfo::Print(process, request, unwinder);
79 }
80 
GetReasonInfo(const ProcessDumpRequest & request,DfxProcess & process,DfxMaps & maps)81 std::string DumpInfoHeader::GetReasonInfo(const ProcessDumpRequest& request, DfxProcess& process, DfxMaps& maps)
82 {
83     std::string reasonInfo = DfxSignal::PrintSignal(request.siginfo);
84     do {
85         uint64_t addr = reinterpret_cast<uint64_t>(request.siginfo.si_addr);
86         if (request.siginfo.si_signo == SIGSEGV &&
87             (request.siginfo.si_code == SEGV_MAPERR || request.siginfo.si_code == SEGV_ACCERR)) {
88             if (addr < PAGE_SIZE) {
89                 reasonInfo += " probably caused by NULL pointer dereference";
90                 break;
91             }
92             if (process.GetKeyThread() == nullptr) {
93                 DFXLOGW("%{public}s is nullptr", "keyThread_");
94                 break;
95             }
96             std::vector<std::shared_ptr<DfxMap>> map;
97             std::string elfName = StringPrintf("[anon:stack:%d]", process.GetKeyThread()->GetThreadInfo().tid);
98             if (!maps.FindMapsByName(elfName, map) || map[0] == nullptr) {
99                 break;
100             }
101             if (addr < map[0]->begin && map[0]->begin - addr <= PAGE_SIZE) {
102                 reasonInfo += StringPrintf(
103                     " current thread stack low address = %" PRIX64_ADDR ", probably caused by stack-buffer-overflow",
104                     map[0]->begin);
105             }
106         } else if (request.siginfo.si_signo == SIGSYS && request.siginfo.si_code == SYS_SECCOMP) {
107             reasonInfo += StringPrintf(" syscall number is %d", request.siginfo.si_syscall);
108         }
109     } while (false);
110     reasonInfo += "\n";
111     process.SetReason(reasonInfo);
112     return reasonInfo;
113 }
114 
GetCrashLogConfigInfo(const ProcessDumpRequest & request,DfxProcess & process)115 std::string DumpInfoHeader::GetCrashLogConfigInfo(const ProcessDumpRequest& request, DfxProcess& process)
116 {
117     constexpr uint32_t extendPcLrMask = 0x1;
118     constexpr uint32_t simplifyVmaMask = 0x2;
119     CrashLogConfig crashLogConfig;
120     std::string crashLogConfigInfo;
121     if ((request.crashLogConfig & extendPcLrMask) == extendPcLrMask) {
122         crashLogConfig.extendPcLrPrinting = true;
123         crashLogConfigInfo += "Extend pc lr printing:true\n";
124     }
125     // 32 : cutoff size start from high 32 bit
126     uint32_t logFileCutoffSizeBytes = static_cast<uint32_t>(request.crashLogConfig >> 32);
127     if (logFileCutoffSizeBytes != 0) {
128         crashLogConfig.logFileCutoffSizeBytes = logFileCutoffSizeBytes;
129         crashLogConfigInfo += StringPrintf("Log cut off size:%" PRIu32 "B\n", crashLogConfig.logFileCutoffSizeBytes);
130     }
131     if ((request.crashLogConfig & simplifyVmaMask) == simplifyVmaMask) {
132         crashLogConfig.simplifyVmaPrinting = true;
133         crashLogConfigInfo += "Simplify maps printing:true\n";
134     }
135     if (!crashLogConfigInfo.empty()) {
136         crashLogConfigInfo = "Enabled app log configs:\n" + crashLogConfigInfo;
137     }
138     process.SetCrashLogConfig(crashLogConfig);
139     return crashLogConfigInfo;
140 }
141 
GetLastFatalMsg(DfxProcess & process,const ProcessDumpRequest & request)142 std::string DumpInfoHeader::GetLastFatalMsg(DfxProcess& process, const ProcessDumpRequest& request)
143 {
144     std::string lastFatalMsg = "";
145     if (request.msg.type == MESSAGE_FATAL || request.msg.type == MESSAGE_CALLBACK) {
146         lastFatalMsg += request.msg.body;
147     }
148     lastFatalMsg += UpdateFatalMessageWhenDebugSignal(process, request);
149     lastFatalMsg += ReadCrashObjString(request);
150     return lastFatalMsg;
151 }
152 
ReadCrashObjString(const ProcessDumpRequest & request) const153 std::string DumpInfoHeader::ReadCrashObjString(const ProcessDumpRequest& request) const
154 {
155     std::string content = "";
156 #ifdef __LP64__
157     if (request.type != ProcessDumpType::DUMP_TYPE_CPP_CRASH || request.crashObj == 0) {
158         DFXLOGI("crash obj not int.");
159         return content;
160     }
161     uintptr_t type = request.crashObj >> 56; // 56 :: Move 56 bit to the right
162     uintptr_t addr = request.crashObj & 0xffffffffffffff;
163     std::vector<size_t> memorylengthTable = {0, 64, 256, 1024, 2048, 4096};
164     if (type == 0) {
165         DFXLOGI("Start read string type of crashObj.");
166         constexpr int bufLen = 256;
167         content = DumpUtils::ReadStringByPtrace(request.nsPid, addr, sizeof(long) * bufLen);
168     }
169 #endif
170     return content;
171 }
172 
UpdateFatalMessageWhenDebugSignal(DfxProcess & process,const ProcessDumpRequest & request)173 std::string DumpInfoHeader::UpdateFatalMessageWhenDebugSignal(DfxProcess& process, const ProcessDumpRequest& request)
174 {
175     if (request.type != ProcessDumpType::DUMP_TYPE_BADFD && request.type != ProcessDumpType::DUMP_TYPE_FDSAN &&
176         request.type != ProcessDumpType::DUMP_TYPE_JEMALLOC) {
177         return "";
178     }
179     pid_t pid = process.GetVmPid() != 0 ? process.GetVmPid() : request.nsPid;
180     if (pid == 0) {
181         DFXLOGE("invalid pid, return directly!");
182         return "";
183     }
184 
185     auto debugMsgPtr = reinterpret_cast<uintptr_t>(request.siginfo.si_value.sival_ptr);
186     debug_msg_t dMsg = {0};
187     if (ReadProcMemByPid(pid, debugMsgPtr, &dMsg, sizeof(dMsg)) != sizeof(debug_msg_t)) {
188         DFXLOGE("Get debug_msg_t failed.");
189         return "";
190     }
191     auto msgPtr = reinterpret_cast<uintptr_t>(dMsg.msg);
192     auto debugMsg = DumpUtils::ReadStringByPtrace(pid, msgPtr, MAX_FATAL_MSG_SIZE);
193     if (debugMsg.empty()) {
194         DFXLOGE("Get debug_msg_t.msg failed.");
195         return "";
196     }
197     return debugMsg;
198 }
199 }
200 }
201