1800b99b8Sopenharmony_ci/* 2800b99b8Sopenharmony_ci * Copyright (c) 2021-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 "dfx_signal_local_handler.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <securec.h> 19800b99b8Sopenharmony_ci#include <csignal> 20800b99b8Sopenharmony_ci#include <sigchain.h> 21800b99b8Sopenharmony_ci#include <cstdint> 22800b99b8Sopenharmony_ci#include <cstdio> 23800b99b8Sopenharmony_ci#include <unistd.h> 24800b99b8Sopenharmony_ci#include <pthread.h> 25800b99b8Sopenharmony_ci#include <sched.h> 26800b99b8Sopenharmony_ci#include <sys/syscall.h> 27800b99b8Sopenharmony_ci#include <sys/mman.h> 28800b99b8Sopenharmony_ci#include <sys/prctl.h> 29800b99b8Sopenharmony_ci#include <sys/wait.h> 30800b99b8Sopenharmony_ci#include <linux/futex.h> 31800b99b8Sopenharmony_ci#include "dfx_allocator.h" 32800b99b8Sopenharmony_ci#include "dfx_crash_local_handler.h" 33800b99b8Sopenharmony_ci#include "dfx_cutil.h" 34800b99b8Sopenharmony_ci#include "dfx_log.h" 35800b99b8Sopenharmony_ci 36800b99b8Sopenharmony_ci#ifdef LOG_DOMAIN 37800b99b8Sopenharmony_ci#undef LOG_DOMAIN 38800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 39800b99b8Sopenharmony_ci#endif 40800b99b8Sopenharmony_ci 41800b99b8Sopenharmony_ci#ifdef LOG_TAG 42800b99b8Sopenharmony_ci#undef LOG_TAG 43800b99b8Sopenharmony_ci#define LOG_TAG "DfxSignalLocalHandler" 44800b99b8Sopenharmony_ci#endif 45800b99b8Sopenharmony_ci 46800b99b8Sopenharmony_ci#define LOCAL_HANDLER_STACK_SIZE (128 * 1024) // 128K 47800b99b8Sopenharmony_ci 48800b99b8Sopenharmony_cistatic CrashFdFunc g_crashFdFn = nullptr; 49800b99b8Sopenharmony_cistatic void *g_reservedChildStack = nullptr; 50800b99b8Sopenharmony_cistatic struct ProcessDumpRequest g_request; 51800b99b8Sopenharmony_cistatic pthread_mutex_t g_signalHandlerMutex = PTHREAD_MUTEX_INITIALIZER; 52800b99b8Sopenharmony_ci 53800b99b8Sopenharmony_cistatic int g_platformSignals[] = { 54800b99b8Sopenharmony_ci SIGABRT, SIGBUS, SIGILL, SIGSEGV, 55800b99b8Sopenharmony_ci}; 56800b99b8Sopenharmony_ci 57800b99b8Sopenharmony_cistatic void ReserveChildThreadSignalStack(void) 58800b99b8Sopenharmony_ci{ 59800b99b8Sopenharmony_ci // reserve stack for fork 60800b99b8Sopenharmony_ci g_reservedChildStack = mmap(nullptr, LOCAL_HANDLER_STACK_SIZE, \ 61800b99b8Sopenharmony_ci PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 1, 0); 62800b99b8Sopenharmony_ci if (g_reservedChildStack == MAP_FAILED) { 63800b99b8Sopenharmony_ci DFXLOGE("[%{public}d]: Failed to alloc memory for child stack.", __LINE__); 64800b99b8Sopenharmony_ci return; 65800b99b8Sopenharmony_ci } 66800b99b8Sopenharmony_ci g_reservedChildStack = static_cast<void *>(static_cast<uint8_t *>(g_reservedChildStack) + 67800b99b8Sopenharmony_ci LOCAL_HANDLER_STACK_SIZE - 1); 68800b99b8Sopenharmony_ci} 69800b99b8Sopenharmony_ci 70800b99b8Sopenharmony_ciAT_UNUSED static void FutexWait(volatile void* ftx, int value) 71800b99b8Sopenharmony_ci{ 72800b99b8Sopenharmony_ci syscall(__NR_futex, ftx, FUTEX_WAIT, value, NULL, NULL, 0); 73800b99b8Sopenharmony_ci} 74800b99b8Sopenharmony_ci 75800b99b8Sopenharmony_cistatic int DoCrashHandler(void* arg) 76800b99b8Sopenharmony_ci{ 77800b99b8Sopenharmony_ci (void)arg; 78800b99b8Sopenharmony_ci RegisterAllocator(); 79800b99b8Sopenharmony_ci if (g_crashFdFn == nullptr) { 80800b99b8Sopenharmony_ci CrashLocalHandler(&g_request); 81800b99b8Sopenharmony_ci } else { 82800b99b8Sopenharmony_ci int fd = g_crashFdFn(); 83800b99b8Sopenharmony_ci CrashLocalHandlerFd(fd, &g_request); 84800b99b8Sopenharmony_ci if (fd >= 0) { 85800b99b8Sopenharmony_ci close(fd); 86800b99b8Sopenharmony_ci } 87800b99b8Sopenharmony_ci } 88800b99b8Sopenharmony_ci UnregisterAllocator(); 89800b99b8Sopenharmony_ci pthread_mutex_unlock(&g_signalHandlerMutex); 90800b99b8Sopenharmony_ci syscall(__NR_exit, 0); 91800b99b8Sopenharmony_ci return 0; 92800b99b8Sopenharmony_ci} 93800b99b8Sopenharmony_ci 94800b99b8Sopenharmony_civoid DFX_SignalLocalHandler(int sig, siginfo_t *si, void *context) 95800b99b8Sopenharmony_ci{ 96800b99b8Sopenharmony_ci pthread_mutex_lock(&g_signalHandlerMutex); 97800b99b8Sopenharmony_ci (void)memset_s(&g_request, sizeof(g_request), 0, sizeof(g_request)); 98800b99b8Sopenharmony_ci g_request.type = static_cast<ProcessDumpType>(sig); 99800b99b8Sopenharmony_ci g_request.tid = gettid(); 100800b99b8Sopenharmony_ci g_request.pid = getpid(); 101800b99b8Sopenharmony_ci g_request.uid = getuid(); 102800b99b8Sopenharmony_ci g_request.timeStamp = GetTimeMilliseconds(); 103800b99b8Sopenharmony_ci DFXLOGI("DFX_SignalLocalHandler :: sig(%{public}d), pid(%{public}d), tid(%{public}d).", 104800b99b8Sopenharmony_ci sig, g_request.pid, g_request.tid); 105800b99b8Sopenharmony_ci 106800b99b8Sopenharmony_ci GetThreadNameByTid(g_request.tid, g_request.threadName, sizeof(g_request.threadName)); 107800b99b8Sopenharmony_ci GetProcessName(g_request.processName, sizeof(g_request.processName)); 108800b99b8Sopenharmony_ci 109800b99b8Sopenharmony_ci int ret = memcpy_s(&(g_request.siginfo), sizeof(siginfo_t), si, sizeof(siginfo_t)); 110800b99b8Sopenharmony_ci if (ret < 0) { 111800b99b8Sopenharmony_ci DFXLOGE("memcpy_s siginfo fail, ret=%{public}d", ret); 112800b99b8Sopenharmony_ci } 113800b99b8Sopenharmony_ci ret = memcpy_s(&(g_request.context), sizeof(ucontext_t), context, sizeof(ucontext_t)); 114800b99b8Sopenharmony_ci if (ret < 0) { 115800b99b8Sopenharmony_ci DFXLOGE("memcpy_s context fail, ret=%{public}d", ret); 116800b99b8Sopenharmony_ci } 117800b99b8Sopenharmony_ci#ifdef __aarch64__ 118800b99b8Sopenharmony_ci DoCrashHandler(NULL); 119800b99b8Sopenharmony_ci#else 120800b99b8Sopenharmony_ci int pseudothreadTid = -1; 121800b99b8Sopenharmony_ci pid_t childTid = clone(DoCrashHandler, g_reservedChildStack, \ 122800b99b8Sopenharmony_ci CLONE_THREAD | CLONE_SIGHAND | CLONE_VM | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID, \ 123800b99b8Sopenharmony_ci &pseudothreadTid, NULL, NULL, &pseudothreadTid); 124800b99b8Sopenharmony_ci if (childTid == -1) { 125800b99b8Sopenharmony_ci DFXLOGE("Failed to create thread for crash local handler"); 126800b99b8Sopenharmony_ci pthread_mutex_unlock(&g_signalHandlerMutex); 127800b99b8Sopenharmony_ci return; 128800b99b8Sopenharmony_ci } 129800b99b8Sopenharmony_ci 130800b99b8Sopenharmony_ci FutexWait(&pseudothreadTid, -1); 131800b99b8Sopenharmony_ci FutexWait(&pseudothreadTid, childTid); 132800b99b8Sopenharmony_ci 133800b99b8Sopenharmony_ci DFXLOGI("child thread(%{public}d) exit.", childTid); 134800b99b8Sopenharmony_ci syscall(__NR_exit, 0); 135800b99b8Sopenharmony_ci#endif 136800b99b8Sopenharmony_ci} 137800b99b8Sopenharmony_ci 138800b99b8Sopenharmony_civoid DFX_GetCrashFdFunc(CrashFdFunc fn) 139800b99b8Sopenharmony_ci{ 140800b99b8Sopenharmony_ci g_crashFdFn = fn; 141800b99b8Sopenharmony_ci} 142800b99b8Sopenharmony_ci 143800b99b8Sopenharmony_civoid DFX_InstallLocalSignalHandler(void) 144800b99b8Sopenharmony_ci{ 145800b99b8Sopenharmony_ci ReserveChildThreadSignalStack(); 146800b99b8Sopenharmony_ci 147800b99b8Sopenharmony_ci sigset_t set; 148800b99b8Sopenharmony_ci sigemptyset(&set); 149800b99b8Sopenharmony_ci struct sigaction action; 150800b99b8Sopenharmony_ci (void)memset_s(&action, sizeof(action), 0, sizeof(action)); 151800b99b8Sopenharmony_ci sigfillset(&action.sa_mask); 152800b99b8Sopenharmony_ci action.sa_sigaction = DFX_SignalLocalHandler; 153800b99b8Sopenharmony_ci action.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 154800b99b8Sopenharmony_ci 155800b99b8Sopenharmony_ci for (size_t i = 0; i < sizeof(g_platformSignals) / sizeof(g_platformSignals[0]); i++) { 156800b99b8Sopenharmony_ci int32_t sig = g_platformSignals[i]; 157800b99b8Sopenharmony_ci remove_all_special_handler(sig); 158800b99b8Sopenharmony_ci 159800b99b8Sopenharmony_ci sigaddset(&set, sig); 160800b99b8Sopenharmony_ci if (sigaction(sig, &action, nullptr) != 0) { 161800b99b8Sopenharmony_ci DFXLOGE("Failed to register signal(%{public}d)", sig); 162800b99b8Sopenharmony_ci } 163800b99b8Sopenharmony_ci } 164800b99b8Sopenharmony_ci sigprocmask(SIG_UNBLOCK, &set, nullptr); 165800b99b8Sopenharmony_ci} 166