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[] = {"PACKAGE", "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[] = {"APPVERSION", "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[] = {"LIFTIME", "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
60 auto JAVA_CRASH_LOG_SEQUENCE = {
61 DEVICE_INFO, BUILD_INFO, MODULE_NAME, MODULE_VERSION, MODULE_PID, MODULE_UID,
62 FAULT_TYPE, FOREGROUND, LIFETIME, REASON, TRACE_ID, STACKTRACE
63 };
64
65 auto CPP_CRASH_LOG_SEQUENCE = {
66 DEVICE_INFO, BUILD_INFO, MODULE_NAME, MODULE_VERSION, MODULE_PID, MODULE_UID, FAULT_TYPE,
67 SYSVMTYPE, APPVMTYPE, REASON, FAULT_MESSAGE, TRACE_ID, PROCESS_NAME, KEY_THREAD_INFO,
68 KEY_THREAD_REGISTERS, OTHER_THREAD_INFO
69 };
70
71 auto JAVASCRIPT_CRASH_LOG_SEQUENCE = {
72 DEVICE_INFO, BUILD_INFO, MODULE_NAME, MODULE_VERSION, MODULE_PID,
73 MODULE_UID, FAULT_TYPE, FAULT_MESSAGE, SYSVMTYPE, APPVMTYPE,
74 FOREGROUND, LIFETIME, REASON, TRACE_ID
75 };
76
77 auto APP_FREEZE_LOG_SEQUENCE = {
78 DEVICE_INFO, BUILD_INFO, MODULE_NAME, MODULE_VERSION, MODULE_PID,
79 MODULE_UID, FAULT_TYPE, SYSVMTYPE, APPVMTYPE, REASON, SUMMARY,
80 TRACE_ID, CPU_USAGE, MEMORY_USAGE, ROOT_CAUSE, STACKTRACE,
81 MSG_QUEUE_INFO, BINDER_TRANSACTION_INFO, PROCESS_STACKTRACE
82 };
83
84 auto SYS_FREEZE_LOG_SEQUENCE = {
85 DEVICE_INFO, BUILD_INFO, MODULE_NAME, MODULE_VERSION, MODULE_PID,
86 MODULE_UID, FAULT_TYPE, SYSVMTYPE, APPVMTYPE, REASON, SUMMARY,
87 TRACE_ID, CPU_USAGE, MEMORY_USAGE, ROOT_CAUSE, STACKTRACE,
88 MSG_QUEUE_INFO, BINDER_TRANSACTION_INFO, PROCESS_STACKTRACE
89 };
90
GetLogParseList(int32_t logType)91 std::list<const char **> GetLogParseList(int32_t logType)
92 {
93 switch (logType) {
94 case FaultLogType::JAVA_CRASH:
95 return JAVA_CRASH_LOG_SEQUENCE;
96 case FaultLogType::CPP_CRASH:
97 return CPP_CRASH_LOG_SEQUENCE;
98 case FaultLogType::JS_CRASH:
99 return JAVASCRIPT_CRASH_LOG_SEQUENCE;
100 case FaultLogType::APP_FREEZE:
101 return APP_FREEZE_LOG_SEQUENCE;
102 case FaultLogType::SYS_FREEZE:
103 return SYS_FREEZE_LOG_SEQUENCE;
104 default:
105 return std::list<const char **>();
106 }
107 }
108
GetSummaryByType(int32_t logType,std::map<std::string,std::string> sections)109 std::string GetSummaryByType(int32_t logType, std::map<std::string, std::string> sections)
110 {
111 std::string summary = "";
112 switch (logType) {
113 case FaultLogType::JAVA_CRASH:
114 case FaultLogType::JS_CRASH:
115 case FaultLogType::APP_FREEZE:
116 case FaultLogType::SYS_FREEZE:
117 summary = sections[STACKTRACE[LOG_MAP_KEY]];
118 break;
119 case FaultLogType::CPP_CRASH:
120 summary = sections[KEY_THREAD_INFO[LOG_MAP_KEY]];
121 break;
122 default:
123 summary = "Could not figure out summary for this fault.";
124 break;
125 }
126
127 return summary;
128 }
129
ParseFaultLogLine(const std::list<const char ** > & parseList,const std::string & line,const std::string & multline,std::string & multlineName,FaultLogInfo & info)130 bool ParseFaultLogLine(const std::list<const char **>& parseList, const std::string& line, const std::string& multline,
131 std::string& multlineName, FaultLogInfo& info)
132 {
133 for (auto &item : parseList) {
134 std::string sectionHead = std::string(item[LOG_MAP_VALUE], strlen(item[LOG_MAP_VALUE]) - 1);
135 if (line.find(sectionHead) != std::string::npos) {
136 if (line.at(line.size() - 1) == ':') {
137 if ((item[LOG_MAP_KEY] != multlineName) && (!multline.empty())) {
138 info.sectionMap[multlineName] = multline;
139 }
140 multlineName = item[LOG_MAP_KEY];
141 } else {
142 info.sectionMap[item[LOG_MAP_KEY]] = line.substr(line.find_first_of(":") + 1);
143 }
144 return false;
145 }
146 }
147 return true;
148 }
149
WriteStackTraceFromLog(int32_t fd,const std::string & pidStr,const std::string & path)150 void WriteStackTraceFromLog(int32_t fd, const std::string& pidStr, const std::string& path)
151 {
152 std::string realPath;
153 if (!FileUtil::PathToRealPath(path, realPath)) {
154 FileUtil::SaveStringToFd(fd, "Log file not exist.\n");
155 return;
156 }
157
158 std::ifstream logFile(realPath);
159 std::string line;
160 bool startWrite = false;
161 while (std::getline(logFile, line)) {
162 if (!logFile.good()) {
163 break;
164 }
165
166 if (line.empty()) {
167 continue;
168 }
169
170 if ((line.find("----- pid") != std::string::npos) &&
171 (line.find(pidStr) != std::string::npos)) {
172 startWrite = true;
173 }
174
175 if ((line.find("----- end") != std::string::npos) &&
176 (line.find(pidStr) != std::string::npos)) {
177 FileUtil::SaveStringToFd(fd, line + "\n");
178 break;
179 }
180
181 if (startWrite) {
182 FileUtil::SaveStringToFd(fd, line + "\n");
183 }
184 }
185 }
186
WriteFaultLogToFile(int32_t fd,int32_t logType,std::map<std::string,std::string> sections)187 void WriteFaultLogToFile(int32_t fd, int32_t logType, std::map<std::string, std::string> sections)
188 {
189 std::list<const char **> seq = GetLogParseList(logType);
190 for (auto &item : seq) {
191 auto value = sections[item[LOG_MAP_KEY]];
192 if (!value.empty()) {
193 FileUtil::SaveStringToFd(fd, item[LOG_MAP_VALUE]);
194 if (value.back() != '\n') {
195 value.append("\n");
196 }
197 FileUtil::SaveStringToFd(fd, value);
198 }
199 }
200
201 auto summary = sections[SUMMARY[LOG_MAP_KEY]];
202 if (!summary.empty()) {
203 FileUtil::SaveStringToFd(fd, summary);
204 }
205
206 if (!sections["KEYLOGFILE"].empty()) {
207 FileUtil::SaveStringToFd(fd, "Additional Logs:\n");
208 WriteStackTraceFromLog(fd, sections["PID"], sections["KEYLOGFILE"]);
209 }
210 }
211
UpdateFaultLogInfoFromTempFile(FaultLogInfo & info)212 static void UpdateFaultLogInfoFromTempFile(FaultLogInfo& info)
213 {
214 if (!info.module.empty()) {
215 return;
216 }
217
218 StringUtil::ConvertStringTo<int32_t>(info.sectionMap[MODULE_UID[LOG_MAP_KEY]], info.id);
219 info.module = info.sectionMap[PROCESS_NAME[LOG_MAP_KEY]];
220 info.reason = info.sectionMap[REASON[LOG_MAP_KEY]];
221 info.summary = info.sectionMap[KEY_THREAD_INFO[LOG_MAP_KEY]];
222 info.sectionMap.clear();
223 }
224
ParseFaultLogInfoFromFile(const std::string & path,bool isTempFile)225 FaultLogInfo ParseFaultLogInfoFromFile(const std::string &path, bool isTempFile)
226 {
227 auto fileName = FileUtil::ExtractFileName(path);
228 FaultLogInfo info;
229 if (!isTempFile) {
230 info = ExtractInfoFromFileName(fileName);
231 } else {
232 info = ExtractInfoFromTempFile(fileName);
233 }
234
235 auto parseList = GetLogParseList(info.faultLogType);
236 std::ifstream logFile(path);
237 std::string line;
238 std::string multline;
239 std::string multlineName;
240 while (std::getline(logFile, line)) {
241 if (!logFile.good()) {
242 break;
243 }
244
245 if (line.empty()) {
246 continue;
247 }
248
249 if (ParseFaultLogLine(parseList, line, multline, multlineName, info)) {
250 multline.append(line).append("\n");
251 }
252 }
253
254 if (!multline.empty() && !multlineName.empty()) {
255 info.sectionMap[multlineName] = multline;
256 }
257 UpdateFaultLogInfoFromTempFile(info);
258 return info;
259 }
260
WriteLogToFile(int32_t fd,const std::string & path)261 bool WriteLogToFile(int32_t fd, const std::string& path)
262 {
263 if ((fd < 0) || path.empty()) {
264 return false;
265 }
266
267 std::string line;
268 std::ifstream logFile(path);
269 while (std::getline(logFile, line)) {
270 if (!logFile.good()) {
271 return false;
272 }
273 FileUtil::SaveStringToFd(fd, line);
274 FileUtil::SaveStringToFd(fd, "\n");
275 }
276 return true;
277 }
278 } // namespace FaultLogger
279 } // namespace HiviewDFX
280 } // namespace OHOS
281