1800b99b8Sopenharmony_ci/*
2800b99b8Sopenharmony_ci * Copyright (c) 2021-2022 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#include "dfx_signal_handler.h"
16800b99b8Sopenharmony_ci
17800b99b8Sopenharmony_ci#ifndef _GNU_SOURCE
18800b99b8Sopenharmony_ci#define _GNU_SOURCE 1
19800b99b8Sopenharmony_ci#endif
20800b99b8Sopenharmony_ci
21800b99b8Sopenharmony_ci#include <fcntl.h>
22800b99b8Sopenharmony_ci#include <poll.h>
23800b99b8Sopenharmony_ci#include <pthread.h>
24800b99b8Sopenharmony_ci#include <sched.h>
25800b99b8Sopenharmony_ci#include <signal.h>
26800b99b8Sopenharmony_ci#include <sigchain.h>
27800b99b8Sopenharmony_ci#include <stdint.h>
28800b99b8Sopenharmony_ci#include <stdio.h>
29800b99b8Sopenharmony_ci#include <sys/capability.h>
30800b99b8Sopenharmony_ci#include <sys/mman.h>
31800b99b8Sopenharmony_ci#include <sys/prctl.h>
32800b99b8Sopenharmony_ci#include <sys/syscall.h>
33800b99b8Sopenharmony_ci#include <sys/time.h>
34800b99b8Sopenharmony_ci#include <sys/types.h>
35800b99b8Sopenharmony_ci#include <sys/uio.h>
36800b99b8Sopenharmony_ci#include <sys/wait.h>
37800b99b8Sopenharmony_ci#include <time.h>
38800b99b8Sopenharmony_ci#include <unistd.h>
39800b99b8Sopenharmony_ci#include "dfx_define.h"
40800b99b8Sopenharmony_ci#include "dfx_dump_request.h"
41800b99b8Sopenharmony_ci#include "dfx_signalhandler_exception.h"
42800b99b8Sopenharmony_ci#include "errno.h"
43800b99b8Sopenharmony_ci#include "linux/capability.h"
44800b99b8Sopenharmony_ci#include "stdbool.h"
45800b99b8Sopenharmony_ci#include "string.h"
46800b99b8Sopenharmony_ci#ifndef DFX_SIGNAL_LIBC
47800b99b8Sopenharmony_ci#include <securec.h>
48800b99b8Sopenharmony_ci#include "dfx_cutil.h"
49800b99b8Sopenharmony_ci#include "dfx_log.h"
50800b99b8Sopenharmony_ci#else
51800b99b8Sopenharmony_ci#include "musl_cutil.h"
52800b99b8Sopenharmony_ci#include "musl_log.h"
53800b99b8Sopenharmony_ci#endif
54800b99b8Sopenharmony_ci
55800b99b8Sopenharmony_ci#ifdef is_ohos_lite
56800b99b8Sopenharmony_ci#include "dfx_dumprequest.h"
57800b99b8Sopenharmony_ci#endif
58800b99b8Sopenharmony_ci
59800b99b8Sopenharmony_ci#include "info/fatal_message.h"
60800b99b8Sopenharmony_ci
61800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN
62800b99b8Sopenharmony_ci#undef LOG_DOMAIN
63800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11
64800b99b8Sopenharmony_ci#endif
65800b99b8Sopenharmony_ci
66800b99b8Sopenharmony_ci#ifdef LOG_TAG
67800b99b8Sopenharmony_ci#undef LOG_TAG
68800b99b8Sopenharmony_ci#define LOG_TAG "DfxSignalHandler"
69800b99b8Sopenharmony_ci#endif
70800b99b8Sopenharmony_ci
71800b99b8Sopenharmony_ci#if defined (__LP64__)
72800b99b8Sopenharmony_ci#define RESERVED_CHILD_STACK_SIZE (32 * 1024)  // 32K
73800b99b8Sopenharmony_ci#else
74800b99b8Sopenharmony_ci#define RESERVED_CHILD_STACK_SIZE (16 * 1024)  // 16K
75800b99b8Sopenharmony_ci#endif
76800b99b8Sopenharmony_ci
77800b99b8Sopenharmony_ci#define BOOL int
78800b99b8Sopenharmony_ci#define TRUE 1
79800b99b8Sopenharmony_ci#define FALSE 0
80800b99b8Sopenharmony_ci
81800b99b8Sopenharmony_ci#ifndef NSIG
82800b99b8Sopenharmony_ci#define NSIG 64
83800b99b8Sopenharmony_ci#endif
84800b99b8Sopenharmony_ci
85800b99b8Sopenharmony_ci#ifndef F_SETPIPE_SZ
86800b99b8Sopenharmony_ci#define F_SETPIPE_SZ 1031
87800b99b8Sopenharmony_ci#endif
88800b99b8Sopenharmony_ci
89800b99b8Sopenharmony_ci#define NUMBER_SIXTYFOUR 64
90800b99b8Sopenharmony_ci#define INHERITABLE_OFFSET 32
91800b99b8Sopenharmony_ci
92800b99b8Sopenharmony_ci#ifndef __MUSL__
93800b99b8Sopenharmony_civoid __attribute__((constructor)) InitHandler(void)
94800b99b8Sopenharmony_ci{
95800b99b8Sopenharmony_ci    DFX_InstallSignalHandler();
96800b99b8Sopenharmony_ci}
97800b99b8Sopenharmony_ci#endif
98800b99b8Sopenharmony_ci
99800b99b8Sopenharmony_cistatic struct ProcessDumpRequest g_request;
100800b99b8Sopenharmony_cistatic void *g_reservedChildStack = NULL;
101800b99b8Sopenharmony_cistatic pthread_mutex_t g_signalHandlerMutex = PTHREAD_MUTEX_INITIALIZER;
102800b99b8Sopenharmony_cistatic pthread_key_t g_crashObjKey;
103800b99b8Sopenharmony_cistatic bool g_crashObjInit = false;
104800b99b8Sopenharmony_cistatic BOOL g_hasInit = FALSE;
105800b99b8Sopenharmony_cistatic const int SIGNALHANDLER_TIMEOUT = 10000; // 10000 us
106800b99b8Sopenharmony_cistatic const int ALARM_TIME_S = 10;
107800b99b8Sopenharmony_cistatic int g_prevHandledSignal = SIGDUMP;
108800b99b8Sopenharmony_cistatic struct sigaction g_oldSigactionList[NSIG] = {};
109800b99b8Sopenharmony_cistatic char g_appRunningId[MAX_APP_RUNNING_UNIQUE_ID_LEN];
110800b99b8Sopenharmony_cienum DumpPreparationStage {
111800b99b8Sopenharmony_ci    CREATE_PIPE_FAIL = 1,
112800b99b8Sopenharmony_ci    SET_PIPE_LEN_FAIL,
113800b99b8Sopenharmony_ci    WRITE_PIPE_FAIL,
114800b99b8Sopenharmony_ci    INHERIT_CAP_FAIL,
115800b99b8Sopenharmony_ci    EXEC_FAIL,
116800b99b8Sopenharmony_ci};
117800b99b8Sopenharmony_ci
118800b99b8Sopenharmony_ciTraceInfo HiTraceGetId(void) __attribute__((weak));
119800b99b8Sopenharmony_cistatic void FillTraceIdLocked(struct ProcessDumpRequest* request)
120800b99b8Sopenharmony_ci{
121800b99b8Sopenharmony_ci    if (HiTraceGetId == NULL || request == NULL) {
122800b99b8Sopenharmony_ci        return;
123800b99b8Sopenharmony_ci    }
124800b99b8Sopenharmony_ci
125800b99b8Sopenharmony_ci    TraceInfo id = HiTraceGetId();
126800b99b8Sopenharmony_ci    memcpy(&(request->traceInfo), &id, sizeof(TraceInfo));
127800b99b8Sopenharmony_ci}
128800b99b8Sopenharmony_ci
129800b99b8Sopenharmony_ciconst char* GetLastFatalMessage(void) __attribute__((weak));
130800b99b8Sopenharmony_cifatal_msg_t *get_fatal_message(void) __attribute__((weak));
131800b99b8Sopenharmony_ci
132800b99b8Sopenharmony_citypedef struct ThreadCallbackItem {
133800b99b8Sopenharmony_ci    int32_t tid;
134800b99b8Sopenharmony_ci    ThreadInfoCallBack callback;
135800b99b8Sopenharmony_ci} ThreadCallbackItem;
136800b99b8Sopenharmony_ci
137800b99b8Sopenharmony_ci#define CALLBACK_ITEM_COUNT 32
138800b99b8Sopenharmony_cistatic ThreadCallbackItem g_callbackItems[CALLBACK_ITEM_COUNT];
139800b99b8Sopenharmony_cistatic void InitCallbackItems(void)
140800b99b8Sopenharmony_ci{
141800b99b8Sopenharmony_ci    for (int i = 0; i < CALLBACK_ITEM_COUNT; i++) {
142800b99b8Sopenharmony_ci        g_callbackItems[i].tid = -1;
143800b99b8Sopenharmony_ci        g_callbackItems[i].callback = NULL;
144800b99b8Sopenharmony_ci    }
145800b99b8Sopenharmony_ci}
146800b99b8Sopenharmony_ci
147800b99b8Sopenharmony_cistatic GetStackIdFunc g_GetStackIdFunc = NULL;
148800b99b8Sopenharmony_civoid SetAsyncStackCallbackFunc(void* func)
149800b99b8Sopenharmony_ci{
150800b99b8Sopenharmony_ci    g_GetStackIdFunc = (GetStackIdFunc)func;
151800b99b8Sopenharmony_ci}
152800b99b8Sopenharmony_ci
153800b99b8Sopenharmony_ci// caller should set to NULL before exit thread
154800b99b8Sopenharmony_civoid SetThreadInfoCallback(ThreadInfoCallBack func)
155800b99b8Sopenharmony_ci{
156800b99b8Sopenharmony_ci    int32_t currentTid = syscall(SYS_gettid);
157800b99b8Sopenharmony_ci    int32_t firstEmptySlot = -1;
158800b99b8Sopenharmony_ci    int32_t currentThreadSlot = -1;
159800b99b8Sopenharmony_ci    pthread_mutex_lock(&g_signalHandlerMutex);
160800b99b8Sopenharmony_ci    for (int i = 0; i < CALLBACK_ITEM_COUNT; i++) {
161800b99b8Sopenharmony_ci        if (firstEmptySlot == -1 && g_callbackItems[i].tid == -1) {
162800b99b8Sopenharmony_ci            firstEmptySlot = i;
163800b99b8Sopenharmony_ci        }
164800b99b8Sopenharmony_ci
165800b99b8Sopenharmony_ci        if (g_callbackItems[i].tid == currentTid) {
166800b99b8Sopenharmony_ci            currentThreadSlot = i;
167800b99b8Sopenharmony_ci            break;
168800b99b8Sopenharmony_ci        }
169800b99b8Sopenharmony_ci    }
170800b99b8Sopenharmony_ci
171800b99b8Sopenharmony_ci    int32_t targetSlot = currentThreadSlot == -1 ? firstEmptySlot : currentThreadSlot;
172800b99b8Sopenharmony_ci    if (targetSlot != -1) {
173800b99b8Sopenharmony_ci        g_callbackItems[targetSlot].tid = func == NULL ? -1 : currentTid;
174800b99b8Sopenharmony_ci        g_callbackItems[targetSlot].callback = func;
175800b99b8Sopenharmony_ci    }
176800b99b8Sopenharmony_ci    pthread_mutex_unlock(&g_signalHandlerMutex);
177800b99b8Sopenharmony_ci}
178800b99b8Sopenharmony_ci
179800b99b8Sopenharmony_cistatic ThreadInfoCallBack GetCallbackLocked()
180800b99b8Sopenharmony_ci{
181800b99b8Sopenharmony_ci    int32_t currentTid = syscall(SYS_gettid);
182800b99b8Sopenharmony_ci    for (int i = 0; i < CALLBACK_ITEM_COUNT; i++) {
183800b99b8Sopenharmony_ci        if (g_callbackItems[i].tid != currentTid) {
184800b99b8Sopenharmony_ci            continue;
185800b99b8Sopenharmony_ci        }
186800b99b8Sopenharmony_ci
187800b99b8Sopenharmony_ci        return g_callbackItems[i].callback;
188800b99b8Sopenharmony_ci    }
189800b99b8Sopenharmony_ci    return NULL;
190800b99b8Sopenharmony_ci}
191800b99b8Sopenharmony_ci
192800b99b8Sopenharmony_cistatic void FillLastFatalMessageLocked(int32_t sig)
193800b99b8Sopenharmony_ci{
194800b99b8Sopenharmony_ci    if (sig != SIGABRT) {
195800b99b8Sopenharmony_ci        return;
196800b99b8Sopenharmony_ci    }
197800b99b8Sopenharmony_ci
198800b99b8Sopenharmony_ci    const char* lastFatalMessage = NULL;
199800b99b8Sopenharmony_ci    if (get_fatal_message != NULL) {
200800b99b8Sopenharmony_ci        fatal_msg_t* fatalMsg = get_fatal_message();
201800b99b8Sopenharmony_ci        lastFatalMessage = fatalMsg == NULL ? NULL : fatalMsg->msg;
202800b99b8Sopenharmony_ci    }
203800b99b8Sopenharmony_ci
204800b99b8Sopenharmony_ci    if (lastFatalMessage == NULL && GetLastFatalMessage != NULL) {
205800b99b8Sopenharmony_ci        lastFatalMessage = GetLastFatalMessage();
206800b99b8Sopenharmony_ci    }
207800b99b8Sopenharmony_ci
208800b99b8Sopenharmony_ci    if (lastFatalMessage == NULL) {
209800b99b8Sopenharmony_ci        return;
210800b99b8Sopenharmony_ci    }
211800b99b8Sopenharmony_ci
212800b99b8Sopenharmony_ci    size_t len = strlen(lastFatalMessage);
213800b99b8Sopenharmony_ci    if (len > MAX_FATAL_MSG_SIZE) {
214800b99b8Sopenharmony_ci        DFXLOGE("Last message is longer than MAX_FATAL_MSG_SIZE");
215800b99b8Sopenharmony_ci        return;
216800b99b8Sopenharmony_ci    }
217800b99b8Sopenharmony_ci
218800b99b8Sopenharmony_ci    g_request.msg.type = MESSAGE_FATAL;
219800b99b8Sopenharmony_ci    (void)strncpy(g_request.msg.body, lastFatalMessage, sizeof(g_request.msg.body) - 1);
220800b99b8Sopenharmony_ci}
221800b99b8Sopenharmony_ci
222800b99b8Sopenharmony_cistatic bool FillMessageBodyLocked(MessageType type, debug_msg_t* dMsg)
223800b99b8Sopenharmony_ci{
224800b99b8Sopenharmony_ci    if (dMsg == NULL || dMsg->msg == NULL) {
225800b99b8Sopenharmony_ci        return true;
226800b99b8Sopenharmony_ci    }
227800b99b8Sopenharmony_ci
228800b99b8Sopenharmony_ci    if (g_request.timeStamp > dMsg->timestamp + PROCESSDUMP_TIMEOUT * NUMBER_ONE_THOUSAND) {
229800b99b8Sopenharmony_ci        DFXLOGE("The event has timed out since it was triggered");
230800b99b8Sopenharmony_ci        return false;
231800b99b8Sopenharmony_ci    }
232800b99b8Sopenharmony_ci
233800b99b8Sopenharmony_ci    g_request.msg.type = type;
234800b99b8Sopenharmony_ci    (void)strncpy(g_request.msg.body, dMsg->msg, sizeof(g_request.msg.body) - 1);
235800b99b8Sopenharmony_ci    return true;
236800b99b8Sopenharmony_ci}
237800b99b8Sopenharmony_ci
238800b99b8Sopenharmony_cistatic bool FillDebugMessageLocked(int32_t sig, siginfo_t *si)
239800b99b8Sopenharmony_ci{
240800b99b8Sopenharmony_ci    if (sig != SIGLEAK_STACK || si == NULL || si->si_signo != SIGLEAK_STACK) {
241800b99b8Sopenharmony_ci        return true;
242800b99b8Sopenharmony_ci    }
243800b99b8Sopenharmony_ci    switch (si->si_code) {
244800b99b8Sopenharmony_ci        case SIGLEAK_STACK_FDSAN: {
245800b99b8Sopenharmony_ci            return FillMessageBodyLocked(MESSAGE_FDSAN_DEBUG, (debug_msg_t*)si->si_value.sival_ptr);
246800b99b8Sopenharmony_ci        }
247800b99b8Sopenharmony_ci        case SIGLEAK_STACK_JEMALLOC: {
248800b99b8Sopenharmony_ci            return FillMessageBodyLocked(MESSAGE_JEMALLOC, (debug_msg_t*)si->si_value.sival_ptr);
249800b99b8Sopenharmony_ci        }
250800b99b8Sopenharmony_ci        case SIGLEAK_STACK_BADFD:
251800b99b8Sopenharmony_ci            g_request.msg.type = MESSAGE_BADFD;
252800b99b8Sopenharmony_ci            break;
253800b99b8Sopenharmony_ci        default:
254800b99b8Sopenharmony_ci            break;
255800b99b8Sopenharmony_ci    }
256800b99b8Sopenharmony_ci    return true;
257800b99b8Sopenharmony_ci}
258800b99b8Sopenharmony_ci
259800b99b8Sopenharmony_cistatic const char* GetCrashDescription(const int32_t errCode)
260800b99b8Sopenharmony_ci{
261800b99b8Sopenharmony_ci    size_t i;
262800b99b8Sopenharmony_ci
263800b99b8Sopenharmony_ci    for (i = 0; i < sizeof(g_crashExceptionMap) / sizeof(g_crashExceptionMap[0]); i++) {
264800b99b8Sopenharmony_ci        if (errCode == g_crashExceptionMap[i].errCode) {
265800b99b8Sopenharmony_ci            return g_crashExceptionMap[i].str;
266800b99b8Sopenharmony_ci        }
267800b99b8Sopenharmony_ci    }
268800b99b8Sopenharmony_ci    return g_crashExceptionMap[i - 1].str;    /* the end of map is "unknown reason" */
269800b99b8Sopenharmony_ci}
270800b99b8Sopenharmony_ci
271800b99b8Sopenharmony_cistatic void FillCrashExceptionAndReport(const int err)
272800b99b8Sopenharmony_ci{
273800b99b8Sopenharmony_ci    struct CrashDumpException exception;
274800b99b8Sopenharmony_ci    memset(&exception, 0, sizeof(struct CrashDumpException));
275800b99b8Sopenharmony_ci    exception.pid = g_request.pid;
276800b99b8Sopenharmony_ci    exception.uid = (int32_t)(g_request.uid);
277800b99b8Sopenharmony_ci    exception.error = err;
278800b99b8Sopenharmony_ci    exception.time = (int64_t)(GetTimeMilliseconds());
279800b99b8Sopenharmony_ci    (void)strncpy(exception.message, GetCrashDescription(err), sizeof(exception.message) - 1);
280800b99b8Sopenharmony_ci    ReportException(exception);
281800b99b8Sopenharmony_ci}
282800b99b8Sopenharmony_ci
283800b99b8Sopenharmony_cistatic bool IsDumpSignal(int sig)
284800b99b8Sopenharmony_ci{
285800b99b8Sopenharmony_ci    return sig == SIGDUMP || sig == SIGLEAK_STACK;
286800b99b8Sopenharmony_ci}
287800b99b8Sopenharmony_ci
288800b99b8Sopenharmony_cistatic bool FillDumpRequest(int sig, siginfo_t *si, void *context)
289800b99b8Sopenharmony_ci{
290800b99b8Sopenharmony_ci    memset(&g_request, 0, sizeof(g_request));
291800b99b8Sopenharmony_ci    g_request.type = sig;
292800b99b8Sopenharmony_ci    g_request.pid = GetRealPid();
293800b99b8Sopenharmony_ci    g_request.nsPid = syscall(SYS_getpid);
294800b99b8Sopenharmony_ci    g_request.tid = syscall(SYS_gettid);
295800b99b8Sopenharmony_ci    g_request.uid = getuid();
296800b99b8Sopenharmony_ci    g_request.reserved = 0;
297800b99b8Sopenharmony_ci    g_request.timeStamp = GetTimeMilliseconds();
298800b99b8Sopenharmony_ci    g_request.fdTableAddr = (uint64_t)fdsan_get_fd_table();
299800b99b8Sopenharmony_ci    memcpy(g_request.appRunningId, g_appRunningId, sizeof(g_request.appRunningId));
300800b99b8Sopenharmony_ci    if (!IsDumpSignal(sig) && g_GetStackIdFunc!= NULL) {
301800b99b8Sopenharmony_ci        g_request.stackId = g_GetStackIdFunc();
302800b99b8Sopenharmony_ci        DFXLOGI("g_GetStackIdFunc %{public}p.", (void*)g_request.stackId);
303800b99b8Sopenharmony_ci    }
304800b99b8Sopenharmony_ci
305800b99b8Sopenharmony_ci    GetThreadNameByTid(g_request.tid, g_request.threadName, sizeof(g_request.threadName));
306800b99b8Sopenharmony_ci    GetProcessName(g_request.processName, sizeof(g_request.processName));
307800b99b8Sopenharmony_ci
308800b99b8Sopenharmony_ci    memcpy(&(g_request.siginfo), si, sizeof(siginfo_t));
309800b99b8Sopenharmony_ci    memcpy(&(g_request.context), context, sizeof(ucontext_t));
310800b99b8Sopenharmony_ci
311800b99b8Sopenharmony_ci    FillTraceIdLocked(&g_request);
312800b99b8Sopenharmony_ci    bool ret = true;
313800b99b8Sopenharmony_ci    switch (sig) {
314800b99b8Sopenharmony_ci        case SIGABRT:
315800b99b8Sopenharmony_ci            FillLastFatalMessageLocked(sig);
316800b99b8Sopenharmony_ci            break;
317800b99b8Sopenharmony_ci        case SIGLEAK_STACK:
318800b99b8Sopenharmony_ci            ret = FillDebugMessageLocked(sig, si);
319800b99b8Sopenharmony_ci            /* fall-through */
320800b99b8Sopenharmony_ci        default: {
321800b99b8Sopenharmony_ci            ThreadInfoCallBack callback = GetCallbackLocked();
322800b99b8Sopenharmony_ci            if (callback != NULL) {
323800b99b8Sopenharmony_ci                DFXLOGI("Start collect crash thread info.");
324800b99b8Sopenharmony_ci                g_request.msg.type = MESSAGE_FATAL;
325800b99b8Sopenharmony_ci                callback(g_request.msg.body, sizeof(g_request.msg.body), context);
326800b99b8Sopenharmony_ci                DFXLOGI("Finish collect crash thread info.");
327800b99b8Sopenharmony_ci            }
328800b99b8Sopenharmony_ci            break;
329800b99b8Sopenharmony_ci        }
330800b99b8Sopenharmony_ci    }
331800b99b8Sopenharmony_ci    g_request.crashObj = (uintptr_t)pthread_getspecific(g_crashObjKey);
332800b99b8Sopenharmony_ci
333800b99b8Sopenharmony_ci    return ret;
334800b99b8Sopenharmony_ci}
335800b99b8Sopenharmony_ci
336800b99b8Sopenharmony_cistatic const int SIGCHAIN_DUMP_SIGNAL_LIST[] = {
337800b99b8Sopenharmony_ci    SIGDUMP, SIGLEAK_STACK
338800b99b8Sopenharmony_ci};
339800b99b8Sopenharmony_ci
340800b99b8Sopenharmony_cistatic const int SIGCHAIN_CRASH_SIGNAL_LIST[] = {
341800b99b8Sopenharmony_ci    SIGILL, SIGABRT, SIGBUS, SIGFPE,
342800b99b8Sopenharmony_ci    SIGSEGV, SIGSTKFLT, SIGSYS, SIGTRAP
343800b99b8Sopenharmony_ci};
344800b99b8Sopenharmony_ci
345800b99b8Sopenharmony_cistatic bool IsMainThread(void)
346800b99b8Sopenharmony_ci{
347800b99b8Sopenharmony_ci    if (syscall(SYS_getpid) == 1) {
348800b99b8Sopenharmony_ci        if (syscall(SYS_gettid) == 1) {
349800b99b8Sopenharmony_ci            return true;
350800b99b8Sopenharmony_ci        }
351800b99b8Sopenharmony_ci    } else {
352800b99b8Sopenharmony_ci        if (syscall(SYS_getpid) == syscall(SYS_gettid)) {
353800b99b8Sopenharmony_ci            return true;
354800b99b8Sopenharmony_ci        }
355800b99b8Sopenharmony_ci    }
356800b99b8Sopenharmony_ci    return false;
357800b99b8Sopenharmony_ci}
358800b99b8Sopenharmony_ci
359800b99b8Sopenharmony_cistatic void ResetAndRethrowSignalIfNeed(int sig, siginfo_t *si)
360800b99b8Sopenharmony_ci{
361800b99b8Sopenharmony_ci    if (IsDumpSignal(sig)) {
362800b99b8Sopenharmony_ci        return;
363800b99b8Sopenharmony_ci    }
364800b99b8Sopenharmony_ci
365800b99b8Sopenharmony_ci    if (g_oldSigactionList[sig].sa_sigaction == NULL) {
366800b99b8Sopenharmony_ci        signal(sig, SIG_DFL);
367800b99b8Sopenharmony_ci    } else if (sigaction(sig, &(g_oldSigactionList[sig]), NULL) != 0) {
368800b99b8Sopenharmony_ci        DFXLOGE("Failed to reset sig(%{public}d).", sig);
369800b99b8Sopenharmony_ci        signal(sig, SIG_DFL);
370800b99b8Sopenharmony_ci    }
371800b99b8Sopenharmony_ci
372800b99b8Sopenharmony_ci    if (syscall(SYS_rt_tgsigqueueinfo, syscall(SYS_getpid), syscall(SYS_gettid), sig, si) != 0) {
373800b99b8Sopenharmony_ci        DFXLOGE("Failed to rethrow sig(%{public}d), errno(%{public}d).", sig, errno);
374800b99b8Sopenharmony_ci    } else {
375800b99b8Sopenharmony_ci        DFXLOGI("Current process(%{public}ld) rethrow sig(%{public}d).", syscall(SYS_getpid), sig);
376800b99b8Sopenharmony_ci    }
377800b99b8Sopenharmony_ci}
378800b99b8Sopenharmony_ci
379800b99b8Sopenharmony_cistatic void PauseMainThreadHandler(int sig)
380800b99b8Sopenharmony_ci{
381800b99b8Sopenharmony_ci    DFXLOGI("Crash(%{public}d) in child thread(%{public}ld), lock main thread.", sig, syscall(SYS_gettid));
382800b99b8Sopenharmony_ci    // only work when subthread crash and send SIGDUMP to mainthread.
383800b99b8Sopenharmony_ci    pthread_mutex_lock(&g_signalHandlerMutex);
384800b99b8Sopenharmony_ci    pthread_mutex_unlock(&g_signalHandlerMutex);
385800b99b8Sopenharmony_ci    DFXLOGI("Crash in child thread(%{public}ld), exit main thread.", syscall(SYS_gettid));
386800b99b8Sopenharmony_ci}
387800b99b8Sopenharmony_ci
388800b99b8Sopenharmony_cistatic void BlockMainThreadIfNeed(int sig)
389800b99b8Sopenharmony_ci{
390800b99b8Sopenharmony_ci    if (IsMainThread() || IsDumpSignal(sig)) {
391800b99b8Sopenharmony_ci        return;
392800b99b8Sopenharmony_ci    }
393800b99b8Sopenharmony_ci
394800b99b8Sopenharmony_ci    DFXLOGI("Try block main thread.");
395800b99b8Sopenharmony_ci    (void)signal(SIGQUIT, PauseMainThreadHandler);
396800b99b8Sopenharmony_ci    if (syscall(SYS_tgkill, syscall(SYS_getpid), syscall(SYS_getpid), SIGQUIT) != 0) {
397800b99b8Sopenharmony_ci        DFXLOGE("Failed to send SIGQUIT to main thread, errno(%{public}d).", errno);
398800b99b8Sopenharmony_ci    }
399800b99b8Sopenharmony_ci}
400800b99b8Sopenharmony_ci
401800b99b8Sopenharmony_ci#ifndef is_ohos_lite
402800b99b8Sopenharmony_ciint DfxDumpRequest(int sig, struct ProcessDumpRequest *request, void *reservedChildStack) __attribute__((weak));
403800b99b8Sopenharmony_ci#endif
404800b99b8Sopenharmony_cistatic int DumpRequest(int sig)
405800b99b8Sopenharmony_ci{
406800b99b8Sopenharmony_ci    int ret = false;
407800b99b8Sopenharmony_ci    if (DfxDumpRequest == NULL) {
408800b99b8Sopenharmony_ci        DFXLOGE("DumpRequest fail, the DfxDumpRequest is NULL");
409800b99b8Sopenharmony_ci        FillCrashExceptionAndReport(CRASH_SIGNAL_EDUMPREQUEST);
410800b99b8Sopenharmony_ci        return ret;
411800b99b8Sopenharmony_ci    }
412800b99b8Sopenharmony_ci    ret = DfxDumpRequest(sig, &g_request, g_reservedChildStack);
413800b99b8Sopenharmony_ci    return ret;
414800b99b8Sopenharmony_ci}
415800b99b8Sopenharmony_ci
416800b99b8Sopenharmony_ci
417800b99b8Sopenharmony_cistatic bool DFX_SigchainHandler(int sig, siginfo_t *si, void *context)
418800b99b8Sopenharmony_ci{
419800b99b8Sopenharmony_ci    int pid = syscall(SYS_getpid);
420800b99b8Sopenharmony_ci    int tid = syscall(SYS_gettid);
421800b99b8Sopenharmony_ci
422800b99b8Sopenharmony_ci    DFXLOGW("DFX_SigchainHandler :: sig(%{public}d), pid(%{public}d), tid(%{public}d).", sig, pid, tid);
423800b99b8Sopenharmony_ci    bool ret = false;
424800b99b8Sopenharmony_ci    if (sig == SIGDUMP) {
425800b99b8Sopenharmony_ci        if (si->si_code != DUMP_TYPE_REMOTE) {
426800b99b8Sopenharmony_ci            DFXLOGW("DFX_SigchainHandler :: sig(%{public}d:%{public}d) is not remote dump type, return directly",
427800b99b8Sopenharmony_ci                sig, si->si_code);
428800b99b8Sopenharmony_ci            return true;
429800b99b8Sopenharmony_ci        }
430800b99b8Sopenharmony_ci    }
431800b99b8Sopenharmony_ci
432800b99b8Sopenharmony_ci    // crash signal should never be skipped
433800b99b8Sopenharmony_ci    pthread_mutex_lock(&g_signalHandlerMutex);
434800b99b8Sopenharmony_ci    if (!IsDumpSignal(g_prevHandledSignal)) {
435800b99b8Sopenharmony_ci        pthread_mutex_unlock(&g_signalHandlerMutex);
436800b99b8Sopenharmony_ci        return ret;
437800b99b8Sopenharmony_ci    }
438800b99b8Sopenharmony_ci    BlockMainThreadIfNeed(sig);
439800b99b8Sopenharmony_ci    g_prevHandledSignal = sig;
440800b99b8Sopenharmony_ci
441800b99b8Sopenharmony_ci    if (!FillDumpRequest(sig, si, context)) {
442800b99b8Sopenharmony_ci        pthread_mutex_unlock(&g_signalHandlerMutex);
443800b99b8Sopenharmony_ci        DFXLOGE("DFX_SigchainHandler :: signal(%{public}d) in %{public}d:%{public}d fill dump request faild.",
444800b99b8Sopenharmony_ci            sig, g_request.pid, g_request.tid);
445800b99b8Sopenharmony_ci        return sig == SIGLEAK_STACK;
446800b99b8Sopenharmony_ci    }
447800b99b8Sopenharmony_ci    DFXLOGI("DFX_SigchainHandler :: sig(%{public}d), pid(%{public}d), processName(%{public}s), threadName(%{public}s).",
448800b99b8Sopenharmony_ci        sig, g_request.pid, g_request.processName, g_request.threadName);
449800b99b8Sopenharmony_ci    ret = DumpRequest(sig);
450800b99b8Sopenharmony_ci    pthread_mutex_unlock(&g_signalHandlerMutex);
451800b99b8Sopenharmony_ci    DFXLOGW("Finish handle signal(%{public}d) in %{public}d:%{public}d.", sig, g_request.pid, g_request.tid);
452800b99b8Sopenharmony_ci    return ret;
453800b99b8Sopenharmony_ci}
454800b99b8Sopenharmony_ci
455800b99b8Sopenharmony_cistatic void DFX_SignalHandler(int sig, siginfo_t *si, void *context)
456800b99b8Sopenharmony_ci{
457800b99b8Sopenharmony_ci    DFX_SigchainHandler(sig, si, context);
458800b99b8Sopenharmony_ci    ResetAndRethrowSignalIfNeed(sig, si);
459800b99b8Sopenharmony_ci}
460800b99b8Sopenharmony_ci
461800b99b8Sopenharmony_cistatic void InstallSigActionHandler(int sig)
462800b99b8Sopenharmony_ci{
463800b99b8Sopenharmony_ci    struct sigaction action;
464800b99b8Sopenharmony_ci    memset(&action, 0, sizeof(action));
465800b99b8Sopenharmony_ci    memset(&g_oldSigactionList, 0, sizeof(g_oldSigactionList));
466800b99b8Sopenharmony_ci    sigfillset(&action.sa_mask);
467800b99b8Sopenharmony_ci    action.sa_sigaction = DFX_SignalHandler;
468800b99b8Sopenharmony_ci    action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
469800b99b8Sopenharmony_ci    if (sigaction(sig, &action, &(g_oldSigactionList[sig])) != 0) {
470800b99b8Sopenharmony_ci        DFXLOGE("Failed to register signal(%{public}d)", sig);
471800b99b8Sopenharmony_ci    }
472800b99b8Sopenharmony_ci}
473800b99b8Sopenharmony_ci
474800b99b8Sopenharmony_civoid DFX_InstallSignalHandler(void)
475800b99b8Sopenharmony_ci{
476800b99b8Sopenharmony_ci    if (g_hasInit) {
477800b99b8Sopenharmony_ci        return;
478800b99b8Sopenharmony_ci    }
479800b99b8Sopenharmony_ci
480800b99b8Sopenharmony_ci    InitCallbackItems();
481800b99b8Sopenharmony_ci    // reserve stack for fork
482800b99b8Sopenharmony_ci    g_reservedChildStack = mmap(NULL, RESERVED_CHILD_STACK_SIZE, \
483800b99b8Sopenharmony_ci        PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 1, 0);
484800b99b8Sopenharmony_ci    if (g_reservedChildStack == NULL) {
485800b99b8Sopenharmony_ci        DFXLOGE("[%{public}d]: Failed to alloc memory for child stack.", __LINE__);
486800b99b8Sopenharmony_ci        return;
487800b99b8Sopenharmony_ci    }
488800b99b8Sopenharmony_ci    g_reservedChildStack = (void *)(((uint8_t *)g_reservedChildStack) + RESERVED_CHILD_STACK_SIZE - 1);
489800b99b8Sopenharmony_ci
490800b99b8Sopenharmony_ci    struct signal_chain_action sigchain = {
491800b99b8Sopenharmony_ci        .sca_sigaction = DFX_SigchainHandler,
492800b99b8Sopenharmony_ci        .sca_mask = {},
493800b99b8Sopenharmony_ci        .sca_flags = 0,
494800b99b8Sopenharmony_ci    };
495800b99b8Sopenharmony_ci
496800b99b8Sopenharmony_ci    for (size_t i = 0; i < sizeof(SIGCHAIN_DUMP_SIGNAL_LIST) / sizeof(SIGCHAIN_DUMP_SIGNAL_LIST[0]); i++) {
497800b99b8Sopenharmony_ci        int32_t sig = SIGCHAIN_DUMP_SIGNAL_LIST[i];
498800b99b8Sopenharmony_ci        sigfillset(&sigchain.sca_mask);
499800b99b8Sopenharmony_ci        // dump signal not mask crash signal
500800b99b8Sopenharmony_ci        for (size_t j = 0; j < sizeof(SIGCHAIN_CRASH_SIGNAL_LIST) / sizeof(SIGCHAIN_CRASH_SIGNAL_LIST[0]); j++) {
501800b99b8Sopenharmony_ci            sigdelset(&sigchain.sca_mask, SIGCHAIN_CRASH_SIGNAL_LIST[j]);
502800b99b8Sopenharmony_ci        }
503800b99b8Sopenharmony_ci        add_special_handler_at_last(sig, &sigchain);
504800b99b8Sopenharmony_ci    }
505800b99b8Sopenharmony_ci    for (size_t i = 0; i < sizeof(SIGCHAIN_CRASH_SIGNAL_LIST) / sizeof(SIGCHAIN_CRASH_SIGNAL_LIST[0]); i++) {
506800b99b8Sopenharmony_ci        int32_t sig = SIGCHAIN_CRASH_SIGNAL_LIST[i];
507800b99b8Sopenharmony_ci        if (sig == SIGILL || sig == SIGSYS) {
508800b99b8Sopenharmony_ci            InstallSigActionHandler(sig);
509800b99b8Sopenharmony_ci        } else {
510800b99b8Sopenharmony_ci            sigfillset(&sigchain.sca_mask);
511800b99b8Sopenharmony_ci            add_special_handler_at_last(sig, &sigchain);
512800b99b8Sopenharmony_ci        }
513800b99b8Sopenharmony_ci    }
514800b99b8Sopenharmony_ci
515800b99b8Sopenharmony_ci    g_hasInit = TRUE;
516800b99b8Sopenharmony_ci    if (pthread_key_create(&g_crashObjKey, NULL) == 0) {
517800b99b8Sopenharmony_ci        g_crashObjInit = true;
518800b99b8Sopenharmony_ci    }
519800b99b8Sopenharmony_ci}
520800b99b8Sopenharmony_ci
521800b99b8Sopenharmony_ciint DFX_SetAppRunningUniqueId(const char* appRunningId, size_t len)
522800b99b8Sopenharmony_ci{
523800b99b8Sopenharmony_ci    size_t appRunningIdMaxLen = sizeof(g_appRunningId);
524800b99b8Sopenharmony_ci    if (appRunningId == NULL || appRunningIdMaxLen <= len) {
525800b99b8Sopenharmony_ci        DFXLOGE("param error. appRunningId is NULL or length overflow");
526800b99b8Sopenharmony_ci        return -1;
527800b99b8Sopenharmony_ci    }
528800b99b8Sopenharmony_ci    memset(g_appRunningId, 0, appRunningIdMaxLen);
529800b99b8Sopenharmony_ci    memcpy(g_appRunningId, appRunningId, len);
530800b99b8Sopenharmony_ci    return 0;
531800b99b8Sopenharmony_ci}
532800b99b8Sopenharmony_ci
533800b99b8Sopenharmony_ciuintptr_t DFX_SetCrashObj(uint8_t type, uintptr_t addr)
534800b99b8Sopenharmony_ci{
535800b99b8Sopenharmony_ci    if (!g_crashObjInit) {
536800b99b8Sopenharmony_ci        return 0;
537800b99b8Sopenharmony_ci    }
538800b99b8Sopenharmony_ci#if defined __LP64__
539800b99b8Sopenharmony_ci    uintptr_t origin = (uintptr_t)pthread_getspecific(g_crashObjKey);
540800b99b8Sopenharmony_ci    uintptr_t crashObj = 0;
541800b99b8Sopenharmony_ci    const int moveBit = 56;
542800b99b8Sopenharmony_ci    crashObj = ((uintptr_t)type << moveBit) | (addr & 0x00ffffffffffffff);
543800b99b8Sopenharmony_ci    pthread_setspecific(g_crashObjKey, (void*)(crashObj));
544800b99b8Sopenharmony_ci    return origin;
545800b99b8Sopenharmony_ci#else
546800b99b8Sopenharmony_ci    return 0;
547800b99b8Sopenharmony_ci#endif
548800b99b8Sopenharmony_ci}
549800b99b8Sopenharmony_ci
550800b99b8Sopenharmony_civoid DFX_ResetCrashObj(uintptr_t crashObj)
551800b99b8Sopenharmony_ci{
552800b99b8Sopenharmony_ci    if (!g_crashObjInit) {
553800b99b8Sopenharmony_ci        return;
554800b99b8Sopenharmony_ci    }
555800b99b8Sopenharmony_ci#if defined __LP64__
556800b99b8Sopenharmony_ci    pthread_setspecific(g_crashObjKey, (void*)(crashObj));
557800b99b8Sopenharmony_ci#endif
558800b99b8Sopenharmony_ci}
559