• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 #include "faultlog_formatter.h"
16 
17 #include <cstdint>
18 #include <fstream>
19 #include <list>
20 #include <sstream>
21 #include <string>
22 
23 #include "faultlog_info.h"
24 #include "faultlog_util.h"
25 #include "file_util.h"
26 #include "string_util.h"
27 
28 namespace OHOS {
29 namespace HiviewDFX {
30 namespace FaultLogger {
31 constexpr int LOG_MAP_KEY = 0;
32 constexpr int LOG_MAP_VALUE = 1;
33 static const char *DEVICE_INFO[] = {"DEVICE_INFO", "Device info:"};
34 static const char *BUILD_INFO[] = {"BUILD_INFO", "Build info:"};
35 static const char *MODULE_NAME[] = {"MODULE", "Module name:"};
36 static const char *PROCESS_NAME[] = {"PNAME", "Process name:"};
37 static const char *MODULE_PID[] = {"PID", "Pid:"};
38 static const char *MODULE_UID[] = {"UID", "Uid:"};
39 static const char *MODULE_VERSION[] = {"VERSION", "Version:"};
40 static const char *FAULT_TYPE[] = {"FAULT_TYPE", "Fault type:"};
41 static const char *SYSVMTYPE[] = {"SYSVMTYPE", "SYSVMTYPE:"};
42 static const char *APPVMTYPE[] = {"APPVMTYPE", "APPVMTYPE:"};
43 static const char *FOREGROUND[] = {"FG", "Foreground:"};
44 static const char *LIFETIME[] = {"LIFETIME", "Up time:"};
45 static const char *REASON[] = {"REASON", "Reason:"};
46 static const char *FAULT_MESSAGE[] = {"FAULT_MESSAGE", "Fault message:"};
47 static const char *STACKTRACE[] = {"TRUSTSTACK", "Selected stacktrace:\n"};
48 static const char *ROOT_CAUSE[] = {"BINDERMAX", "Blocked chain:\n"};
49 static const char *MSG_QUEUE_INFO[] = {"MSG_QUEUE_INFO", "Message queue info:\n"};
50 static const char *BINDER_TRANSACTION_INFO[] = {"BINDER_TRANSACTION_INFO", "Binder transaction info:\n"};
51 static const char *PROCESS_STACKTRACE[] = {"PROCESS_STACKTRACE", "Process stacktrace:\n"};
52 static const char *OTHER_THREAD_INFO[] = {"OTHER_THREAD_INFO", "Other thread info:\n"};
53 static const char *KEY_THREAD_INFO[] = {"KEY_THREAD_INFO", "Fault thread Info:\n"};
54 static const char *KEY_THREAD_REGISTERS[] = {"KEY_THREAD_REGISTERS", "Registers:\n"};
55 static const char *MEMORY_USAGE[] = {"MEM_USAGE", "Memory Usage:\n"};
56 static const char *CPU_USAGE[] = {"FAULTCPU", "CPU Usage:"};
57 static const char *TRACE_ID[] = {"TRACEID", "Trace-Id:"};
58 static const char *SUMMARY[] = {"SUMMARY", "Summary:\n"};
59 static const char *TIMESTAMP[] = {"TIMESTAMP", "Timestamp:"};
60 
61 auto CPP_CRASH_LOG_SEQUENCE = {
62     DEVICE_INFO,      BUILD_INFO, TIMESTAMP, MODULE_NAME, MODULE_VERSION, MODULE_PID, MODULE_UID,      FAULT_TYPE,
63     SYSVMTYPE,        APPVMTYPE,  REASON,      FAULT_MESSAGE,  TRACE_ID,   PROCESS_NAME,    KEY_THREAD_INFO,
64     KEY_THREAD_REGISTERS, OTHER_THREAD_INFO
65 };
66 
67 auto JAVASCRIPT_CRASH_LOG_SEQUENCE = {
68     DEVICE_INFO, BUILD_INFO, TIMESTAMP, MODULE_NAME,   MODULE_VERSION, MODULE_PID,
69     MODULE_UID,  FAULT_TYPE, FAULT_MESSAGE, SYSVMTYPE,      APPVMTYPE,
70     FOREGROUND,  LIFETIME,   REASON,        TRACE_ID
71 };
72 
73 auto APP_FREEZE_LOG_SEQUENCE = {
74     DEVICE_INFO, BUILD_INFO, TIMESTAMP, MODULE_NAME, MODULE_VERSION, MODULE_PID,
75     MODULE_UID, FAULT_TYPE, SYSVMTYPE, APPVMTYPE, REASON,
76     TRACE_ID, CPU_USAGE, MEMORY_USAGE, ROOT_CAUSE, STACKTRACE,
77     MSG_QUEUE_INFO, BINDER_TRANSACTION_INFO, PROCESS_STACKTRACE
78 };
79 
80 auto SYS_FREEZE_LOG_SEQUENCE = {
81     DEVICE_INFO, BUILD_INFO, TIMESTAMP, MODULE_NAME, MODULE_VERSION, MODULE_PID,
82     MODULE_UID, FAULT_TYPE, SYSVMTYPE, APPVMTYPE, REASON,
83     TRACE_ID, CPU_USAGE, MEMORY_USAGE, ROOT_CAUSE, STACKTRACE,
84     MSG_QUEUE_INFO, BINDER_TRANSACTION_INFO, PROCESS_STACKTRACE
85 };
86 
GetLogParseList(int32_t logType)87 std::list<const char **> GetLogParseList(int32_t logType)
88 {
89     switch (logType) {
90         case FaultLogType::CPP_CRASH:
91             return CPP_CRASH_LOG_SEQUENCE;
92         case FaultLogType::JS_CRASH:
93             return JAVASCRIPT_CRASH_LOG_SEQUENCE;
94         case FaultLogType::APP_FREEZE:
95             return APP_FREEZE_LOG_SEQUENCE;
96         case FaultLogType::SYS_FREEZE:
97             return SYS_FREEZE_LOG_SEQUENCE;
98         default:
99             return std::list<const char **>();
100     }
101 }
102 
GetSummaryByType(int32_t logType,std::map<std::string,std::string> sections)103 std::string GetSummaryByType(int32_t logType, std::map<std::string, std::string> sections)
104 {
105     std::string summary = "";
106     switch (logType) {
107         case FaultLogType::JS_CRASH:
108         case FaultLogType::APP_FREEZE:
109         case FaultLogType::SYS_FREEZE:
110             summary = sections[STACKTRACE[LOG_MAP_KEY]];
111             break;
112         case FaultLogType::CPP_CRASH:
113             summary = sections[KEY_THREAD_INFO[LOG_MAP_KEY]];
114             break;
115         default:
116             summary = "Could not figure out summary for this fault.";
117             break;
118     }
119 
120     return summary;
121 }
122 
ParseFaultLogLine(const std::list<const char ** > & parseList,const std::string & line,const std::string & multline,std::string & multlineName,FaultLogInfo & info)123 bool ParseFaultLogLine(const std::list<const char **>& parseList, const std::string& line, const std::string& multline,
124     std::string& multlineName, FaultLogInfo& info)
125 {
126     for (auto &item : parseList) {
127         std::string sectionHead = std::string(item[LOG_MAP_VALUE], strlen(item[LOG_MAP_VALUE]) - 1);
128         if (line.find(sectionHead) != std::string::npos) {
129             if (line.at(line.size() - 1) == ':') {
130                 if ((item[LOG_MAP_KEY] != multlineName) && (!multline.empty())) {
131                     info.sectionMap[multlineName] = multline;
132                 }
133                 multlineName = item[LOG_MAP_KEY];
134             } else {
135                 info.sectionMap[item[LOG_MAP_KEY]] = line.substr(line.find_first_of(":") + 1);
136             }
137             return false;
138         }
139     }
140     return true;
141 }
142 
WriteStackTraceFromLog(int32_t fd,const std::string & pidStr,const std::string & path)143 void WriteStackTraceFromLog(int32_t fd, const std::string& pidStr, const std::string& path)
144 {
145     std::string realPath;
146     if (!FileUtil::PathToRealPath(path, realPath)) {
147         FileUtil::SaveStringToFd(fd, "Log file not exist.\n");
148         return;
149     }
150 
151     std::ifstream logFile(realPath);
152     std::string line;
153     bool startWrite = false;
154     while (std::getline(logFile, line)) {
155         if (!logFile.good()) {
156             break;
157         }
158 
159         if (line.empty()) {
160             continue;
161         }
162 
163         if ((line.find("----- pid") != std::string::npos) &&
164             (line.find(pidStr) != std::string::npos)) {
165             startWrite = true;
166         }
167 
168         if ((line.find("----- end") != std::string::npos) &&
169             (line.find(pidStr) != std::string::npos)) {
170             FileUtil::SaveStringToFd(fd, line + "\n");
171             break;
172         }
173 
174         if (startWrite) {
175             FileUtil::SaveStringToFd(fd, line + "\n");
176         }
177     }
178 }
179 
WriteDfxLogToFile(int32_t fd)180 void WriteDfxLogToFile(int32_t fd)
181 {
182     std::string dfxStr = std::string("Generated by HiviewDFX@OpenHarmony\n");
183     std::string sepStr = std::string("================================================================\n");
184     FileUtil::SaveStringToFd(fd, dfxStr);
185     FileUtil::SaveStringToFd(fd, sepStr);
186 }
187 
WriteFaultLogToFile(int32_t fd,int32_t logType,std::map<std::string,std::string> sections)188 void WriteFaultLogToFile(int32_t fd, int32_t logType, std::map<std::string, std::string> sections)
189 {
190     std::list<const char **> seq = GetLogParseList(logType);
191     for (auto &item : seq) {
192         auto value = sections[item[LOG_MAP_KEY]];
193         if (!value.empty()) {
194             FileUtil::SaveStringToFd(fd, item[LOG_MAP_VALUE]);
195             if (value.back() != '\n') {
196                 value.append("\n");
197             }
198             FileUtil::SaveStringToFd(fd, value);
199         }
200     }
201 
202     auto summary = sections[SUMMARY[LOG_MAP_KEY]];
203     if (!summary.empty()) {
204         FileUtil::SaveStringToFd(fd, summary);
205     }
206 
207     if (!sections["KEYLOGFILE"].empty()) {
208         FileUtil::SaveStringToFd(fd, "Additional Logs:\n");
209         WriteStackTraceFromLog(fd, sections["PID"], sections["KEYLOGFILE"]);
210     }
211 }
212 
UpdateFaultLogInfoFromTempFile(FaultLogInfo & info)213 static void UpdateFaultLogInfoFromTempFile(FaultLogInfo& info)
214 {
215     if (!info.module.empty()) {
216         return;
217     }
218 
219     StringUtil::ConvertStringTo<int32_t>(info.sectionMap[MODULE_UID[LOG_MAP_KEY]], info.id);
220     info.module = info.sectionMap[PROCESS_NAME[LOG_MAP_KEY]];
221     info.reason = info.sectionMap[REASON[LOG_MAP_KEY]];
222     info.summary = info.sectionMap[KEY_THREAD_INFO[LOG_MAP_KEY]];
223     info.sectionMap.clear();
224 }
225 
ParseFaultLogInfoFromFile(const std::string & path,bool isTempFile)226 FaultLogInfo ParseFaultLogInfoFromFile(const std::string &path, bool isTempFile)
227 {
228     auto fileName = FileUtil::ExtractFileName(path);
229     FaultLogInfo info;
230     if (!isTempFile) {
231         info = ExtractInfoFromFileName(fileName);
232     } else {
233         info = ExtractInfoFromTempFile(fileName);
234     }
235 
236     auto parseList = GetLogParseList(info.faultLogType);
237     std::ifstream logFile(path);
238     std::string line;
239     std::string multline;
240     std::string multlineName;
241     while (std::getline(logFile, line)) {
242         if (!logFile.good()) {
243             break;
244         }
245 
246         if (line.empty()) {
247             continue;
248         }
249 
250         if (ParseFaultLogLine(parseList, line, multline, multlineName, info)) {
251             multline.append(line).append("\n");
252         }
253     }
254 
255     if (!multline.empty() && !multlineName.empty()) {
256         info.sectionMap[multlineName] = multline;
257     }
258     UpdateFaultLogInfoFromTempFile(info);
259     return info;
260 }
261 
WriteLogToFile(int32_t fd,const std::string & path)262 bool WriteLogToFile(int32_t fd, const std::string& path)
263 {
264     if ((fd < 0) || path.empty()) {
265         return false;
266     }
267 
268     std::string line;
269     std::ifstream logFile(path);
270     while (std::getline(logFile, line)) {
271         if (!logFile.good()) {
272             return false;
273         }
274         FileUtil::SaveStringToFd(fd, line);
275         FileUtil::SaveStringToFd(fd, "\n");
276     }
277     return true;
278 }
279 } // namespace FaultLogger
280 } // namespace HiviewDFX
281 } // namespace OHOS
282