• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2024 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 "dfx_crash_local_handler.h"
16 
17 #include <securec.h>
18 #include <csignal>
19 #include <sys/time.h>
20 #include <sys/ucontext.h>
21 #include <cinttypes>
22 #include <unistd.h>
23 #include <pthread.h>
24 #include <cerrno>
25 #include "dfx_log.h"
26 #include "dfx_cutil.h"
27 #include "dfx_signal.h"
28 #include "dfx_signalhandler_exception.h"
29 #include "faultloggerd_client.h"
30 #include "hisysevent.h"
31 #include "string_printf.h"
32 #include "unwinder.h"
33 
34 #ifdef LOG_DOMAIN
35 #undef LOG_DOMAIN
36 #define LOG_DOMAIN 0xD002D11
37 #endif
38 
39 #ifdef LOG_TAG
40 #undef LOG_TAG
41 #define LOG_TAG "DfxCrashLocalHandler"
42 #endif
43 
44 #define MAX_FRAME 64
45 #define BUF_SZ 512
46 #define MAPINFO_SIZE 256
47 #define TIME_DIV 1000
48 #define BUF_SZ_SMALL 256
49 
RequestOutputLogFile(const struct ProcessDumpRequest * request)50 static __attribute__((noinline)) int RequestOutputLogFile(const struct ProcessDumpRequest* request)
51 {
52     struct FaultLoggerdRequest faultloggerdRequest;
53     (void)memset_s(&faultloggerdRequest, sizeof(faultloggerdRequest), 0, sizeof(struct FaultLoggerdRequest));
54 
55     faultloggerdRequest.type = FaultLoggerType::CPP_CRASH;
56     faultloggerdRequest.pid = request->pid;
57     faultloggerdRequest.tid = request->tid;
58     faultloggerdRequest.time = request->timeStamp;
59     return RequestFileDescriptorEx(&faultloggerdRequest);
60 }
61 
PrintLog(int fd,const char * format,...)62 static __attribute__((noinline)) void PrintLog(int fd, const char *format, ...)
63 {
64     char buf[BUF_SZ] = {0};
65     va_list args;
66     va_start(args, format);
67     int size = vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format, args);
68     va_end(args);
69     if (size == -1) {
70         if (fd > 0) {
71             const char* error = "PrintLog vsnprintf_s fail\n";
72             (void)OHOS_TEMP_FAILURE_RETRY(write(fd, error, strlen(error)));
73         }
74         return;
75     }
76     DFXLOGE("%{public}s", buf);
77     if (fd > 0) {
78         (void)OHOS_TEMP_FAILURE_RETRY(write(fd, buf, strlen(buf)));
79     }
80 }
81 
CrashLocalUnwind(const int fd,const struct ProcessDumpRequest * request,std::string & errMessage)82 static __attribute__((noinline)) void CrashLocalUnwind(const int fd,
83                                                        const struct ProcessDumpRequest* request,
84                                                        std::string& errMessage)
85 {
86     if (request == nullptr) {
87         return;
88     }
89     std::string logContext = OHOS::HiviewDFX::StringPrintf("Tid:%d, Name:%s\n", request->tid, request->threadName);
90     OHOS::HiviewDFX::Unwinder unwind;
91     unwind.UnwindLocalWithContext(request->context);
92     logContext.append(unwind.GetFramesStr(unwind.GetFrames()));
93     errMessage += logContext;
94     auto regs = OHOS::HiviewDFX::DfxRegs::CreateFromUcontext(request->context);
95     logContext.append(regs->PrintRegs());
96     logContext.append("\nMaps:\n");
97     for (const auto &map : unwind.GetMaps()->GetMaps()) {
98         logContext.append(map->ToString());
99     }
100 
101     for (unsigned int i = 0; i < logContext.length(); i += BUF_SZ_SMALL) {
102         PrintLog(fd, "%s", logContext.substr(i, BUF_SZ_SMALL).c_str());
103     }
104 }
105 
106 // currently, only stacktrace is logged to faultloggerd
CrashLocalHandler(struct ProcessDumpRequest * request)107 void CrashLocalHandler(struct ProcessDumpRequest* request)
108 {
109     int fd = RequestOutputLogFile(request);
110     CrashLocalHandlerFd(fd, request);
111     if (fd >= 0) {
112         close(fd);
113     }
114 }
115 
PrintTimeStamp(const int fd,const struct ProcessDumpRequest * request)116 static void PrintTimeStamp(const int fd, const struct ProcessDumpRequest* request)
117 {
118     uint64_t currentTime = request->timeStamp;
119     char secBuf[BUF_SZ] = {0};
120     char printBuf[BUF_SZ] = {0};
121     time_t sec = static_cast<time_t>(currentTime / TIME_DIV);
122     uint64_t millisec = currentTime % TIME_DIV;
123     struct tm* t = localtime(&sec);
124     if (!t) {
125         return;
126     }
127     (void)strftime(secBuf, sizeof(secBuf) - 1, "%Y-%m-%d %H:%M:%S", t);
128     if (snprintf_s(printBuf, sizeof(printBuf), sizeof(printBuf) - 1,
129             "%s.%03u\n", secBuf, millisec) < 0) {
130         DFXLOGE("snprintf timestamp fail");
131         return;
132     }
133     PrintLog(fd, "Timestamp:%s", printBuf);
134 }
135 
CrashLocalHandlerFd(const int fd,struct ProcessDumpRequest * request)136 void CrashLocalHandlerFd(const int fd, struct ProcessDumpRequest* request)
137 {
138     if (request == nullptr) {
139         return;
140     }
141     PrintTimeStamp(fd, request);
142     PrintLog(fd, "Pid:%d\n", request->pid);
143     PrintLog(fd, "Uid:%d\n", request->uid);
144     PrintLog(fd, "Process name:%s\n", request->processName);
145     if (request->siginfo.si_pid == request->pid) {
146         request->siginfo.si_uid = request->uid;
147     }
148     std::string reason = OHOS::HiviewDFX::DfxSignal::PrintSignal(request->siginfo) + "\n";
149     std::string errMessage = reason;
150     PrintLog(fd, reason.c_str());
151     PrintLog(fd, "Fault thread info:\n");
152     CrashLocalUnwind(fd, request, errMessage);
153     HiSysEventWrite(
154         OHOS::HiviewDFX::HiSysEvent::Domain::RELIABILITY,
155         "CPP_CRASH_EXCEPTION",
156         OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
157         "PROCESS_NAME", request->processName,
158         "PID", request->pid,
159         "UID", request->uid,
160         "HAPPEN_TIME", request->timeStamp,
161         "ERROR_CODE", CRASH_DUMP_LOCAL_REPORT,
162         "ERROR_MSG", errMessage);
163 }
164