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