1020a203aSopenharmony_ci/* 2020a203aSopenharmony_ci * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4020a203aSopenharmony_ci * you may not use this file except in compliance with the License. 5020a203aSopenharmony_ci * You may obtain a copy of the License at 6020a203aSopenharmony_ci * 7020a203aSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8020a203aSopenharmony_ci * 9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12020a203aSopenharmony_ci * See the License for the specific language governing permissions and 13020a203aSopenharmony_ci * limitations under the License. 14020a203aSopenharmony_ci */ 15020a203aSopenharmony_ci 16020a203aSopenharmony_ci#include <cstdint> 17020a203aSopenharmony_ci#include <ctime> 18020a203aSopenharmony_ci#include <mutex> 19020a203aSopenharmony_ci#include <string> 20020a203aSopenharmony_ci#include <sys/stat.h> 21020a203aSopenharmony_ci#include <vector> 22020a203aSopenharmony_ci 23020a203aSopenharmony_ci#include "constants.h" 24020a203aSopenharmony_ci#include "faultlog_info.h" 25020a203aSopenharmony_ci#include "string_util.h" 26020a203aSopenharmony_ci#include "time_util.h" 27020a203aSopenharmony_ci 28020a203aSopenharmony_cinamespace OHOS { 29020a203aSopenharmony_cinamespace HiviewDFX { 30020a203aSopenharmony_cinamespace { 31020a203aSopenharmony_ciconstexpr int DEFAULT_BUFFER_SIZE = 64; 32020a203aSopenharmony_ciconstexpr const char* const DEFAULT_FAULTLOG_TEMP_FOLDER = "/data/log/faultlog/temp/"; 33020a203aSopenharmony_ci} // namespace 34020a203aSopenharmony_ci 35020a203aSopenharmony_cistd::string GetFormatedTime(uint64_t target) 36020a203aSopenharmony_ci{ 37020a203aSopenharmony_ci time_t now = time(nullptr); 38020a203aSopenharmony_ci if (target > static_cast<uint64_t>(now)) { 39020a203aSopenharmony_ci target = target / 1000; // 1000 : convert millisecond to seconds 40020a203aSopenharmony_ci } 41020a203aSopenharmony_ci 42020a203aSopenharmony_ci time_t out = static_cast<time_t>(target); 43020a203aSopenharmony_ci struct tm tmStruct {0}; 44020a203aSopenharmony_ci struct tm* timeInfo = localtime_r(&out, &tmStruct); 45020a203aSopenharmony_ci if (timeInfo == nullptr) { 46020a203aSopenharmony_ci return "00000000000000"; 47020a203aSopenharmony_ci } 48020a203aSopenharmony_ci 49020a203aSopenharmony_ci char buf[DEFAULT_BUFFER_SIZE] = {0}; 50020a203aSopenharmony_ci strftime(buf, DEFAULT_BUFFER_SIZE - 1, "%Y%m%d%H%M%S", timeInfo); 51020a203aSopenharmony_ci return std::string(buf, strlen(buf)); 52020a203aSopenharmony_ci} 53020a203aSopenharmony_ci 54020a203aSopenharmony_cistd::string GetFaultNameByType(int32_t faultType, bool asFileName) 55020a203aSopenharmony_ci{ 56020a203aSopenharmony_ci switch (faultType) { 57020a203aSopenharmony_ci case FaultLogType::JS_CRASH: 58020a203aSopenharmony_ci return asFileName ? "jscrash" : "JS_ERROR"; 59020a203aSopenharmony_ci case FaultLogType::CPP_CRASH: 60020a203aSopenharmony_ci return asFileName ? "cppcrash" : "CPP_CRASH"; 61020a203aSopenharmony_ci case FaultLogType::APP_FREEZE: 62020a203aSopenharmony_ci return asFileName ? "appfreeze" : "APP_FREEZE"; 63020a203aSopenharmony_ci case FaultLogType::SYS_FREEZE: 64020a203aSopenharmony_ci return asFileName ? "sysfreeze" : "SYS_FREEZE"; 65020a203aSopenharmony_ci case FaultLogType::SYS_WARNING: 66020a203aSopenharmony_ci return asFileName ? "syswarning" : "SYS_WARNING"; 67020a203aSopenharmony_ci case FaultLogType::RUST_PANIC: 68020a203aSopenharmony_ci return asFileName ? "rustpanic" : "RUST_PANIC"; 69020a203aSopenharmony_ci case FaultLogType::ADDR_SANITIZER: 70020a203aSopenharmony_ci return asFileName ? "sanitizer" : "ADDR_SANITIZER"; 71020a203aSopenharmony_ci default: 72020a203aSopenharmony_ci break; 73020a203aSopenharmony_ci } 74020a203aSopenharmony_ci return "Unknown"; 75020a203aSopenharmony_ci} 76020a203aSopenharmony_ci 77020a203aSopenharmony_cistd::string GetFaultLogName(const FaultLogInfo& info) 78020a203aSopenharmony_ci{ 79020a203aSopenharmony_ci std::string name = info.module; 80020a203aSopenharmony_ci if (name.find("/") != std::string::npos) { 81020a203aSopenharmony_ci name = info.module.substr(info.module.find_last_of("/") + 1); 82020a203aSopenharmony_ci } 83020a203aSopenharmony_ci 84020a203aSopenharmony_ci std::string ret = ""; 85020a203aSopenharmony_ci if (info.faultLogType == FaultLogType::ADDR_SANITIZER) { 86020a203aSopenharmony_ci if (info.reason.compare("TSAN") == 0) { 87020a203aSopenharmony_ci ret.append("tsan"); 88020a203aSopenharmony_ci } else if (info.reason.compare("UBSAN") == 0) { 89020a203aSopenharmony_ci ret.append("ubsan"); 90020a203aSopenharmony_ci } else if (info.reason.compare("GWP-ASAN") == 0) { 91020a203aSopenharmony_ci ret.append("gwpasan"); 92020a203aSopenharmony_ci } else if (info.reason.compare("HWASAN") == 0) { 93020a203aSopenharmony_ci ret.append("hwasan"); 94020a203aSopenharmony_ci } else if (info.reason.compare("ASAN") == 0) { 95020a203aSopenharmony_ci ret.append("asan"); 96020a203aSopenharmony_ci } else { 97020a203aSopenharmony_ci ret.append("sanitizer"); 98020a203aSopenharmony_ci } 99020a203aSopenharmony_ci } else { 100020a203aSopenharmony_ci ret.append(GetFaultNameByType(info.faultLogType, true)); 101020a203aSopenharmony_ci } 102020a203aSopenharmony_ci ret.append("-"); 103020a203aSopenharmony_ci ret.append(name); 104020a203aSopenharmony_ci ret.append("-"); 105020a203aSopenharmony_ci ret.append(std::to_string(info.id)); 106020a203aSopenharmony_ci ret.append("-"); 107020a203aSopenharmony_ci ret.append(GetFormatedTime(info.time)); 108020a203aSopenharmony_ci return ret; 109020a203aSopenharmony_ci} 110020a203aSopenharmony_ci 111020a203aSopenharmony_ciint32_t GetLogTypeByName(const std::string& type) 112020a203aSopenharmony_ci{ 113020a203aSopenharmony_ci if (type == "jscrash") { 114020a203aSopenharmony_ci return FaultLogType::JS_CRASH; 115020a203aSopenharmony_ci } else if (type == "cppcrash") { 116020a203aSopenharmony_ci return FaultLogType::CPP_CRASH; 117020a203aSopenharmony_ci } else if (type == "appfreeze") { 118020a203aSopenharmony_ci return FaultLogType::APP_FREEZE; 119020a203aSopenharmony_ci } else if (type == "sysfreeze") { 120020a203aSopenharmony_ci return FaultLogType::SYS_FREEZE; 121020a203aSopenharmony_ci } else if (type == "syswarning") { 122020a203aSopenharmony_ci return FaultLogType::SYS_WARNING; 123020a203aSopenharmony_ci } else if (type == "sanitizer") { 124020a203aSopenharmony_ci return FaultLogType::ADDR_SANITIZER; 125020a203aSopenharmony_ci } else if (type == "all" || type == "ALL") { 126020a203aSopenharmony_ci return FaultLogType::ALL; 127020a203aSopenharmony_ci } else { 128020a203aSopenharmony_ci return -1; 129020a203aSopenharmony_ci } 130020a203aSopenharmony_ci} 131020a203aSopenharmony_ci 132020a203aSopenharmony_ciFaultLogInfo ExtractInfoFromFileName(const std::string& fileName) 133020a203aSopenharmony_ci{ 134020a203aSopenharmony_ci // FileName LogType-PackageName-Uid-YYYYMMDDHHMMSS 135020a203aSopenharmony_ci FaultLogInfo info; 136020a203aSopenharmony_ci std::vector<std::string> splitStr; 137020a203aSopenharmony_ci const int32_t expectedVecSize = 4; 138020a203aSopenharmony_ci StringUtil::SplitStr(fileName, "-", splitStr); 139020a203aSopenharmony_ci if (splitStr.size() == expectedVecSize) { 140020a203aSopenharmony_ci info.faultLogType = GetLogTypeByName(splitStr[0]); // 0 : index of log type 141020a203aSopenharmony_ci info.module = splitStr[1]; // 1 : index of module name 142020a203aSopenharmony_ci StringUtil::ConvertStringTo<int32_t>(splitStr[2], info.id); // 2 : index of uid 143020a203aSopenharmony_ci info.time = TimeUtil::StrToTimeStamp(splitStr[3], "%Y%m%d%H%M%S"); // 3 : index of timestamp 144020a203aSopenharmony_ci } 145020a203aSopenharmony_ci info.pid = 0; 146020a203aSopenharmony_ci return info; 147020a203aSopenharmony_ci} 148020a203aSopenharmony_ci 149020a203aSopenharmony_ciFaultLogInfo ExtractInfoFromTempFile(const std::string& fileName) 150020a203aSopenharmony_ci{ 151020a203aSopenharmony_ci // FileName LogType-pid-time 152020a203aSopenharmony_ci FaultLogInfo info; 153020a203aSopenharmony_ci std::vector<std::string> splitStr; 154020a203aSopenharmony_ci const int32_t expectedVecSize = 3; 155020a203aSopenharmony_ci StringUtil::SplitStr(fileName, "-", splitStr); 156020a203aSopenharmony_ci if (splitStr.size() == expectedVecSize) { 157020a203aSopenharmony_ci info.faultLogType = GetLogTypeByName(splitStr[0]); // 0 : index of log type 158020a203aSopenharmony_ci StringUtil::ConvertStringTo<int32_t>(splitStr[1], info.pid); // 1 : index of pid 159020a203aSopenharmony_ci StringUtil::ConvertStringTo<int64_t>(splitStr[2], info.time); // 2 : index of timestamp 160020a203aSopenharmony_ci } 161020a203aSopenharmony_ci return info; 162020a203aSopenharmony_ci} 163020a203aSopenharmony_ci 164020a203aSopenharmony_cistd::string RegulateModuleNameIfNeed(const std::string& name) 165020a203aSopenharmony_ci{ 166020a203aSopenharmony_ci std::vector<std::string> splitStr; 167020a203aSopenharmony_ci StringUtil::SplitStr(name, "/", splitStr); 168020a203aSopenharmony_ci auto size = splitStr.size(); 169020a203aSopenharmony_ci if (size > 0) { 170020a203aSopenharmony_ci return splitStr[size - 1]; 171020a203aSopenharmony_ci } 172020a203aSopenharmony_ci return name; 173020a203aSopenharmony_ci} 174020a203aSopenharmony_ci 175020a203aSopenharmony_citime_t GetFileLastAccessTimeStamp(const std::string& fileName) 176020a203aSopenharmony_ci{ 177020a203aSopenharmony_ci struct stat fileInfo; 178020a203aSopenharmony_ci if (stat(fileName.c_str(), &fileInfo) != 0) { 179020a203aSopenharmony_ci return 0; 180020a203aSopenharmony_ci } 181020a203aSopenharmony_ci return fileInfo.st_atime; 182020a203aSopenharmony_ci} 183020a203aSopenharmony_ci 184020a203aSopenharmony_cistd::string GetCppCrashTempLogName(const FaultLogInfo& info) 185020a203aSopenharmony_ci{ 186020a203aSopenharmony_ci return std::string(DEFAULT_FAULTLOG_TEMP_FOLDER) + 187020a203aSopenharmony_ci "cppcrash-" + 188020a203aSopenharmony_ci std::to_string(info.pid) + 189020a203aSopenharmony_ci "-" + 190020a203aSopenharmony_ci std::to_string(info.time); 191020a203aSopenharmony_ci} 192020a203aSopenharmony_ci 193020a203aSopenharmony_cistd::string GetThreadStack(const std::string& path, int32_t threadId) 194020a203aSopenharmony_ci{ 195020a203aSopenharmony_ci std::string stack; 196020a203aSopenharmony_ci if (path.empty()) { 197020a203aSopenharmony_ci return stack; 198020a203aSopenharmony_ci } 199020a203aSopenharmony_ci char realPath[PATH_MAX] = {0}; 200020a203aSopenharmony_ci if (realpath(path.c_str(), realPath) == nullptr) { 201020a203aSopenharmony_ci return stack; 202020a203aSopenharmony_ci } 203020a203aSopenharmony_ci if (strncmp(realPath, FaultLogger::FAULTLOG_BASE_FOLDER, strlen(FaultLogger::FAULTLOG_BASE_FOLDER)) != 0) { 204020a203aSopenharmony_ci return stack; 205020a203aSopenharmony_ci } 206020a203aSopenharmony_ci 207020a203aSopenharmony_ci std::ifstream logFile(realPath); 208020a203aSopenharmony_ci if (!logFile.is_open()) { 209020a203aSopenharmony_ci return stack; 210020a203aSopenharmony_ci } 211020a203aSopenharmony_ci std::string regTidString = "^Tid:" + std::to_string(threadId) + ", Name:(.{0,32})$"; 212020a203aSopenharmony_ci std::regex regTid(regTidString); 213020a203aSopenharmony_ci std::regex regStack(R"(^#\d{2,3} (pc|at) .{0,1024}$)"); 214020a203aSopenharmony_ci std::string line; 215020a203aSopenharmony_ci while (std::getline(logFile, line)) { 216020a203aSopenharmony_ci if (!logFile.good()) { 217020a203aSopenharmony_ci break; 218020a203aSopenharmony_ci } 219020a203aSopenharmony_ci 220020a203aSopenharmony_ci if (!std::regex_match(line, regTid)) { 221020a203aSopenharmony_ci continue; 222020a203aSopenharmony_ci } 223020a203aSopenharmony_ci 224020a203aSopenharmony_ci do { 225020a203aSopenharmony_ci stack.append(line + "\n"); 226020a203aSopenharmony_ci if (!logFile.good()) { 227020a203aSopenharmony_ci break; 228020a203aSopenharmony_ci } 229020a203aSopenharmony_ci } while (std::getline(logFile, line) && std::regex_match(line, regStack)); 230020a203aSopenharmony_ci break; 231020a203aSopenharmony_ci } 232020a203aSopenharmony_ci 233020a203aSopenharmony_ci return stack; 234020a203aSopenharmony_ci} 235020a203aSopenharmony_ci} // namespace HiviewDFX 236020a203aSopenharmony_ci} // namespace OHOS 237