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 "process_dumper.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <algorithm> 19800b99b8Sopenharmony_ci#include <cerrno> 20800b99b8Sopenharmony_ci#include <chrono> 21800b99b8Sopenharmony_ci#include <cinttypes> 22800b99b8Sopenharmony_ci#include <csignal> 23800b99b8Sopenharmony_ci#include <cstdio> 24800b99b8Sopenharmony_ci#include <cstdlib> 25800b99b8Sopenharmony_ci#include <cstring> 26800b99b8Sopenharmony_ci#include <dirent.h> 27800b99b8Sopenharmony_ci#include <fcntl.h> 28800b99b8Sopenharmony_ci#include <memory> 29800b99b8Sopenharmony_ci#include <pthread.h> 30800b99b8Sopenharmony_ci#include <securec.h> 31800b99b8Sopenharmony_ci#include <string> 32800b99b8Sopenharmony_ci#include <syscall.h> 33800b99b8Sopenharmony_ci#include <sys/time.h> 34800b99b8Sopenharmony_ci#include <sys/types.h> 35800b99b8Sopenharmony_ci#include <sys/ptrace.h> 36800b99b8Sopenharmony_ci#include <ucontext.h> 37800b99b8Sopenharmony_ci#include <unistd.h> 38800b99b8Sopenharmony_ci 39800b99b8Sopenharmony_ci#include "cppcrash_reporter.h" 40800b99b8Sopenharmony_ci#include "crash_exception.h" 41800b99b8Sopenharmony_ci#include "dfx_config.h" 42800b99b8Sopenharmony_ci#include "dfx_define.h" 43800b99b8Sopenharmony_ci#include "dfx_dump_request.h" 44800b99b8Sopenharmony_ci#include "dfx_dump_res.h" 45800b99b8Sopenharmony_ci#include "dfx_fdsan.h" 46800b99b8Sopenharmony_ci#include "dfx_logger.h" 47800b99b8Sopenharmony_ci#include "dfx_process.h" 48800b99b8Sopenharmony_ci#include "dfx_regs.h" 49800b99b8Sopenharmony_ci#include "dfx_ring_buffer_wrapper.h" 50800b99b8Sopenharmony_ci#include "dfx_stack_info_formatter.h" 51800b99b8Sopenharmony_ci#include "dfx_thread.h" 52800b99b8Sopenharmony_ci#include "dfx_unwind_remote.h" 53800b99b8Sopenharmony_ci#include "dfx_util.h" 54800b99b8Sopenharmony_ci#include "dfx_trace.h" 55800b99b8Sopenharmony_ci#include "elapsed_time.h" 56800b99b8Sopenharmony_ci#include "faultloggerd_client.h" 57800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE 58800b99b8Sopenharmony_ci#include "hisysevent.h" 59800b99b8Sopenharmony_ci#endif 60800b99b8Sopenharmony_ci#include "printer.h" 61800b99b8Sopenharmony_ci#include "procinfo.h" 62800b99b8Sopenharmony_ci#include "unwinder_config.h" 63800b99b8Sopenharmony_ci#ifndef is_ohos_lite 64800b99b8Sopenharmony_ci#include "parameter.h" 65800b99b8Sopenharmony_ci#include "parameters.h" 66800b99b8Sopenharmony_ci#endif // !is_ohos_lite 67800b99b8Sopenharmony_ci 68800b99b8Sopenharmony_cinamespace OHOS { 69800b99b8Sopenharmony_cinamespace HiviewDFX { 70800b99b8Sopenharmony_cinamespace { 71800b99b8Sopenharmony_ci#undef LOG_DOMAIN 72800b99b8Sopenharmony_ci#undef LOG_TAG 73800b99b8Sopenharmony_ci#define LOG_DOMAIN 0xD002D11 74800b99b8Sopenharmony_ci#define LOG_TAG "DfxProcessDump" 75800b99b8Sopenharmony_ciconst char *const BLOCK_CRASH_PROCESS = "faultloggerd.priv.block_crash_process.enabled"; 76800b99b8Sopenharmony_ci 77800b99b8Sopenharmony_cistatic bool IsBlockCrashProcess() 78800b99b8Sopenharmony_ci{ 79800b99b8Sopenharmony_ci bool isBlockCrash = false; 80800b99b8Sopenharmony_ci#ifndef is_ohos_lite 81800b99b8Sopenharmony_ci isBlockCrash = OHOS::system::GetParameter(BLOCK_CRASH_PROCESS, "false") == "true"; 82800b99b8Sopenharmony_ci#endif 83800b99b8Sopenharmony_ci return isBlockCrash; 84800b99b8Sopenharmony_ci} 85800b99b8Sopenharmony_ci 86800b99b8Sopenharmony_civoid WriteData(int fd, const std::string& data, size_t blockSize) 87800b99b8Sopenharmony_ci{ 88800b99b8Sopenharmony_ci size_t dataSize = data.length(); 89800b99b8Sopenharmony_ci size_t index = 0; 90800b99b8Sopenharmony_ci while (index < dataSize) { 91800b99b8Sopenharmony_ci size_t writeLength = (index + blockSize) <= dataSize ? blockSize : (dataSize - index); 92800b99b8Sopenharmony_ci ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(fd, data.substr(index, writeLength).c_str(), writeLength)); 93800b99b8Sopenharmony_ci if (nwrite != static_cast<ssize_t>(writeLength)) { 94800b99b8Sopenharmony_ci DFXLOGI("%{public}s :: nwrite: %{public}zd, writeLength: %{public}zu", __func__, nwrite, writeLength); 95800b99b8Sopenharmony_ci } 96800b99b8Sopenharmony_ci index += writeLength; 97800b99b8Sopenharmony_ci } 98800b99b8Sopenharmony_ci DFXLOGI("%{public}s :: needWriteDataSize: %{public}zu, writeDataSize: %{public}zu", __func__, dataSize, index); 99800b99b8Sopenharmony_ci} 100800b99b8Sopenharmony_ci 101800b99b8Sopenharmony_ci#if !defined(__x86_64__) 102800b99b8Sopenharmony_ciconst int ARG_MAX_NUM = 131072; 103800b99b8Sopenharmony_ci#endif 104800b99b8Sopenharmony_ciusing OpenFilesList = std::map<int, FDInfo>; 105800b99b8Sopenharmony_ci 106800b99b8Sopenharmony_cibool ReadLink(std::string &src, std::string &dst) 107800b99b8Sopenharmony_ci{ 108800b99b8Sopenharmony_ci char buf[PATH_MAX]; 109800b99b8Sopenharmony_ci ssize_t count = readlink(src.c_str(), buf, sizeof(buf) - 1); 110800b99b8Sopenharmony_ci if (count < 0) { 111800b99b8Sopenharmony_ci return false; 112800b99b8Sopenharmony_ci } 113800b99b8Sopenharmony_ci buf[count] = '\0'; 114800b99b8Sopenharmony_ci dst = buf; 115800b99b8Sopenharmony_ci return true; 116800b99b8Sopenharmony_ci} 117800b99b8Sopenharmony_ci 118800b99b8Sopenharmony_civoid CollectOpenFiles(OpenFilesList &list, pid_t pid) 119800b99b8Sopenharmony_ci{ 120800b99b8Sopenharmony_ci std::string fdDirName = "/proc/" + std::to_string(pid) + "/fd"; 121800b99b8Sopenharmony_ci std::unique_ptr<DIR, int (*)(DIR *)> dir(opendir(fdDirName.c_str()), closedir); 122800b99b8Sopenharmony_ci if (dir == nullptr) { 123800b99b8Sopenharmony_ci DFXLOGE("failed to open directory %{public}s: %{public}s", fdDirName.c_str(), strerror(errno)); 124800b99b8Sopenharmony_ci return; 125800b99b8Sopenharmony_ci } 126800b99b8Sopenharmony_ci 127800b99b8Sopenharmony_ci struct dirent *de; 128800b99b8Sopenharmony_ci while ((de = readdir(dir.get())) != nullptr) { 129800b99b8Sopenharmony_ci if (*de->d_name == '.') { 130800b99b8Sopenharmony_ci continue; 131800b99b8Sopenharmony_ci } 132800b99b8Sopenharmony_ci 133800b99b8Sopenharmony_ci int fd = atoi(de->d_name); 134800b99b8Sopenharmony_ci std::string path = fdDirName + "/" + std::string(de->d_name); 135800b99b8Sopenharmony_ci std::string target; 136800b99b8Sopenharmony_ci if (ReadLink(path, target)) { 137800b99b8Sopenharmony_ci list[fd].path = target; 138800b99b8Sopenharmony_ci } else { 139800b99b8Sopenharmony_ci list[fd].path = "???"; 140800b99b8Sopenharmony_ci DFXLOGE("failed to readlink %{public}s: %{public}s", path.c_str(), strerror(errno)); 141800b99b8Sopenharmony_ci } 142800b99b8Sopenharmony_ci } 143800b99b8Sopenharmony_ci} 144800b99b8Sopenharmony_ci 145800b99b8Sopenharmony_ci#if !defined(__x86_64__) 146800b99b8Sopenharmony_civoid FillFdsaninfo(OpenFilesList &list, pid_t nsPid, uint64_t fdTableAddr) 147800b99b8Sopenharmony_ci{ 148800b99b8Sopenharmony_ci constexpr size_t fds = sizeof(FdTable::entries) / sizeof(*FdTable::entries); 149800b99b8Sopenharmony_ci size_t entryOffset = offsetof(FdTable, entries); 150800b99b8Sopenharmony_ci uint64_t addr = fdTableAddr + entryOffset; 151800b99b8Sopenharmony_ci FdEntry entrys[fds]; 152800b99b8Sopenharmony_ci if (DfxMemory::ReadProcMemByPid(nsPid, addr, entrys, sizeof(FdEntry) * fds) != sizeof(FdEntry) * fds) { 153800b99b8Sopenharmony_ci DFXLOGE("[%{public}d]: read nsPid mem error %{public}s", __LINE__, strerror(errno)); 154800b99b8Sopenharmony_ci return; 155800b99b8Sopenharmony_ci } 156800b99b8Sopenharmony_ci for (size_t i = 0; i < fds; i++) { 157800b99b8Sopenharmony_ci if (entrys[i].close_tag) { 158800b99b8Sopenharmony_ci list[i].fdsanOwner = entrys[i].close_tag; 159800b99b8Sopenharmony_ci } 160800b99b8Sopenharmony_ci } 161800b99b8Sopenharmony_ci 162800b99b8Sopenharmony_ci size_t overflowOffset = offsetof(FdTable, overflow); 163800b99b8Sopenharmony_ci uintptr_t overflow = 0; 164800b99b8Sopenharmony_ci uint64_t tmp = fdTableAddr + overflowOffset; 165800b99b8Sopenharmony_ci if (DfxMemory::ReadProcMemByPid(nsPid, tmp, &overflow, sizeof(overflow)) != sizeof(overflow)) { 166800b99b8Sopenharmony_ci return; 167800b99b8Sopenharmony_ci } 168800b99b8Sopenharmony_ci if (!overflow) { 169800b99b8Sopenharmony_ci return; 170800b99b8Sopenharmony_ci } 171800b99b8Sopenharmony_ci 172800b99b8Sopenharmony_ci size_t overflowLength; 173800b99b8Sopenharmony_ci if (DfxMemory::ReadProcMemByPid(nsPid, overflow, &overflowLength, sizeof(overflowLength)) 174800b99b8Sopenharmony_ci != sizeof(overflowLength)) { 175800b99b8Sopenharmony_ci return; 176800b99b8Sopenharmony_ci } 177800b99b8Sopenharmony_ci if (overflowLength > ARG_MAX_NUM) { 178800b99b8Sopenharmony_ci return; 179800b99b8Sopenharmony_ci } 180800b99b8Sopenharmony_ci 181800b99b8Sopenharmony_ci std::vector<FdEntry> overflowFdEntrys(overflowLength); 182800b99b8Sopenharmony_ci uint64_t address = overflow + offsetof(FdTableOverflow, entries); 183800b99b8Sopenharmony_ci if (DfxMemory::ReadProcMemByPid(nsPid, address, overflowFdEntrys.data(), sizeof(FdEntry) * overflowLength) != 184800b99b8Sopenharmony_ci sizeof(FdEntry) * overflowLength) { 185800b99b8Sopenharmony_ci DFXLOGE("[%{public}d]: read nsPid mem error %{public}s", __LINE__, strerror(errno)); 186800b99b8Sopenharmony_ci return; 187800b99b8Sopenharmony_ci } 188800b99b8Sopenharmony_ci size_t fdIndex = fds; 189800b99b8Sopenharmony_ci for (size_t i = 0; i < overflowLength; i++) { 190800b99b8Sopenharmony_ci if (overflowFdEntrys[i].close_tag) { 191800b99b8Sopenharmony_ci list[fdIndex].fdsanOwner = overflowFdEntrys[i].close_tag; 192800b99b8Sopenharmony_ci } 193800b99b8Sopenharmony_ci fdIndex++; 194800b99b8Sopenharmony_ci } 195800b99b8Sopenharmony_ci} 196800b99b8Sopenharmony_ci#endif 197800b99b8Sopenharmony_ci 198800b99b8Sopenharmony_cistd::string DumpOpenFiles(OpenFilesList &files) 199800b99b8Sopenharmony_ci{ 200800b99b8Sopenharmony_ci std::string openFiles; 201800b99b8Sopenharmony_ci for (auto &[fd, entry]: files) { 202800b99b8Sopenharmony_ci const std::string path = entry.path; 203800b99b8Sopenharmony_ci uint64_t tag = entry.fdsanOwner; 204800b99b8Sopenharmony_ci const char* type = fdsan_get_tag_type(tag); 205800b99b8Sopenharmony_ci uint64_t val = fdsan_get_tag_value(tag); 206800b99b8Sopenharmony_ci if (!path.empty()) { 207800b99b8Sopenharmony_ci openFiles += std::to_string(fd) + "->" + path + " " + type + " " + std::to_string(val) + "\n"; 208800b99b8Sopenharmony_ci } else { 209800b99b8Sopenharmony_ci openFiles += "OpenFilesList contain an entry (fd " + std::to_string(fd) + ") with no path or owner\n"; 210800b99b8Sopenharmony_ci } 211800b99b8Sopenharmony_ci } 212800b99b8Sopenharmony_ci return openFiles; 213800b99b8Sopenharmony_ci} 214800b99b8Sopenharmony_ci 215800b99b8Sopenharmony_civoid ReadPids(int& realPid, int& vmPid) 216800b99b8Sopenharmony_ci{ 217800b99b8Sopenharmony_ci pid_t pids[PID_MAX] = {0}; 218800b99b8Sopenharmony_ci OHOS_TEMP_FAILURE_RETRY(read(STDIN_FILENO, pids, sizeof(pids))); 219800b99b8Sopenharmony_ci realPid = pids[REAL_PROCESS_PID]; 220800b99b8Sopenharmony_ci vmPid = pids[VIRTUAL_PROCESS_PID]; 221800b99b8Sopenharmony_ci DFXLOGW("procecdump get real pid is %{public}d vm pid is %{public}d", realPid, vmPid); 222800b99b8Sopenharmony_ci} 223800b99b8Sopenharmony_ci 224800b99b8Sopenharmony_civoid InfoRemoteProcessResult(std::shared_ptr<ProcessDumpRequest> request, int result, int type) 225800b99b8Sopenharmony_ci{ 226800b99b8Sopenharmony_ci if (request == nullptr) { 227800b99b8Sopenharmony_ci return; 228800b99b8Sopenharmony_ci } 229800b99b8Sopenharmony_ci if (request->pmPipeFd[0] != -1) { 230800b99b8Sopenharmony_ci close(request->pmPipeFd[0]); 231800b99b8Sopenharmony_ci request->pmPipeFd[0] = -1; 232800b99b8Sopenharmony_ci } 233800b99b8Sopenharmony_ci switch (type) { 234800b99b8Sopenharmony_ci case MAIN_PROCESS: 235800b99b8Sopenharmony_ci OHOS_TEMP_FAILURE_RETRY(write(request->pmPipeFd[1], &result, sizeof(result))); 236800b99b8Sopenharmony_ci break; 237800b99b8Sopenharmony_ci case VIRTUAL_PROCESS: 238800b99b8Sopenharmony_ci OHOS_TEMP_FAILURE_RETRY(write(request->vmPipeFd[1], &result, sizeof(result))); 239800b99b8Sopenharmony_ci break; 240800b99b8Sopenharmony_ci default: 241800b99b8Sopenharmony_ci break; 242800b99b8Sopenharmony_ci } 243800b99b8Sopenharmony_ci} 244800b99b8Sopenharmony_ci 245800b99b8Sopenharmony_civoid SetProcessdumpTimeout(siginfo_t &si) 246800b99b8Sopenharmony_ci{ 247800b99b8Sopenharmony_ci if (si.si_signo != SIGDUMP) { 248800b99b8Sopenharmony_ci return; 249800b99b8Sopenharmony_ci } 250800b99b8Sopenharmony_ci 251800b99b8Sopenharmony_ci uint64_t endTime; 252800b99b8Sopenharmony_ci int tid; 253800b99b8Sopenharmony_ci ParseSiValue(si, endTime, tid); 254800b99b8Sopenharmony_ci 255800b99b8Sopenharmony_ci if (tid == 0) { 256800b99b8Sopenharmony_ci DFXLOGI("reset, prevent incorrect reading sival_int for tid"); 257800b99b8Sopenharmony_ci si.si_value.sival_int = 0; 258800b99b8Sopenharmony_ci } 259800b99b8Sopenharmony_ci 260800b99b8Sopenharmony_ci if (endTime == 0) { 261800b99b8Sopenharmony_ci DFXLOGI("end time is zero, not set new alarm"); 262800b99b8Sopenharmony_ci return; 263800b99b8Sopenharmony_ci } 264800b99b8Sopenharmony_ci 265800b99b8Sopenharmony_ci uint64_t curTime = GetAbsTimeMilliSeconds(); 266800b99b8Sopenharmony_ci if (curTime >= endTime) { 267800b99b8Sopenharmony_ci DFXLOGI("now has timeout, processdump exit"); 268800b99b8Sopenharmony_ci#ifndef CLANG_COVERAGE 269800b99b8Sopenharmony_ci _exit(0); 270800b99b8Sopenharmony_ci#endif 271800b99b8Sopenharmony_ci } 272800b99b8Sopenharmony_ci uint64_t diffTime = endTime - curTime; 273800b99b8Sopenharmony_ci 274800b99b8Sopenharmony_ci DFXLOGI("processdump remain time%{public}" PRIu64 "ms", diffTime); 275800b99b8Sopenharmony_ci if (diffTime > PROCESSDUMP_TIMEOUT * NUMBER_ONE_THOUSAND) { 276800b99b8Sopenharmony_ci DFXLOGE("dump remain time is invalid, not set timer"); 277800b99b8Sopenharmony_ci return; 278800b99b8Sopenharmony_ci } 279800b99b8Sopenharmony_ci 280800b99b8Sopenharmony_ci struct itimerval timer; 281800b99b8Sopenharmony_ci timer.it_value.tv_sec = static_cast<int64_t>(diffTime / NUMBER_ONE_THOUSAND); 282800b99b8Sopenharmony_ci timer.it_value.tv_usec = static_cast<int64_t>(diffTime * NUMBER_ONE_THOUSAND % NUMBER_ONE_MILLION); 283800b99b8Sopenharmony_ci timer.it_interval.tv_sec = 0; 284800b99b8Sopenharmony_ci timer.it_interval.tv_usec = 0; 285800b99b8Sopenharmony_ci 286800b99b8Sopenharmony_ci if (setitimer(ITIMER_REAL, &timer, nullptr) != 0) { 287800b99b8Sopenharmony_ci DFXLOGE("start processdump timer fail %{public}d", errno); 288800b99b8Sopenharmony_ci } 289800b99b8Sopenharmony_ci} 290800b99b8Sopenharmony_ci} 291800b99b8Sopenharmony_ci 292800b99b8Sopenharmony_ciProcessDumper &ProcessDumper::GetInstance() 293800b99b8Sopenharmony_ci{ 294800b99b8Sopenharmony_ci static ProcessDumper ins; 295800b99b8Sopenharmony_ci return ins; 296800b99b8Sopenharmony_ci} 297800b99b8Sopenharmony_ci 298800b99b8Sopenharmony_civoid ProcessDumper::Dump() 299800b99b8Sopenharmony_ci{ 300800b99b8Sopenharmony_ci startTime_ = GetTimeMillisec(); 301800b99b8Sopenharmony_ci std::shared_ptr<ProcessDumpRequest> request = std::make_shared<ProcessDumpRequest>(); 302800b99b8Sopenharmony_ci resDump_ = DumpProcess(request); 303800b99b8Sopenharmony_ci if (process_ == nullptr) { 304800b99b8Sopenharmony_ci DFXLOGE("Dump process failed, please check permission and whether pid is valid."); 305800b99b8Sopenharmony_ci } else { 306800b99b8Sopenharmony_ci if (isCrash_ && process_->vmThread_ != nullptr) { 307800b99b8Sopenharmony_ci process_->vmThread_->Detach(); 308800b99b8Sopenharmony_ci } 309800b99b8Sopenharmony_ci if (process_->keyThread_ != nullptr) { 310800b99b8Sopenharmony_ci process_->keyThread_->Detach(); 311800b99b8Sopenharmony_ci } 312800b99b8Sopenharmony_ci if (isCrash_ && (request->dumpMode == FUSION_MODE) && IsBlockCrashProcess()) { 313800b99b8Sopenharmony_ci DFXLOGI("start block crash process pid %{public}d nspid %{public}d", request->pid, request->nsPid); 314800b99b8Sopenharmony_ci if (syscall(SYS_tgkill, request->nsPid, request->tid, SIGSTOP) != 0) { 315800b99b8Sopenharmony_ci DFXLOGE("send signal stop to nsPid %{public}d fail %{public}s", request->nsPid, strerror(errno)); 316800b99b8Sopenharmony_ci } 317800b99b8Sopenharmony_ci } 318800b99b8Sopenharmony_ci } 319800b99b8Sopenharmony_ci 320800b99b8Sopenharmony_ci std::string jsonInfo; 321800b99b8Sopenharmony_ci if (isJsonDump_ || isCrash_) { 322800b99b8Sopenharmony_ci DfxStackInfoFormatter formatter(process_, request); 323800b99b8Sopenharmony_ci formatter.GetStackInfo(isJsonDump_, jsonInfo); 324800b99b8Sopenharmony_ci DFXLOGI("Finish GetStackInfo len %{public}" PRIuPTR "", jsonInfo.length()); 325800b99b8Sopenharmony_ci if (isJsonDump_) { 326800b99b8Sopenharmony_ci WriteData(jsonFd_, jsonInfo, MAX_PIPE_SIZE); 327800b99b8Sopenharmony_ci } 328800b99b8Sopenharmony_ci } 329800b99b8Sopenharmony_ci 330800b99b8Sopenharmony_ci finishTime_ = GetTimeMillisec(); 331800b99b8Sopenharmony_ci ReportSigDumpStats(request); 332800b99b8Sopenharmony_ci // After skipping InitPrintThread due to ptrace failure or other reasons, 333800b99b8Sopenharmony_ci // request resFd_ to write back the result to dumpcatch 334800b99b8Sopenharmony_ci if (request->siginfo.si_signo == SIGDUMP && resFd_ == -1) { 335800b99b8Sopenharmony_ci resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES); 336800b99b8Sopenharmony_ci if (resFd_ < 0) { 337800b99b8Sopenharmony_ci resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_RES); 338800b99b8Sopenharmony_ci } 339800b99b8Sopenharmony_ci } 340800b99b8Sopenharmony_ci WriteDumpRes(resDump_); 341800b99b8Sopenharmony_ci // print keythread base info to hilog when carsh 342800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().PrintBaseInfo(); 343800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().StopThread(); 344800b99b8Sopenharmony_ci DFXLOGW("Finish dump stacktrace for %{public}s(%{public}d:%{public}d).", 345800b99b8Sopenharmony_ci request->processName, request->pid, request->tid); 346800b99b8Sopenharmony_ci Report(request, jsonInfo); 347800b99b8Sopenharmony_ci} 348800b99b8Sopenharmony_ci 349800b99b8Sopenharmony_civoid ProcessDumper::Report(std::shared_ptr<ProcessDumpRequest> request, std::string &jsonInfo) 350800b99b8Sopenharmony_ci{ 351800b99b8Sopenharmony_ci if (request == nullptr) { 352800b99b8Sopenharmony_ci DFXLOGE("request is nullptr."); 353800b99b8Sopenharmony_ci return; 354800b99b8Sopenharmony_ci } 355800b99b8Sopenharmony_ci if (request->msg.type == MESSAGE_FDSAN_DEBUG || 356800b99b8Sopenharmony_ci request->msg.type == MESSAGE_JEMALLOC || 357800b99b8Sopenharmony_ci request->msg.type == MESSAGE_BADFD) { 358800b99b8Sopenharmony_ci ReportAddrSanitizer(*request, jsonInfo); 359800b99b8Sopenharmony_ci return; 360800b99b8Sopenharmony_ci } 361800b99b8Sopenharmony_ci if (resDump_ != DumpErrorCode::DUMP_ENOMAP && resDump_ != DumpErrorCode::DUMP_EREADPID) { 362800b99b8Sopenharmony_ci ReportCrashInfo(jsonInfo); 363800b99b8Sopenharmony_ci } 364800b99b8Sopenharmony_ci if ((request->dumpMode == FUSION_MODE) && isCrash_) { 365800b99b8Sopenharmony_ci InfoRemoteProcessResult(request, OPE_CONTINUE, MAIN_PROCESS); 366800b99b8Sopenharmony_ci } 367800b99b8Sopenharmony_ci} 368800b99b8Sopenharmony_ci 369800b99b8Sopenharmony_cistatic int32_t ReadRequestAndCheck(std::shared_ptr<ProcessDumpRequest> request) 370800b99b8Sopenharmony_ci{ 371800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("ReadRequestAndCheck"); 372800b99b8Sopenharmony_ci ElapsedTime counter("ReadRequestAndCheck", 20); // 20 : limit cost time 20 ms 373800b99b8Sopenharmony_ci ssize_t readCount = OHOS_TEMP_FAILURE_RETRY(read(STDIN_FILENO, request.get(), sizeof(ProcessDumpRequest))); 374800b99b8Sopenharmony_ci request->threadName[NAME_BUF_LEN - 1] = '\0'; 375800b99b8Sopenharmony_ci request->processName[NAME_BUF_LEN - 1] = '\0'; 376800b99b8Sopenharmony_ci request->msg.body[MAX_FATAL_MSG_SIZE - 1] = '\0'; 377800b99b8Sopenharmony_ci request->appRunningId[MAX_APP_RUNNING_UNIQUE_ID_LEN - 1] = '\0'; 378800b99b8Sopenharmony_ci if (readCount != static_cast<long>(sizeof(ProcessDumpRequest))) { 379800b99b8Sopenharmony_ci DFXLOGE("Failed to read DumpRequest(%{public}d), readCount(%{public}zd).", errno, readCount); 380800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 381800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EREADREQ); 382800b99b8Sopenharmony_ci return DumpErrorCode::DUMP_EREADREQUEST; 383800b99b8Sopenharmony_ci } 384800b99b8Sopenharmony_ci 385800b99b8Sopenharmony_ci return DumpErrorCode::DUMP_ESUCCESS; 386800b99b8Sopenharmony_ci} 387800b99b8Sopenharmony_ci 388800b99b8Sopenharmony_cistd::string GetOpenFiles(int32_t pid, int nsPid, uint64_t fdTableAddr) 389800b99b8Sopenharmony_ci{ 390800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("GetOpenFiles"); 391800b99b8Sopenharmony_ci OpenFilesList openFies; 392800b99b8Sopenharmony_ci CollectOpenFiles(openFies, pid); 393800b99b8Sopenharmony_ci#if !defined(__x86_64__) 394800b99b8Sopenharmony_ci FillFdsaninfo(openFies, nsPid, fdTableAddr); 395800b99b8Sopenharmony_ci#endif 396800b99b8Sopenharmony_ci std::string fds = DumpOpenFiles(openFies); 397800b99b8Sopenharmony_ci DFXLOGI("get open files info finish"); 398800b99b8Sopenharmony_ci return fds; 399800b99b8Sopenharmony_ci} 400800b99b8Sopenharmony_ci 401800b99b8Sopenharmony_civoid ProcessDumper::InitRegs(std::shared_ptr<ProcessDumpRequest> request, int &dumpRes) 402800b99b8Sopenharmony_ci{ 403800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("InitRegs"); 404800b99b8Sopenharmony_ci uint32_t opeResult = OPE_SUCCESS; 405800b99b8Sopenharmony_ci if (request->dumpMode == FUSION_MODE) { 406800b99b8Sopenharmony_ci if (!DfxUnwindRemote::GetInstance().InitProcessAllThreadRegs(request, process_)) { 407800b99b8Sopenharmony_ci DFXLOGE("Failed to init process regs."); 408800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND; 409800b99b8Sopenharmony_ci opeResult = OPE_FAIL; 410800b99b8Sopenharmony_ci } 411800b99b8Sopenharmony_ci 412800b99b8Sopenharmony_ci InfoRemoteProcessResult(request, opeResult, MAIN_PROCESS); 413800b99b8Sopenharmony_ci DFXLOGI("get all tid regs finish"); 414800b99b8Sopenharmony_ci } 415800b99b8Sopenharmony_ci} 416800b99b8Sopenharmony_ci 417800b99b8Sopenharmony_cibool ProcessDumper::IsTargetProcessAlive(std::shared_ptr<ProcessDumpRequest> request) 418800b99b8Sopenharmony_ci{ 419800b99b8Sopenharmony_ci if ((request->dumpMode == SPLIT_MODE) && ((!isCrash_ && (syscall(SYS_getppid) != request->nsPid)) || 420800b99b8Sopenharmony_ci (isCrash_ && (syscall(SYS_getppid) != request->vmNsPid)))) { 421800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg( 422800b99b8Sopenharmony_ci "Target process has been killed, the crash log may not be fully generated."); 423800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 424800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EKILLED); 425800b99b8Sopenharmony_ci return false; 426800b99b8Sopenharmony_ci } 427800b99b8Sopenharmony_ci return true; 428800b99b8Sopenharmony_ci} 429800b99b8Sopenharmony_ci 430800b99b8Sopenharmony_civoid ProcessDumper::UnwindWriteJit(const ProcessDumpRequest &request) 431800b99b8Sopenharmony_ci{ 432800b99b8Sopenharmony_ci if (!isCrash_) { 433800b99b8Sopenharmony_ci return; 434800b99b8Sopenharmony_ci } 435800b99b8Sopenharmony_ci 436800b99b8Sopenharmony_ci const auto& jitCache = unwinder_->GetJitCache(); 437800b99b8Sopenharmony_ci if (jitCache.empty()) { 438800b99b8Sopenharmony_ci return; 439800b99b8Sopenharmony_ci } 440800b99b8Sopenharmony_ci struct FaultLoggerdRequest jitRequest; 441800b99b8Sopenharmony_ci (void)memset_s(&jitRequest, sizeof(jitRequest), 0, sizeof(jitRequest)); 442800b99b8Sopenharmony_ci jitRequest.type = FaultLoggerType::JIT_CODE_LOG; 443800b99b8Sopenharmony_ci jitRequest.pid = request.pid; 444800b99b8Sopenharmony_ci jitRequest.tid = request.tid; 445800b99b8Sopenharmony_ci jitRequest.uid = request.uid; 446800b99b8Sopenharmony_ci jitRequest.time = OHOS::HiviewDFX::GetTimeMilliSeconds(); 447800b99b8Sopenharmony_ci int32_t fd = RequestFileDescriptorEx(&jitRequest); 448800b99b8Sopenharmony_ci if (fd == -1) { 449800b99b8Sopenharmony_ci DFXLOGE("request jitlog fd failed."); 450800b99b8Sopenharmony_ci return; 451800b99b8Sopenharmony_ci } 452800b99b8Sopenharmony_ci if (unwinder_->ArkWriteJitCodeToFile(fd) < 0) { 453800b99b8Sopenharmony_ci DFXLOGE("jit code write file failed."); 454800b99b8Sopenharmony_ci } 455800b99b8Sopenharmony_ci (void)close(fd); 456800b99b8Sopenharmony_ci} 457800b99b8Sopenharmony_ci 458800b99b8Sopenharmony_cistd::string ProcessDumper::ReadStringByPtrace(pid_t tid, uintptr_t addr) 459800b99b8Sopenharmony_ci{ 460800b99b8Sopenharmony_ci constexpr int bufLen = 256; 461800b99b8Sopenharmony_ci long buffer[bufLen] = {0}; 462800b99b8Sopenharmony_ci for (int i = 0; i < bufLen - 1; i++) { 463800b99b8Sopenharmony_ci long ret = ptrace(PTRACE_PEEKTEXT, tid, reinterpret_cast<void*>(addr + sizeof(long) * i), nullptr); 464800b99b8Sopenharmony_ci if (ret == -1) { 465800b99b8Sopenharmony_ci DFXLOGE("read target mem by ptrace failed, errno(%{public}s).", strerror(errno)); 466800b99b8Sopenharmony_ci break; 467800b99b8Sopenharmony_ci } 468800b99b8Sopenharmony_ci buffer[i] = ret; 469800b99b8Sopenharmony_ci if (ret == 0) { 470800b99b8Sopenharmony_ci break; 471800b99b8Sopenharmony_ci } 472800b99b8Sopenharmony_ci } 473800b99b8Sopenharmony_ci char* val = reinterpret_cast<char*>(buffer); 474800b99b8Sopenharmony_ci return std::string(val); 475800b99b8Sopenharmony_ci} 476800b99b8Sopenharmony_ci 477800b99b8Sopenharmony_civoid ProcessDumper::GetCrashObj(std::shared_ptr<ProcessDumpRequest> request) 478800b99b8Sopenharmony_ci{ 479800b99b8Sopenharmony_ci#ifdef __LP64__ 480800b99b8Sopenharmony_ci if (!isCrash_ || request->crashObj == 0) { 481800b99b8Sopenharmony_ci return; 482800b99b8Sopenharmony_ci } 483800b99b8Sopenharmony_ci uintptr_t type = request->crashObj >> 56; // 56 :: Move 56 bit to the right 484800b99b8Sopenharmony_ci uintptr_t addr = request->crashObj & 0xffffffffffffff; 485800b99b8Sopenharmony_ci switch (type) { 486800b99b8Sopenharmony_ci case 0: { 487800b99b8Sopenharmony_ci if (process_ != nullptr) { 488800b99b8Sopenharmony_ci process_->SetFatalMessage(process_->GetFatalMessage() + ReadStringByPtrace(request->nsPid, addr)); 489800b99b8Sopenharmony_ci } 490800b99b8Sopenharmony_ci break; 491800b99b8Sopenharmony_ci } 492800b99b8Sopenharmony_ci default: 493800b99b8Sopenharmony_ci break; 494800b99b8Sopenharmony_ci } 495800b99b8Sopenharmony_ci#endif 496800b99b8Sopenharmony_ci} 497800b99b8Sopenharmony_ci 498800b99b8Sopenharmony_cibool ProcessDumper::Unwind(std::shared_ptr<ProcessDumpRequest> request, int &dumpRes, pid_t vmPid) 499800b99b8Sopenharmony_ci{ 500800b99b8Sopenharmony_ci // dump unwind should still keep main thread or aim thread is frist unwind 501800b99b8Sopenharmony_ci if (!isCrash_) { 502800b99b8Sopenharmony_ci int tid = request->siginfo.si_value.sival_int; 503800b99b8Sopenharmony_ci tid = tid != 0 ? tid : request->nsPid; 504800b99b8Sopenharmony_ci for (auto &thread : process_->GetOtherThreads()) { 505800b99b8Sopenharmony_ci if (thread->threadInfo_.nsTid == tid) { 506800b99b8Sopenharmony_ci swap(process_->keyThread_, thread); 507800b99b8Sopenharmony_ci break; 508800b99b8Sopenharmony_ci } 509800b99b8Sopenharmony_ci } 510800b99b8Sopenharmony_ci } 511800b99b8Sopenharmony_ci GetCrashObj(request); 512800b99b8Sopenharmony_ci if (!DfxUnwindRemote::GetInstance().UnwindProcess(request, process_, unwinder_, vmPid)) { 513800b99b8Sopenharmony_ci DFXLOGE("Failed to unwind process."); 514800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_ESTOPUNWIND; 515800b99b8Sopenharmony_ci return false; 516800b99b8Sopenharmony_ci } 517800b99b8Sopenharmony_ci 518800b99b8Sopenharmony_ci UnwindWriteJit(*request); 519800b99b8Sopenharmony_ci return true; 520800b99b8Sopenharmony_ci} 521800b99b8Sopenharmony_ci 522800b99b8Sopenharmony_ciint ProcessDumper::DumpProcess(std::shared_ptr<ProcessDumpRequest> request) 523800b99b8Sopenharmony_ci{ 524800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("DumpProcess"); 525800b99b8Sopenharmony_ci int dumpRes = DumpErrorCode::DUMP_ESUCCESS; 526800b99b8Sopenharmony_ci uint32_t opeResult = OPE_SUCCESS; 527800b99b8Sopenharmony_ci do { 528800b99b8Sopenharmony_ci if ((dumpRes = ReadRequestAndCheck(request)) != DumpErrorCode::DUMP_ESUCCESS) { 529800b99b8Sopenharmony_ci break; 530800b99b8Sopenharmony_ci } 531800b99b8Sopenharmony_ci SetProcessdumpTimeout(request->siginfo); 532800b99b8Sopenharmony_ci isCrash_ = request->siginfo.si_signo != SIGDUMP; 533800b99b8Sopenharmony_ci bool isLeakDump = request->siginfo.si_signo == SIGLEAK_STACK; 534800b99b8Sopenharmony_ci // We need check pid is same with getppid(). 535800b99b8Sopenharmony_ci // As in signal handler, current process is a child process, and target pid is our parent process. 536800b99b8Sopenharmony_ci // If pid namespace is enabled, both ppid and pid are equal one. 537800b99b8Sopenharmony_ci // In this case, we have to parse /proc/self/status 538800b99b8Sopenharmony_ci if ((request->dumpMode == SPLIT_MODE) && (((!isCrash_) && (syscall(SYS_getppid) != request->nsPid)) || 539800b99b8Sopenharmony_ci ((isCrash_ || isLeakDump) && (syscall(SYS_getppid) != request->vmNsPid)))) { 540800b99b8Sopenharmony_ci DFXLOGE("Target process(%{public}s:%{public}d) is not parent pid(%{public}ld), " \ 541800b99b8Sopenharmony_ci "exit processdump for signal(%{public}d).", 542800b99b8Sopenharmony_ci request->processName, request->nsPid, syscall(SYS_getppid), request->siginfo.si_signo); 543800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_EGETPPID; 544800b99b8Sopenharmony_ci break; 545800b99b8Sopenharmony_ci } 546800b99b8Sopenharmony_ci DFXLOGW("Processdump SigVal(%{public}d), TargetPid(%{public}d:%{public}d), TargetTid(%{public}d), " \ 547800b99b8Sopenharmony_ci "threadname(%{public}s).", 548800b99b8Sopenharmony_ci request->siginfo.si_value.sival_int, request->pid, request->nsPid, request->tid, request->threadName); 549800b99b8Sopenharmony_ci 550800b99b8Sopenharmony_ci if (InitProcessInfo(request) < 0) { 551800b99b8Sopenharmony_ci DFXLOGE("Failed to init crash process info."); 552800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_EATTACH; 553800b99b8Sopenharmony_ci break; 554800b99b8Sopenharmony_ci } 555800b99b8Sopenharmony_ci InitRegs(request, dumpRes); 556800b99b8Sopenharmony_ci pid_t vmPid = 0; 557800b99b8Sopenharmony_ci if (!InitUnwinder(request, vmPid, dumpRes) && (isCrash_ && !isLeakDump)) { 558800b99b8Sopenharmony_ci opeResult = OPE_FAIL; 559800b99b8Sopenharmony_ci break; 560800b99b8Sopenharmony_ci } 561800b99b8Sopenharmony_ci if (InitPrintThread(request) < 0) { 562800b99b8Sopenharmony_ci DFXLOGE("Failed to init print thread."); 563800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_EGETFD; 564800b99b8Sopenharmony_ci } 565800b99b8Sopenharmony_ci ReadFdTable(*request); 566800b99b8Sopenharmony_ci if (!Unwind(request, dumpRes, vmPid)) { 567800b99b8Sopenharmony_ci opeResult = OPE_FAIL; 568800b99b8Sopenharmony_ci } 569800b99b8Sopenharmony_ci } while (false); 570800b99b8Sopenharmony_ci if (request->dumpMode == FUSION_MODE) { 571800b99b8Sopenharmony_ci InfoRemoteProcessResult(request, opeResult, VIRTUAL_PROCESS); 572800b99b8Sopenharmony_ci } 573800b99b8Sopenharmony_ci if (dumpRes == DumpErrorCode::DUMP_ESUCCESS && !IsTargetProcessAlive(request)) { 574800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_EGETPPID; 575800b99b8Sopenharmony_ci } 576800b99b8Sopenharmony_ci return dumpRes; 577800b99b8Sopenharmony_ci} 578800b99b8Sopenharmony_ci 579800b99b8Sopenharmony_cibool ProcessDumper::InitVmThread(std::shared_ptr<ProcessDumpRequest> request) 580800b99b8Sopenharmony_ci{ 581800b99b8Sopenharmony_ci if (request == nullptr || process_ == nullptr) { 582800b99b8Sopenharmony_ci return false; 583800b99b8Sopenharmony_ci } 584800b99b8Sopenharmony_ci if (isCrash_ && request->vmPid != 0) { 585800b99b8Sopenharmony_ci if (getppid() != request->vmNsPid) { 586800b99b8Sopenharmony_ci DFXLOGE("VM process(%{public}d) should be parent pid.", request->vmNsPid); 587800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 588800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EPARENTPID); 589800b99b8Sopenharmony_ci return false; 590800b99b8Sopenharmony_ci } 591800b99b8Sopenharmony_ci process_->vmThread_ = DfxThread::Create(request->vmPid, request->vmPid, request->vmNsPid); 592800b99b8Sopenharmony_ci if ((process_->vmThread_ == nullptr) || (!process_->vmThread_->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT))) { 593800b99b8Sopenharmony_ci DFXLOGE("Failed to attach vm thread(%{public}d).", request->vmNsPid); 594800b99b8Sopenharmony_ci return false; 595800b99b8Sopenharmony_ci } 596800b99b8Sopenharmony_ci 597800b99b8Sopenharmony_ci process_->vmThread_->SetThreadRegs(DfxRegs::CreateFromUcontext(request->context)); 598800b99b8Sopenharmony_ci process_->vmThread_->threadInfo_.threadName = std::string(request->threadName); 599800b99b8Sopenharmony_ci } 600800b99b8Sopenharmony_ci return true; 601800b99b8Sopenharmony_ci} 602800b99b8Sopenharmony_ci 603800b99b8Sopenharmony_cibool ProcessDumper::InitKeyThread(std::shared_ptr<ProcessDumpRequest> request) 604800b99b8Sopenharmony_ci{ 605800b99b8Sopenharmony_ci if (request == nullptr || process_ == nullptr) { 606800b99b8Sopenharmony_ci return false; 607800b99b8Sopenharmony_ci } 608800b99b8Sopenharmony_ci pid_t nsTid = request->tid; 609800b99b8Sopenharmony_ci pid_t tid = process_->ChangeTid(nsTid, true); 610800b99b8Sopenharmony_ci process_->keyThread_ = DfxThread::Create(process_->processInfo_.pid, tid, nsTid); 611800b99b8Sopenharmony_ci if ((process_->keyThread_ == nullptr) || (!process_->keyThread_->Attach(PTRACE_ATTATCH_KEY_THREAD_TIMEOUT))) { 612800b99b8Sopenharmony_ci DFXLOGE("Failed to attach key thread(%{public}d).", nsTid); 613800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 614800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EATTACH); 615800b99b8Sopenharmony_ci if (!isCrash_) { 616800b99b8Sopenharmony_ci return false; 617800b99b8Sopenharmony_ci } 618800b99b8Sopenharmony_ci } 619800b99b8Sopenharmony_ci if ((process_->keyThread_ != nullptr) && request->dumpMode == FUSION_MODE) { 620800b99b8Sopenharmony_ci ptrace(PTRACE_CONT, process_->keyThread_->threadInfo_.nsTid, 0, 0); 621800b99b8Sopenharmony_ci } 622800b99b8Sopenharmony_ci 623800b99b8Sopenharmony_ci if ((process_->keyThread_ != nullptr) && (request->dumpMode == SPLIT_MODE) && !isCrash_) { 624800b99b8Sopenharmony_ci process_->keyThread_->SetThreadRegs(DfxRegs::CreateFromUcontext(request->context)); 625800b99b8Sopenharmony_ci } 626800b99b8Sopenharmony_ci 627800b99b8Sopenharmony_ci if ((process_->keyThread_ != nullptr) && process_->keyThread_->threadInfo_.threadName.empty()) { 628800b99b8Sopenharmony_ci process_->keyThread_->threadInfo_.threadName = std::string(request->threadName); 629800b99b8Sopenharmony_ci } 630800b99b8Sopenharmony_ci return true; 631800b99b8Sopenharmony_ci} 632800b99b8Sopenharmony_ci 633800b99b8Sopenharmony_cibool ProcessDumper::InitUnwinder(std::shared_ptr<ProcessDumpRequest> request, pid_t &vmPid, int &dumpRes) 634800b99b8Sopenharmony_ci{ 635800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("InitUnwinder"); 636800b99b8Sopenharmony_ci pid_t realPid = 0; 637800b99b8Sopenharmony_ci if (request->dumpMode == FUSION_MODE) { 638800b99b8Sopenharmony_ci ReadPids(realPid, vmPid); 639800b99b8Sopenharmony_ci if (realPid == 0 || vmPid == 0) { 640800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 641800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EREADPID); 642800b99b8Sopenharmony_ci DFXLOGE("Failed to read real pid!"); 643800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_EREADPID; 644800b99b8Sopenharmony_ci return false; 645800b99b8Sopenharmony_ci } 646800b99b8Sopenharmony_ci } 647800b99b8Sopenharmony_ci 648800b99b8Sopenharmony_ci // frezze detach after vm process create 649800b99b8Sopenharmony_ci if (!isCrash_) { 650800b99b8Sopenharmony_ci if (process_->keyThread_ != nullptr) { 651800b99b8Sopenharmony_ci process_->keyThread_->Detach(); 652800b99b8Sopenharmony_ci } 653800b99b8Sopenharmony_ci process_->Detach(); 654800b99b8Sopenharmony_ci DFXLOGI("ptrace detach all tids"); 655800b99b8Sopenharmony_ci } 656800b99b8Sopenharmony_ci 657800b99b8Sopenharmony_ci if (request->dumpMode == FUSION_MODE) { 658800b99b8Sopenharmony_ci unwinder_ = std::make_shared<Unwinder>(realPid, vmPid, isCrash_); 659800b99b8Sopenharmony_ci } else { 660800b99b8Sopenharmony_ci if (isCrash_) { 661800b99b8Sopenharmony_ci unwinder_ = std::make_shared<Unwinder>(process_->vmThread_->threadInfo_.pid); 662800b99b8Sopenharmony_ci } else { 663800b99b8Sopenharmony_ci unwinder_ = std::make_shared<Unwinder>(process_->processInfo_.pid, false); 664800b99b8Sopenharmony_ci } 665800b99b8Sopenharmony_ci } 666800b99b8Sopenharmony_ci if (unwinder_ == nullptr) { 667800b99b8Sopenharmony_ci DFXLOGE("unwinder_ is nullptr!"); 668800b99b8Sopenharmony_ci return false; 669800b99b8Sopenharmony_ci } 670800b99b8Sopenharmony_ci if (unwinder_->GetMaps() == nullptr) { 671800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 672800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_LOG_EMAPLOS); 673800b99b8Sopenharmony_ci DFXLOGE("Mapinfo of crashed process is not exist!"); 674800b99b8Sopenharmony_ci dumpRes = DumpErrorCode::DUMP_ENOMAP; 675800b99b8Sopenharmony_ci return false; 676800b99b8Sopenharmony_ci } 677800b99b8Sopenharmony_ci return true; 678800b99b8Sopenharmony_ci} 679800b99b8Sopenharmony_ci 680800b99b8Sopenharmony_ciint ProcessDumper::InitProcessInfo(std::shared_ptr<ProcessDumpRequest> request) 681800b99b8Sopenharmony_ci{ 682800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("InitProcessInfo"); 683800b99b8Sopenharmony_ci if (request->pid <= 0) { 684800b99b8Sopenharmony_ci return -1; 685800b99b8Sopenharmony_ci } 686800b99b8Sopenharmony_ci process_ = DfxProcess::Create(request->pid, request->nsPid); 687800b99b8Sopenharmony_ci if (process_ == nullptr) { 688800b99b8Sopenharmony_ci return -1; 689800b99b8Sopenharmony_ci } 690800b99b8Sopenharmony_ci if (process_->processInfo_.processName.empty()) { 691800b99b8Sopenharmony_ci process_->processInfo_.processName = std::string(request->processName); 692800b99b8Sopenharmony_ci } 693800b99b8Sopenharmony_ci process_->processInfo_.uid = request->uid; 694800b99b8Sopenharmony_ci process_->recycleTid_ = request->recycleTid; 695800b99b8Sopenharmony_ci process_->SetFatalMessage(request->msg.body); 696800b99b8Sopenharmony_ci 697800b99b8Sopenharmony_ci if (!InitVmThread(request)) { 698800b99b8Sopenharmony_ci return -1; 699800b99b8Sopenharmony_ci } 700800b99b8Sopenharmony_ci 701800b99b8Sopenharmony_ci if (!InitKeyThread(request)) { 702800b99b8Sopenharmony_ci return -1; 703800b99b8Sopenharmony_ci } 704800b99b8Sopenharmony_ci 705800b99b8Sopenharmony_ci DFXLOGI("ptrace attach all tids"); 706800b99b8Sopenharmony_ci bool isLeakDump = request->siginfo.si_signo == SIGLEAK_STACK; 707800b99b8Sopenharmony_ci if (isCrash_ && !isLeakDump) { 708800b99b8Sopenharmony_ci process_->InitOtherThreads(); 709800b99b8Sopenharmony_ci process_->Attach(); 710800b99b8Sopenharmony_ci } else { 711800b99b8Sopenharmony_ci if (!isLeakDump) { 712800b99b8Sopenharmony_ci process_->InitOtherThreads(); 713800b99b8Sopenharmony_ci if (request->dumpMode == FUSION_MODE) { 714800b99b8Sopenharmony_ci process_->Attach(); 715800b99b8Sopenharmony_ci } 716800b99b8Sopenharmony_ci } 717800b99b8Sopenharmony_ci } 718800b99b8Sopenharmony_ci#if defined(PROCESSDUMP_MINIDEBUGINFO) 719800b99b8Sopenharmony_ci UnwinderConfig::SetEnableMiniDebugInfo(true); 720800b99b8Sopenharmony_ci UnwinderConfig::SetEnableLoadSymbolLazily(true); 721800b99b8Sopenharmony_ci#endif 722800b99b8Sopenharmony_ci return 0; 723800b99b8Sopenharmony_ci} 724800b99b8Sopenharmony_ci 725800b99b8Sopenharmony_ciint ProcessDumper::GetLogTypeByRequest(const ProcessDumpRequest &request) 726800b99b8Sopenharmony_ci{ 727800b99b8Sopenharmony_ci switch (request.siginfo.si_signo) { 728800b99b8Sopenharmony_ci case SIGLEAK_STACK: 729800b99b8Sopenharmony_ci switch (request.msg.type) { 730800b99b8Sopenharmony_ci case MESSAGE_FDSAN_DEBUG: 731800b99b8Sopenharmony_ci FALLTHROUGH_INTENDED; 732800b99b8Sopenharmony_ci case MESSAGE_JEMALLOC: 733800b99b8Sopenharmony_ci FALLTHROUGH_INTENDED; 734800b99b8Sopenharmony_ci case MESSAGE_BADFD: 735800b99b8Sopenharmony_ci return FaultLoggerType::CPP_STACKTRACE; 736800b99b8Sopenharmony_ci default: 737800b99b8Sopenharmony_ci return FaultLoggerType::LEAK_STACKTRACE; 738800b99b8Sopenharmony_ci } 739800b99b8Sopenharmony_ci case SIGDUMP: 740800b99b8Sopenharmony_ci return FaultLoggerType::CPP_STACKTRACE; 741800b99b8Sopenharmony_ci default: 742800b99b8Sopenharmony_ci return FaultLoggerType::CPP_CRASH; 743800b99b8Sopenharmony_ci } 744800b99b8Sopenharmony_ci} 745800b99b8Sopenharmony_ci 746800b99b8Sopenharmony_ciint32_t ProcessDumper::CreateFileForCrash(int32_t pid, uint64_t time) const 747800b99b8Sopenharmony_ci{ 748800b99b8Sopenharmony_ci const std::string logFilePath = "/log/crash"; 749800b99b8Sopenharmony_ci const std::string logFileType = "cppcrash"; 750800b99b8Sopenharmony_ci const int32_t logcrashFileProp = 0640; // 0640:-rw-r----- 751800b99b8Sopenharmony_ci if (access(logFilePath.c_str(), F_OK) != 0) { 752800b99b8Sopenharmony_ci DFXLOGE("%{public}s is not exist.", logFilePath.c_str()); 753800b99b8Sopenharmony_ci return INVALID_FD; 754800b99b8Sopenharmony_ci } 755800b99b8Sopenharmony_ci std::string logPath = logFilePath + "/" + logFileType + "-" + std::to_string(pid) + "-" + std::to_string(time); 756800b99b8Sopenharmony_ci int32_t fd = OHOS_TEMP_FAILURE_RETRY(open(logPath.c_str(), O_RDWR | O_CREAT, logcrashFileProp)); 757800b99b8Sopenharmony_ci if (fd == INVALID_FD) { 758800b99b8Sopenharmony_ci DFXLOGE("create %{public}s failed, errno=%{public}d", logPath.c_str(), errno); 759800b99b8Sopenharmony_ci } else { 760800b99b8Sopenharmony_ci DFXLOGI("create crash path %{public}s succ.", logPath.c_str()); 761800b99b8Sopenharmony_ci } 762800b99b8Sopenharmony_ci return fd; 763800b99b8Sopenharmony_ci} 764800b99b8Sopenharmony_ci 765800b99b8Sopenharmony_ciint ProcessDumper::InitPrintThread(std::shared_ptr<ProcessDumpRequest> request) 766800b99b8Sopenharmony_ci{ 767800b99b8Sopenharmony_ci DFX_TRACE_SCOPED("InitPrintThread"); 768800b99b8Sopenharmony_ci int fd = -1; 769800b99b8Sopenharmony_ci struct FaultLoggerdRequest faultloggerdRequest; 770800b99b8Sopenharmony_ci (void)memset_s(&faultloggerdRequest, sizeof(faultloggerdRequest), 0, sizeof(struct FaultLoggerdRequest)); 771800b99b8Sopenharmony_ci faultloggerdRequest.type = ProcessDumper::GetLogTypeByRequest(*request); 772800b99b8Sopenharmony_ci faultloggerdRequest.pid = request->pid; 773800b99b8Sopenharmony_ci faultloggerdRequest.tid = request->tid; 774800b99b8Sopenharmony_ci faultloggerdRequest.uid = request->uid; 775800b99b8Sopenharmony_ci faultloggerdRequest.time = request->timeStamp; 776800b99b8Sopenharmony_ci isJsonDump_ = false; 777800b99b8Sopenharmony_ci jsonFd_ = -1; 778800b99b8Sopenharmony_ci if (isCrash_ || faultloggerdRequest.type == FaultLoggerType::LEAK_STACKTRACE) { 779800b99b8Sopenharmony_ci fd = RequestFileDescriptorEx(&faultloggerdRequest); 780800b99b8Sopenharmony_ci if (fd == -1) { 781800b99b8Sopenharmony_ci fd = CreateFileForCrash(request->pid, request->timeStamp); 782800b99b8Sopenharmony_ci } 783800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().SetWriteFunc(ProcessDumper::WriteDumpBuf); 784800b99b8Sopenharmony_ci } else { 785800b99b8Sopenharmony_ci jsonFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_BUF); 786800b99b8Sopenharmony_ci if (jsonFd_ < 0) { 787800b99b8Sopenharmony_ci // If fd returns -1, we try to obtain the fd that needs to return JSON style 788800b99b8Sopenharmony_ci fd = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_BUF); 789800b99b8Sopenharmony_ci resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_WRITE_RES); 790800b99b8Sopenharmony_ci DFXLOGD("write buf fd: %{public}d, write res fd: %{public}d", fd, resFd_); 791800b99b8Sopenharmony_ci } else { 792800b99b8Sopenharmony_ci resFd_ = RequestPipeFd(request->pid, FaultLoggerPipeType::PIPE_FD_JSON_WRITE_RES); 793800b99b8Sopenharmony_ci DFXLOGD("write json fd: %{public}d, res fd: %{public}d", jsonFd_, resFd_); 794800b99b8Sopenharmony_ci } 795800b99b8Sopenharmony_ci } 796800b99b8Sopenharmony_ci if (jsonFd_ > 0) { 797800b99b8Sopenharmony_ci isJsonDump_ = true; 798800b99b8Sopenharmony_ci } 799800b99b8Sopenharmony_ci if ((fd < 0) && (jsonFd_ < 0)) { 800800b99b8Sopenharmony_ci DFXLOGW("Failed to request fd from faultloggerd."); 801800b99b8Sopenharmony_ci ReportCrashException(request->processName, request->pid, request->uid, 802800b99b8Sopenharmony_ci CrashExceptionCode::CRASH_DUMP_EWRITEFD); 803800b99b8Sopenharmony_ci } 804800b99b8Sopenharmony_ci if (!isJsonDump_) { 805800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().SetWriteBufFd(fd); 806800b99b8Sopenharmony_ci } 807800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().StartThread(); 808800b99b8Sopenharmony_ci return isJsonDump_ ? jsonFd_ : fd; 809800b99b8Sopenharmony_ci} 810800b99b8Sopenharmony_ci 811800b99b8Sopenharmony_ciint ProcessDumper::WriteDumpBuf(int fd, const char* buf, const int len) 812800b99b8Sopenharmony_ci{ 813800b99b8Sopenharmony_ci if (buf == nullptr) { 814800b99b8Sopenharmony_ci return -1; 815800b99b8Sopenharmony_ci } 816800b99b8Sopenharmony_ci return WriteLog(fd, "%s", buf); 817800b99b8Sopenharmony_ci} 818800b99b8Sopenharmony_ci 819800b99b8Sopenharmony_civoid ProcessDumper::WriteDumpRes(int32_t res) 820800b99b8Sopenharmony_ci{ 821800b99b8Sopenharmony_ci DFXLOGI("%{public}s :: res: %{public}d", __func__, res); 822800b99b8Sopenharmony_ci if (resFd_ > 0) { 823800b99b8Sopenharmony_ci ssize_t nwrite = OHOS_TEMP_FAILURE_RETRY(write(resFd_, &res, sizeof(res))); 824800b99b8Sopenharmony_ci if (nwrite < 0) { 825800b99b8Sopenharmony_ci DFXLOGE("%{public}s write fail, err:%{public}d", __func__, errno); 826800b99b8Sopenharmony_ci } 827800b99b8Sopenharmony_ci close(resFd_); 828800b99b8Sopenharmony_ci resFd_ = -1; 829800b99b8Sopenharmony_ci } else { 830800b99b8Sopenharmony_ci if (res != DUMP_ESUCCESS) { 831800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg("Result:\n"); 832800b99b8Sopenharmony_ci DfxRingBufferWrapper::GetInstance().AppendMsg(DfxDumpRes::ToString(res) + "\n"); 833800b99b8Sopenharmony_ci } 834800b99b8Sopenharmony_ci } 835800b99b8Sopenharmony_ci} 836800b99b8Sopenharmony_ci 837800b99b8Sopenharmony_cibool ProcessDumper::IsCrash() const 838800b99b8Sopenharmony_ci{ 839800b99b8Sopenharmony_ci return isCrash_; 840800b99b8Sopenharmony_ci} 841800b99b8Sopenharmony_ci 842800b99b8Sopenharmony_civoid ProcessDumper::ReportSigDumpStats(const std::shared_ptr<ProcessDumpRequest> &request) const 843800b99b8Sopenharmony_ci{ 844800b99b8Sopenharmony_ci if (isCrash_) { 845800b99b8Sopenharmony_ci return; 846800b99b8Sopenharmony_ci } 847800b99b8Sopenharmony_ci 848800b99b8Sopenharmony_ci std::vector<uint8_t> buf(sizeof(struct FaultLoggerdStatsRequest), 0); 849800b99b8Sopenharmony_ci auto stat = reinterpret_cast<struct FaultLoggerdStatsRequest*>(buf.data()); 850800b99b8Sopenharmony_ci stat->type = PROCESS_DUMP; 851800b99b8Sopenharmony_ci stat->pid = request->pid; 852800b99b8Sopenharmony_ci stat->signalTime = request->timeStamp; 853800b99b8Sopenharmony_ci stat->processdumpStartTime = startTime_; 854800b99b8Sopenharmony_ci stat->processdumpFinishTime = finishTime_; 855800b99b8Sopenharmony_ci if (memcpy_s(stat->targetProcess, sizeof(stat->targetProcess), 856800b99b8Sopenharmony_ci request->processName, sizeof(request->processName)) != 0) { 857800b99b8Sopenharmony_ci DFXLOGE("Failed to copy target processName (%{public}d)", errno); 858800b99b8Sopenharmony_ci return; 859800b99b8Sopenharmony_ci } 860800b99b8Sopenharmony_ci 861800b99b8Sopenharmony_ci ReportDumpStats(stat); 862800b99b8Sopenharmony_ci} 863800b99b8Sopenharmony_ci 864800b99b8Sopenharmony_civoid ProcessDumper::ReportCrashInfo(const std::string& jsonInfo) 865800b99b8Sopenharmony_ci{ 866800b99b8Sopenharmony_ci if (reporter_ != nullptr) { 867800b99b8Sopenharmony_ci reporter_->SetCppCrashInfo(jsonInfo); 868800b99b8Sopenharmony_ci reporter_->ReportToHiview(); 869800b99b8Sopenharmony_ci reporter_->ReportToAbilityManagerService(); 870800b99b8Sopenharmony_ci } 871800b99b8Sopenharmony_ci} 872800b99b8Sopenharmony_ci 873800b99b8Sopenharmony_civoid ProcessDumper::ReportAddrSanitizer(ProcessDumpRequest &request, std::string &jsonInfo) 874800b99b8Sopenharmony_ci{ 875800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE 876800b99b8Sopenharmony_ci std::string fingerPrint = request.processName; 877800b99b8Sopenharmony_ci std::string reason = "DEBUG SIGNAL"; 878800b99b8Sopenharmony_ci if (process_ != nullptr && process_->keyThread_ != nullptr) { 879800b99b8Sopenharmony_ci constexpr size_t MAX_FRAME_CNT = 3; 880800b99b8Sopenharmony_ci auto& frames = process_->keyThread_->GetFrames(); 881800b99b8Sopenharmony_ci for (size_t index = 0, cnt = 0; cnt < MAX_FRAME_CNT && index < frames.size(); index++) { 882800b99b8Sopenharmony_ci if (frames[index].mapName.find("ld-musl-", 0) != std::string::npos) { 883800b99b8Sopenharmony_ci continue; 884800b99b8Sopenharmony_ci } 885800b99b8Sopenharmony_ci fingerPrint = fingerPrint + frames[index].funcName; 886800b99b8Sopenharmony_ci cnt++; 887800b99b8Sopenharmony_ci } 888800b99b8Sopenharmony_ci reason = process_->reason; 889800b99b8Sopenharmony_ci } 890800b99b8Sopenharmony_ci size_t hashVal = std::hash<std::string>()(fingerPrint); 891800b99b8Sopenharmony_ci HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::RELIABILITY, "ADDR_SANITIZER", 892800b99b8Sopenharmony_ci OHOS::HiviewDFX::HiSysEvent::EventType::FAULT, 893800b99b8Sopenharmony_ci "MODULE", request.processName, 894800b99b8Sopenharmony_ci "PID", request.pid, 895800b99b8Sopenharmony_ci "HAPPEN_TIME", request.timeStamp, 896800b99b8Sopenharmony_ci "REASON", reason, 897800b99b8Sopenharmony_ci "FINGERPRINT", std::to_string(hashVal)); 898800b99b8Sopenharmony_ci DFXLOGI("%{public}s", "Report fdsan event done."); 899800b99b8Sopenharmony_ci#else 900800b99b8Sopenharmony_ci DFXLOGI("%{public}s", "Not supported for fdsan reporting."); 901800b99b8Sopenharmony_ci#endif 902800b99b8Sopenharmony_ci} 903800b99b8Sopenharmony_ci 904800b99b8Sopenharmony_civoid ProcessDumper::ReadFdTable(const ProcessDumpRequest &request) 905800b99b8Sopenharmony_ci{ 906800b99b8Sopenharmony_ci // Non crash, leak, jemalloc do not read fdtable 907800b99b8Sopenharmony_ci if (!isCrash_ || 908800b99b8Sopenharmony_ci (request.siginfo.si_signo == SIGLEAK_STACK && 909800b99b8Sopenharmony_ci (request.msg.type == NONE || 910800b99b8Sopenharmony_ci request.msg.type == MESSAGE_FATAL || 911800b99b8Sopenharmony_ci request.msg.type == MESSAGE_JEMALLOC))) { 912800b99b8Sopenharmony_ci return; 913800b99b8Sopenharmony_ci } 914800b99b8Sopenharmony_ci process_->openFiles = GetOpenFiles(request.pid, request.nsPid, request.fdTableAddr); 915800b99b8Sopenharmony_ci reporter_ = std::make_shared<CppCrashReporter>(request.timeStamp, process_, request.dumpMode); 916800b99b8Sopenharmony_ci} 917800b99b8Sopenharmony_ci} // namespace HiviewDFX 918800b99b8Sopenharmony_ci} // namespace OHOS 919