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 "cppcrash_reporter.h" 17800b99b8Sopenharmony_ci 18800b99b8Sopenharmony_ci#include <cinttypes> 19800b99b8Sopenharmony_ci#include <dlfcn.h> 20800b99b8Sopenharmony_ci#include <fcntl.h> 21800b99b8Sopenharmony_ci#include <map> 22800b99b8Sopenharmony_ci#include <string> 23800b99b8Sopenharmony_ci#include "dfx_define.h" 24800b99b8Sopenharmony_ci#include "dfx_logger.h" 25800b99b8Sopenharmony_ci#include "dfx_process.h" 26800b99b8Sopenharmony_ci#include "dfx_signal.h" 27800b99b8Sopenharmony_ci#include "dfx_thread.h" 28800b99b8Sopenharmony_ci#include "faultlogger_client_msg.h" 29800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE 30800b99b8Sopenharmony_ci#include "hisysevent.h" 31800b99b8Sopenharmony_ci#endif 32800b99b8Sopenharmony_ci 33800b99b8Sopenharmony_cistatic const char FOUNDATION_PROCESS_NAME[] = "foundation"; 34800b99b8Sopenharmony_cistatic const char HIVIEW_PROCESS_NAME[] = "/system/bin/hiview"; 35800b99b8Sopenharmony_cistatic const char REGS_KEY_WORD[] = "Registers:\n"; 36800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE 37800b99b8Sopenharmony_cistatic const char KILL_REASON_CPP_CRASH[] = "Kill Reason:Cpp Crash"; 38800b99b8Sopenharmony_ci#endif 39800b99b8Sopenharmony_ci 40800b99b8Sopenharmony_ciusing RecordAppExitReason = int (*)(int reason, const char *exitMsg); 41800b99b8Sopenharmony_ci 42800b99b8Sopenharmony_cinamespace OHOS { 43800b99b8Sopenharmony_cinamespace HiviewDFX { 44800b99b8Sopenharmony_ci 45800b99b8Sopenharmony_cibool CppCrashReporter::Format() 46800b99b8Sopenharmony_ci{ 47800b99b8Sopenharmony_ci if (process_ == nullptr) { 48800b99b8Sopenharmony_ci return false; 49800b99b8Sopenharmony_ci } 50800b99b8Sopenharmony_ci 51800b99b8Sopenharmony_ci cmdline_ = process_->processInfo_.processName; 52800b99b8Sopenharmony_ci pid_ = process_->processInfo_.pid; 53800b99b8Sopenharmony_ci uid_ = process_->processInfo_.uid; 54800b99b8Sopenharmony_ci reason_ = process_->reason; 55800b99b8Sopenharmony_ci auto msg = process_->GetFatalMessage(); 56800b99b8Sopenharmony_ci if (!msg.empty()) { 57800b99b8Sopenharmony_ci stack_ = "LastFatalMessage:" + msg + "\n"; 58800b99b8Sopenharmony_ci } 59800b99b8Sopenharmony_ci std::shared_ptr<DfxThread> thread = dumpMode_ == FUSION_MODE ? process_->keyThread_ : process_->vmThread_; 60800b99b8Sopenharmony_ci if (thread != nullptr) { 61800b99b8Sopenharmony_ci std::string threadInfo = thread->ToString(); 62800b99b8Sopenharmony_ci auto iterator = threadInfo.begin(); 63800b99b8Sopenharmony_ci while (iterator != threadInfo.end() && *iterator != '\n') { 64800b99b8Sopenharmony_ci if (isdigit(*iterator)) { 65800b99b8Sopenharmony_ci iterator = threadInfo.erase(iterator); 66800b99b8Sopenharmony_ci } else { 67800b99b8Sopenharmony_ci iterator++; 68800b99b8Sopenharmony_ci } 69800b99b8Sopenharmony_ci } 70800b99b8Sopenharmony_ci stack_ += threadInfo; 71800b99b8Sopenharmony_ci 72800b99b8Sopenharmony_ci // regs 73800b99b8Sopenharmony_ci registers_ = GetRegsString(process_->regs_); 74800b99b8Sopenharmony_ci } 75800b99b8Sopenharmony_ci return true; 76800b99b8Sopenharmony_ci} 77800b99b8Sopenharmony_ci 78800b99b8Sopenharmony_civoid CppCrashReporter::ReportToHiview() 79800b99b8Sopenharmony_ci{ 80800b99b8Sopenharmony_ci if (!Format()) { 81800b99b8Sopenharmony_ci DFXLOGW("Failed to format crash report."); 82800b99b8Sopenharmony_ci return; 83800b99b8Sopenharmony_ci } 84800b99b8Sopenharmony_ci if (process_->processInfo_.processName.find(HIVIEW_PROCESS_NAME) != std::string::npos) { 85800b99b8Sopenharmony_ci DFXLOGW("Failed to report, hiview is crashed."); 86800b99b8Sopenharmony_ci return; 87800b99b8Sopenharmony_ci } 88800b99b8Sopenharmony_ci 89800b99b8Sopenharmony_ci void* handle = dlopen("libfaultlogger.z.so", RTLD_LAZY | RTLD_NODELETE); 90800b99b8Sopenharmony_ci if (handle == nullptr) { 91800b99b8Sopenharmony_ci DFXLOGW("Failed to dlopen libfaultlogger, %{public}s\n", dlerror()); 92800b99b8Sopenharmony_ci return; 93800b99b8Sopenharmony_ci } 94800b99b8Sopenharmony_ci 95800b99b8Sopenharmony_ci auto addFaultLog = reinterpret_cast<void (*)(FaultDFXLOGIInner*)>(dlsym(handle, "AddFaultLog")); 96800b99b8Sopenharmony_ci if (addFaultLog == nullptr) { 97800b99b8Sopenharmony_ci DFXLOGW("Failed to dlsym AddFaultLog, %{public}s\n", dlerror()); 98800b99b8Sopenharmony_ci dlclose(handle); 99800b99b8Sopenharmony_ci return; 100800b99b8Sopenharmony_ci } 101800b99b8Sopenharmony_ci 102800b99b8Sopenharmony_ci FaultDFXLOGIInner info; 103800b99b8Sopenharmony_ci info.time = time_; 104800b99b8Sopenharmony_ci info.id = uid_; 105800b99b8Sopenharmony_ci info.pid = pid_; 106800b99b8Sopenharmony_ci info.pipeFd = WriteCppCrashInfoByPipe(); 107800b99b8Sopenharmony_ci info.faultLogType = 2; // 2 : CPP_CRASH_TYPE 108800b99b8Sopenharmony_ci info.module = cmdline_; 109800b99b8Sopenharmony_ci info.reason = reason_; 110800b99b8Sopenharmony_ci info.summary = stack_; 111800b99b8Sopenharmony_ci info.registers = registers_; 112800b99b8Sopenharmony_ci addFaultLog(&info); 113800b99b8Sopenharmony_ci DFXLOGI("Finish report fault to FaultLogger %{public}s(%{public}d,%{public}d)", cmdline_.c_str(), pid_, uid_); 114800b99b8Sopenharmony_ci dlclose(handle); 115800b99b8Sopenharmony_ci} 116800b99b8Sopenharmony_ci 117800b99b8Sopenharmony_ci// read fd will be closed after transfering to hiview 118800b99b8Sopenharmony_ciint32_t CppCrashReporter::WriteCppCrashInfoByPipe() 119800b99b8Sopenharmony_ci{ 120800b99b8Sopenharmony_ci size_t sz = cppCrashInfo_.size(); 121800b99b8Sopenharmony_ci if (sz > MAX_PIPE_SIZE) { 122800b99b8Sopenharmony_ci DFXLOGE("the size of json string is greater than max pipe size, do not report"); 123800b99b8Sopenharmony_ci return -1; 124800b99b8Sopenharmony_ci } 125800b99b8Sopenharmony_ci int pipeFd[2] = {-1, -1}; 126800b99b8Sopenharmony_ci if (pipe(pipeFd) != 0) { 127800b99b8Sopenharmony_ci DFXLOGE("Failed to create pipe."); 128800b99b8Sopenharmony_ci return -1; 129800b99b8Sopenharmony_ci } 130800b99b8Sopenharmony_ci if (fcntl(pipeFd[PIPE_READ], F_SETPIPE_SZ, sz) < 0 || 131800b99b8Sopenharmony_ci fcntl(pipeFd[PIPE_WRITE], F_SETPIPE_SZ, sz) < 0) { 132800b99b8Sopenharmony_ci DFXLOGE("[%{public}d]: failed to set pipe size.", __LINE__); 133800b99b8Sopenharmony_ci return -1; 134800b99b8Sopenharmony_ci } 135800b99b8Sopenharmony_ci if (fcntl(pipeFd[PIPE_READ], F_GETFL) < 0) { 136800b99b8Sopenharmony_ci DFXLOGE("[%{public}d]: failed to set pipe size.", __LINE__); 137800b99b8Sopenharmony_ci return -1; 138800b99b8Sopenharmony_ci } else { 139800b99b8Sopenharmony_ci uint32_t flags = static_cast<uint32_t>(fcntl(pipeFd[PIPE_READ], F_GETFL)); 140800b99b8Sopenharmony_ci flags |= O_NONBLOCK; 141800b99b8Sopenharmony_ci if (fcntl(pipeFd[PIPE_READ], F_SETFL, flags) < 0) { 142800b99b8Sopenharmony_ci DFXLOGE("Failed to set pipe flag."); 143800b99b8Sopenharmony_ci return -1; 144800b99b8Sopenharmony_ci } 145800b99b8Sopenharmony_ci } 146800b99b8Sopenharmony_ci ssize_t realWriteSize = -1; 147800b99b8Sopenharmony_ci realWriteSize = OHOS_TEMP_FAILURE_RETRY(write(pipeFd[PIPE_WRITE], cppCrashInfo_.c_str(), sz)); 148800b99b8Sopenharmony_ci close(pipeFd[PIPE_WRITE]); 149800b99b8Sopenharmony_ci if (static_cast<ssize_t>(cppCrashInfo_.size()) != realWriteSize) { 150800b99b8Sopenharmony_ci DFXLOGE("Failed to write pipe. realWriteSize %{public}zd, json size %{public}zd", realWriteSize, sz); 151800b99b8Sopenharmony_ci close(pipeFd[PIPE_READ]); 152800b99b8Sopenharmony_ci return -1; 153800b99b8Sopenharmony_ci } 154800b99b8Sopenharmony_ci return pipeFd[PIPE_READ]; 155800b99b8Sopenharmony_ci} 156800b99b8Sopenharmony_ci 157800b99b8Sopenharmony_civoid CppCrashReporter::ReportToAbilityManagerService() 158800b99b8Sopenharmony_ci{ 159800b99b8Sopenharmony_ci if (process_->processInfo_.processName.find(FOUNDATION_PROCESS_NAME) != std::string::npos) { 160800b99b8Sopenharmony_ci DFXLOGW("Do not to report to AbilityManagerService, foundation is crashed."); 161800b99b8Sopenharmony_ci return; 162800b99b8Sopenharmony_ci } 163800b99b8Sopenharmony_ci 164800b99b8Sopenharmony_ci void* handle = dlopen("libability_manager_c.z.so", RTLD_LAZY | RTLD_NODELETE); 165800b99b8Sopenharmony_ci if (handle == nullptr) { 166800b99b8Sopenharmony_ci DFXLOGW("Failed to dlopen libabilityms, %{public}s\n", dlerror()); 167800b99b8Sopenharmony_ci return; 168800b99b8Sopenharmony_ci } 169800b99b8Sopenharmony_ci 170800b99b8Sopenharmony_ci RecordAppExitReason recordAppExitReason = (RecordAppExitReason)dlsym(handle, "RecordAppExitReason"); 171800b99b8Sopenharmony_ci if (recordAppExitReason == nullptr) { 172800b99b8Sopenharmony_ci DFXLOGW("Failed to dlsym RecordAppExitReason, %{public}s\n", dlerror()); 173800b99b8Sopenharmony_ci dlclose(handle); 174800b99b8Sopenharmony_ci return; 175800b99b8Sopenharmony_ci } 176800b99b8Sopenharmony_ci 177800b99b8Sopenharmony_ci // defined in interfaces/inner_api/ability_manager/include/ability_state.h 178800b99b8Sopenharmony_ci const int cppCrashExitReason = 2; 179800b99b8Sopenharmony_ci recordAppExitReason(cppCrashExitReason, reason_.c_str()); 180800b99b8Sopenharmony_ci dlclose(handle); 181800b99b8Sopenharmony_ci#ifndef HISYSEVENT_DISABLE 182800b99b8Sopenharmony_ci int result = HiSysEventWrite(HiSysEvent::Domain::FRAMEWORK, "PROCESS_KILL", HiSysEvent::EventType::FAULT, 183800b99b8Sopenharmony_ci "PID", pid_, "PROCESS_NAME", cmdline_.c_str(), "MSG", KILL_REASON_CPP_CRASH); 184800b99b8Sopenharmony_ci DFXLOGW("hisysevent write result=%{public}d, send event [FRAMEWORK,PROCESS_KILL], pid=%{public}d," 185800b99b8Sopenharmony_ci " processName=%{public}s, msg=%{public}s", result, pid_, cmdline_.c_str(), KILL_REASON_CPP_CRASH); 186800b99b8Sopenharmony_ci#endif 187800b99b8Sopenharmony_ci} 188800b99b8Sopenharmony_ci 189800b99b8Sopenharmony_cistd::string CppCrashReporter::GetRegsString(std::shared_ptr<DfxRegs> regs) 190800b99b8Sopenharmony_ci{ 191800b99b8Sopenharmony_ci std::string regsString = ""; 192800b99b8Sopenharmony_ci if (regs == nullptr) { 193800b99b8Sopenharmony_ci return regsString; 194800b99b8Sopenharmony_ci } 195800b99b8Sopenharmony_ci regsString = regs->PrintRegs(); 196800b99b8Sopenharmony_ci // if start with 'Registers:\n', need remove 197800b99b8Sopenharmony_ci if (regsString.find(REGS_KEY_WORD) == 0) { 198800b99b8Sopenharmony_ci regsString = regsString.substr(strlen(REGS_KEY_WORD)); 199800b99b8Sopenharmony_ci } 200800b99b8Sopenharmony_ci return regsString; 201800b99b8Sopenharmony_ci} 202800b99b8Sopenharmony_ci} // namespace HiviewDFX 203800b99b8Sopenharmony_ci} // namespace OHOS 204