1/* 2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <cstdint> 17#include <ctime> 18#include <mutex> 19#include <string> 20#include <sys/stat.h> 21#include <vector> 22 23#include "constants.h" 24#include "faultlog_info.h" 25#include "string_util.h" 26#include "time_util.h" 27 28namespace OHOS { 29namespace HiviewDFX { 30namespace { 31constexpr int DEFAULT_BUFFER_SIZE = 64; 32constexpr const char* const DEFAULT_FAULTLOG_TEMP_FOLDER = "/data/log/faultlog/temp/"; 33} // namespace 34 35std::string GetFormatedTime(uint64_t target) 36{ 37 time_t now = time(nullptr); 38 if (target > static_cast<uint64_t>(now)) { 39 target = target / 1000; // 1000 : convert millisecond to seconds 40 } 41 42 time_t out = static_cast<time_t>(target); 43 struct tm tmStruct {0}; 44 struct tm* timeInfo = localtime_r(&out, &tmStruct); 45 if (timeInfo == nullptr) { 46 return "00000000000000"; 47 } 48 49 char buf[DEFAULT_BUFFER_SIZE] = {0}; 50 strftime(buf, DEFAULT_BUFFER_SIZE - 1, "%Y%m%d%H%M%S", timeInfo); 51 return std::string(buf, strlen(buf)); 52} 53 54std::string GetFaultNameByType(int32_t faultType, bool asFileName) 55{ 56 switch (faultType) { 57 case FaultLogType::JS_CRASH: 58 return asFileName ? "jscrash" : "JS_ERROR"; 59 case FaultLogType::CPP_CRASH: 60 return asFileName ? "cppcrash" : "CPP_CRASH"; 61 case FaultLogType::APP_FREEZE: 62 return asFileName ? "appfreeze" : "APP_FREEZE"; 63 case FaultLogType::SYS_FREEZE: 64 return asFileName ? "sysfreeze" : "SYS_FREEZE"; 65 case FaultLogType::SYS_WARNING: 66 return asFileName ? "syswarning" : "SYS_WARNING"; 67 case FaultLogType::RUST_PANIC: 68 return asFileName ? "rustpanic" : "RUST_PANIC"; 69 case FaultLogType::ADDR_SANITIZER: 70 return asFileName ? "sanitizer" : "ADDR_SANITIZER"; 71 default: 72 break; 73 } 74 return "Unknown"; 75} 76 77std::string GetFaultLogName(const FaultLogInfo& info) 78{ 79 std::string name = info.module; 80 if (name.find("/") != std::string::npos) { 81 name = info.module.substr(info.module.find_last_of("/") + 1); 82 } 83 84 std::string ret = ""; 85 if (info.faultLogType == FaultLogType::ADDR_SANITIZER) { 86 if (info.reason.compare("TSAN") == 0) { 87 ret.append("tsan"); 88 } else if (info.reason.compare("UBSAN") == 0) { 89 ret.append("ubsan"); 90 } else if (info.reason.compare("GWP-ASAN") == 0) { 91 ret.append("gwpasan"); 92 } else if (info.reason.compare("HWASAN") == 0) { 93 ret.append("hwasan"); 94 } else if (info.reason.compare("ASAN") == 0) { 95 ret.append("asan"); 96 } else { 97 ret.append("sanitizer"); 98 } 99 } else { 100 ret.append(GetFaultNameByType(info.faultLogType, true)); 101 } 102 ret.append("-"); 103 ret.append(name); 104 ret.append("-"); 105 ret.append(std::to_string(info.id)); 106 ret.append("-"); 107 ret.append(GetFormatedTime(info.time)); 108 return ret; 109} 110 111int32_t GetLogTypeByName(const std::string& type) 112{ 113 if (type == "jscrash") { 114 return FaultLogType::JS_CRASH; 115 } else if (type == "cppcrash") { 116 return FaultLogType::CPP_CRASH; 117 } else if (type == "appfreeze") { 118 return FaultLogType::APP_FREEZE; 119 } else if (type == "sysfreeze") { 120 return FaultLogType::SYS_FREEZE; 121 } else if (type == "syswarning") { 122 return FaultLogType::SYS_WARNING; 123 } else if (type == "sanitizer") { 124 return FaultLogType::ADDR_SANITIZER; 125 } else if (type == "all" || type == "ALL") { 126 return FaultLogType::ALL; 127 } else { 128 return -1; 129 } 130} 131 132FaultLogInfo ExtractInfoFromFileName(const std::string& fileName) 133{ 134 // FileName LogType-PackageName-Uid-YYYYMMDDHHMMSS 135 FaultLogInfo info; 136 std::vector<std::string> splitStr; 137 const int32_t expectedVecSize = 4; 138 StringUtil::SplitStr(fileName, "-", splitStr); 139 if (splitStr.size() == expectedVecSize) { 140 info.faultLogType = GetLogTypeByName(splitStr[0]); // 0 : index of log type 141 info.module = splitStr[1]; // 1 : index of module name 142 StringUtil::ConvertStringTo<int32_t>(splitStr[2], info.id); // 2 : index of uid 143 info.time = TimeUtil::StrToTimeStamp(splitStr[3], "%Y%m%d%H%M%S"); // 3 : index of timestamp 144 } 145 info.pid = 0; 146 return info; 147} 148 149FaultLogInfo ExtractInfoFromTempFile(const std::string& fileName) 150{ 151 // FileName LogType-pid-time 152 FaultLogInfo info; 153 std::vector<std::string> splitStr; 154 const int32_t expectedVecSize = 3; 155 StringUtil::SplitStr(fileName, "-", splitStr); 156 if (splitStr.size() == expectedVecSize) { 157 info.faultLogType = GetLogTypeByName(splitStr[0]); // 0 : index of log type 158 StringUtil::ConvertStringTo<int32_t>(splitStr[1], info.pid); // 1 : index of pid 159 StringUtil::ConvertStringTo<int64_t>(splitStr[2], info.time); // 2 : index of timestamp 160 } 161 return info; 162} 163 164std::string RegulateModuleNameIfNeed(const std::string& name) 165{ 166 std::vector<std::string> splitStr; 167 StringUtil::SplitStr(name, "/", splitStr); 168 auto size = splitStr.size(); 169 if (size > 0) { 170 return splitStr[size - 1]; 171 } 172 return name; 173} 174 175time_t GetFileLastAccessTimeStamp(const std::string& fileName) 176{ 177 struct stat fileInfo; 178 if (stat(fileName.c_str(), &fileInfo) != 0) { 179 return 0; 180 } 181 return fileInfo.st_atime; 182} 183 184std::string GetCppCrashTempLogName(const FaultLogInfo& info) 185{ 186 return std::string(DEFAULT_FAULTLOG_TEMP_FOLDER) + 187 "cppcrash-" + 188 std::to_string(info.pid) + 189 "-" + 190 std::to_string(info.time); 191} 192 193std::string GetThreadStack(const std::string& path, int32_t threadId) 194{ 195 std::string stack; 196 if (path.empty()) { 197 return stack; 198 } 199 char realPath[PATH_MAX] = {0}; 200 if (realpath(path.c_str(), realPath) == nullptr) { 201 return stack; 202 } 203 if (strncmp(realPath, FaultLogger::FAULTLOG_BASE_FOLDER, strlen(FaultLogger::FAULTLOG_BASE_FOLDER)) != 0) { 204 return stack; 205 } 206 207 std::ifstream logFile(realPath); 208 if (!logFile.is_open()) { 209 return stack; 210 } 211 std::string regTidString = "^Tid:" + std::to_string(threadId) + ", Name:(.{0,32})$"; 212 std::regex regTid(regTidString); 213 std::regex regStack(R"(^#\d{2,3} (pc|at) .{0,1024}$)"); 214 std::string line; 215 while (std::getline(logFile, line)) { 216 if (!logFile.good()) { 217 break; 218 } 219 220 if (!std::regex_match(line, regTid)) { 221 continue; 222 } 223 224 do { 225 stack.append(line + "\n"); 226 if (!logFile.good()) { 227 break; 228 } 229 } while (std::getline(logFile, line) && std::regex_match(line, regStack)); 230 break; 231 } 232 233 return stack; 234} 235} // namespace HiviewDFX 236} // namespace OHOS 237