• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <securec.h>
20 #include <string>
21 #include <sys/stat.h>
22 #include <vector>
23 
24 #include "constants.h"
25 #include "faultlog_info.h"
26 #include "string_util.h"
27 #include "time_util.h"
28 
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 constexpr int DEFAULT_BUFFER_SIZE = 64;
33 constexpr uint64_t TIME_RATIO = 1000;
34 constexpr const char* const DEFAULT_FAULTLOG_TEMP_FOLDER = "/data/log/faultlog/temp/";
35 constexpr const char* const DEFAULT_FAULTLOG_FOLDER = "/data/log/faultlog/";
36 constexpr const char* const DEFAULT_FAULTLOG_TEST = "/data/test/";
37 } // namespace
38 
GetFormatedTime(uint64_t target)39 std::string GetFormatedTime(uint64_t target)
40 {
41     time_t now = time(nullptr);
42     if (target > static_cast<uint64_t>(now)) {
43         target = target / TIME_RATIO; // 1000 : convert millisecond to seconds
44     }
45 
46     time_t out = static_cast<time_t>(target);
47     struct tm tmStruct {0};
48     struct tm* timeInfo = localtime_r(&out, &tmStruct);
49     if (timeInfo == nullptr) {
50         return "00000000000000";
51     }
52 
53     char buf[DEFAULT_BUFFER_SIZE] = {0};
54     strftime(buf, DEFAULT_BUFFER_SIZE - 1, "%Y%m%d%H%M%S", timeInfo);
55     return std::string(buf, strlen(buf));
56 }
57 
GetFormatedTimeWithMillsec(uint64_t time)58 std::string GetFormatedTimeWithMillsec(uint64_t time)
59 {
60     char millBuf[DEFAULT_BUFFER_SIZE] = {0};
61     int ret = snprintf_s(millBuf, sizeof(millBuf), sizeof(millBuf) - 1, "%03lu", time % TIME_RATIO);
62     if (ret <= 0) {
63         return GetFormatedTime(time) + "000";
64     }
65     std::string millStr(millBuf);
66     return GetFormatedTime(time) + millStr;
67 }
68 
GetFaultNameByType(int32_t faultType,bool asFileName)69 std::string GetFaultNameByType(int32_t faultType, bool asFileName)
70 {
71     switch (faultType) {
72         case FaultLogType::JS_CRASH:
73             return asFileName ? "jscrash" : "JS_ERROR";
74         case FaultLogType::CPP_CRASH:
75             return asFileName ? "cppcrash" : "CPP_CRASH";
76         case FaultLogType::APP_FREEZE:
77             return asFileName ? "appfreeze" : "APP_FREEZE";
78         case FaultLogType::SYS_FREEZE:
79             return asFileName ? "sysfreeze" : "SYS_FREEZE";
80         case FaultLogType::SYS_WARNING:
81             return asFileName ? "syswarning" : "SYS_WARNING";
82         case FaultLogType::RUST_PANIC:
83             return asFileName ? "rustpanic" : "RUST_PANIC";
84         case FaultLogType::ADDR_SANITIZER:
85             return asFileName ? "sanitizer" : "ADDR_SANITIZER";
86         case FaultLogType::CJ_ERROR:
87             return asFileName ? "cjerror" : "CJ_ERROR";
88         default:
89             break;
90     }
91     return "Unknown";
92 }
93 
GetFaultLogName(const FaultLogInfo & info)94 std::string GetFaultLogName(const FaultLogInfo& info)
95 {
96     std::string name = info.module;
97     if (name.find("/") != std::string::npos) {
98         name = info.module.substr(info.module.find_last_of("/") + 1);
99     }
100 
101     std::string ret = "";
102     if (info.faultLogType == FaultLogType::ADDR_SANITIZER) {
103         if (info.sanitizerType.compare("TSAN") == 0) {
104             ret.append("tsan");
105         } else if (info.sanitizerType.compare("UBSAN") == 0) {
106             ret.append("ubsan");
107         } else if (info.sanitizerType.compare("GWP-ASAN") == 0) {
108             ret.append("gwpasan");
109         } else if (info.sanitizerType.compare("HWASAN") == 0) {
110             ret.append("hwasan");
111         } else if (info.sanitizerType.compare("ASAN") == 0) {
112             ret.append("asan");
113         } else {
114             ret.append("sanitizer");
115         }
116     } else {
117         ret.append(GetFaultNameByType(info.faultLogType, true));
118     }
119     ret.append("-");
120     ret.append(name);
121     ret.append("-");
122     ret.append(std::to_string(info.id));
123     ret.append("-");
124     ret.append(GetFormatedTimeWithMillsec(info.time));
125     ret.append(".log");
126     return ret;
127 }
128 
GetLogTypeByName(const std::string & type)129 int32_t GetLogTypeByName(const std::string& type)
130 {
131     if (type == "jscrash") {
132         return FaultLogType::JS_CRASH;
133     } else if (type == "cppcrash") {
134         return FaultLogType::CPP_CRASH;
135     } else if (type == "appfreeze") {
136         return FaultLogType::APP_FREEZE;
137     } else if (type == "sysfreeze") {
138         return FaultLogType::SYS_FREEZE;
139     } else if (type == "syswarning") {
140         return FaultLogType::SYS_WARNING;
141     } else if (type == "sanitizer") {
142         return FaultLogType::ADDR_SANITIZER;
143     } else if (type == "cjerror") {
144         return FaultLogType::CJ_ERROR;
145     } else if (type == "all" || type == "ALL") {
146         return FaultLogType::ALL;
147     } else {
148         return -1;
149     }
150 }
151 
ExtractInfoFromFileName(const std::string & fileName)152 FaultLogInfo ExtractInfoFromFileName(const std::string& fileName)
153 {
154     // FileName LogType-PackageName-Uid-YYYYMMDDHHMMSS
155     FaultLogInfo info;
156     std::vector<std::string> splitStr;
157     const int32_t idxOfType = 0;
158     const int32_t idxOfMoudle = 1;
159     const int32_t idxOfUid = 2;
160     const int32_t idxOfTime = 3;
161     const int32_t expectedVecSize = 4;
162     const size_t tailWithMillSecLen = 7u;
163     const size_t tailWithLogLen = 4u;
164     StringUtil::SplitStr(fileName, "-", splitStr);
165     if (splitStr.size() == expectedVecSize) {
166         info.faultLogType = GetLogTypeByName(splitStr[idxOfType]);
167         info.module = splitStr[idxOfMoudle];
168         StringUtil::ConvertStringTo<int32_t>(splitStr[idxOfUid], info.id);
169         size_t timeStampStrLen = splitStr[idxOfTime].length();
170         if (timeStampStrLen > tailWithMillSecLen &&
171                 splitStr[idxOfTime].substr(timeStampStrLen - tailWithLogLen).compare(".log") == 0) {
172             info.time = TimeUtil::StrToTimeStamp(splitStr[idxOfTime].substr(0, timeStampStrLen - tailWithMillSecLen),
173                 "%Y%m%d%H%M%S");
174         } else {
175             info.time = TimeUtil::StrToTimeStamp(splitStr[idxOfTime], "%Y%m%d%H%M%S");
176         }
177     }
178     info.pid = 0;
179     return info;
180 }
181 
ExtractInfoFromTempFile(const std::string & fileName)182 FaultLogInfo ExtractInfoFromTempFile(const std::string& fileName)
183 {
184     // FileName LogType-pid-time
185     FaultLogInfo info;
186     std::vector<std::string> splitStr;
187     const int32_t expectedVecSize = 3;
188     StringUtil::SplitStr(fileName, "-", splitStr);
189     if (splitStr.size() == expectedVecSize) {
190         info.faultLogType = GetLogTypeByName(splitStr[0]);                 // 0 : index of log type
191         StringUtil::ConvertStringTo<int32_t>(splitStr[1], info.pid);       // 1 : index of pid
192         StringUtil::ConvertStringTo<int64_t>(splitStr[2], info.time);      // 2 : index of timestamp
193     }
194     return info;
195 }
196 
RegulateModuleNameIfNeed(const std::string & name)197 std::string RegulateModuleNameIfNeed(const std::string& name)
198 {
199     std::vector<std::string> splitStr;
200     StringUtil::SplitStr(name, "/", splitStr);
201     auto size = splitStr.size();
202     if (size > 0) {
203         return splitStr[size - 1];
204     }
205     return name;
206 }
207 
GetFileLastAccessTimeStamp(const std::string & fileName)208 time_t GetFileLastAccessTimeStamp(const std::string& fileName)
209 {
210     struct stat fileInfo;
211     if (stat(fileName.c_str(), &fileInfo) != 0) {
212         return 0;
213     }
214     return fileInfo.st_atime;
215 }
216 
GetCppCrashTempLogName(const FaultLogInfo & info)217 std::string GetCppCrashTempLogName(const FaultLogInfo& info)
218 {
219     return std::string(DEFAULT_FAULTLOG_TEMP_FOLDER) +
220         "cppcrash-" +
221         std::to_string(info.pid) +
222         "-" +
223         std::to_string(info.time);
224 }
225 
GetDebugSignalTempLogName(const FaultLogInfo & info)226 std::string GetDebugSignalTempLogName(const FaultLogInfo& info)
227 {
228     return std::string(DEFAULT_FAULTLOG_TEMP_FOLDER) +
229         "stacktrace-" +
230         std::to_string(info.pid) +
231         "-" +
232         std::to_string(info.time);
233 }
234 
GetSanitizerTempLogName(int32_t pid,int64_t happenTime)235 std::string GetSanitizerTempLogName(int32_t pid, int64_t happenTime)
236 {
237     return std::string(DEFAULT_FAULTLOG_TEMP_FOLDER) +
238         "sanitizer-" +
239         std::to_string(pid) +
240         "-" +
241         std::to_string(happenTime);
242 }
243 
GetThreadStack(const std::string & path,int32_t threadId)244 std::string GetThreadStack(const std::string& path, int32_t threadId)
245 {
246     std::string stack;
247     if (path.empty()) {
248         return stack;
249     }
250     char realPath[PATH_MAX] = {0};
251     if (realpath(path.c_str(), realPath) == nullptr) {
252         return stack;
253     }
254     if (strncmp(realPath, FaultLogger::FAULTLOG_BASE_FOLDER, strlen(FaultLogger::FAULTLOG_BASE_FOLDER)) != 0) {
255         return stack;
256     }
257 
258     std::ifstream logFile(realPath);
259     if (!logFile.is_open()) {
260         return stack;
261     }
262     std::string regTidString = "^Tid:" + std::to_string(threadId) + ", Name:(.{0,32})$";
263     std::regex regTid(regTidString);
264     std::regex regStack(R"(^#\d{2,3} (pc|at) .{0,1024}$)");
265     std::string line;
266     while (std::getline(logFile, line)) {
267         if (!logFile.good()) {
268             break;
269         }
270 
271         if (!std::regex_match(line, regTid)) {
272             continue;
273         }
274 
275         do {
276             stack.append(line + "\n");
277             if (!logFile.good()) {
278                 break;
279             }
280         } while (std::getline(logFile, line) && std::regex_match(line, regStack));
281         break;
282     }
283 
284     return stack;
285 }
286 
IsValidPath(const std::string & path)287 bool IsValidPath(const std::string& path)
288 {
289     if (path.size() == 0) {
290         return true;
291     }
292     char realPath[PATH_MAX] = {0};
293     if (realpath(path.c_str(), realPath) == nullptr) {
294         return false;
295     }
296     if (strncmp(realPath, DEFAULT_FAULTLOG_FOLDER, strlen(DEFAULT_FAULTLOG_FOLDER)) == 0 ||
297         strncmp(realPath, DEFAULT_FAULTLOG_TEST, strlen(DEFAULT_FAULTLOG_TEST)) == 0) {
298         return true;
299     }
300     return false;
301 }
302 } // namespace HiviewDFX
303 } // namespace OHOS
304