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