1 /*
2 * Copyright (c) 2024 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 "panic_error_info_handle.h"
17 #include <sys/stat.h>
18 #include "securec.h"
19 #include "hiview_logger.h"
20 #include "parameters.h"
21 #include "string_util.h"
22 #include "time_util.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 namespace PanicErrorInfoHandle {
27 DEFINE_LOG_LABEL(0xD002D11, "PanicErrorInfoHandle");
28
29 using namespace std;
30
31 namespace {
32 constexpr int EVENT_MAX_LEN = 32;
33 constexpr int CATEGORY_MAX_LEN = 32;
34 constexpr int MODULE_MAX_LEN = 32;
35 constexpr int TIMESTAMP_MAX_LEN = 24;
36 constexpr int ERROR_DESC_MAX_LEN = 512;
37
38 constexpr const char* const HISTORY_LOG_PATH = "/data/log/bbox/history.log";
39 constexpr const char* const SYS_FS_PSTORE_PATH = "/sys/fs/pstore/blackbox-ramoops-0";
40
41 /* fault category type */
42 constexpr const char* const CATEGORY_SYSTEM_REBOOT = "SYSREBOOT";
43 constexpr const char* const CATEGORY_SYSTEM_POWEROFF = "POWEROFF";
44 constexpr const char* const CATEGORY_SYSTEM_PANIC = "PANIC";
45 constexpr const char* const CATEGORY_SYSTEM_OOPS = "OOPS";
46 constexpr const char* const CATEGORY_SYSTEM_CUSTOM = "CUSTOM";
47 constexpr const char* const CATEGORY_SYSTEM_WATCHDOG = "HWWATCHDOG";
48 constexpr const char* const CATEGORY_SYSTEM_HUNGTASK = "HUNGTASK";
49 constexpr const char* const CATEGORY_SUBSYSTEM_CUSTOM = "CUSTOM";
50
51 /* top category type */
52 constexpr const char* const TOP_CATEGORY_SYSTEM_RESET = "System Reset";
53 constexpr const char* const TOP_CATEGORY_FREEZE = "System Freeze";
54 constexpr const char* const TOP_CATEGORY_SYSTEM_POWEROFF = "POWEROFF";
55 constexpr const char* const TOP_CATEGORY_SUBSYSTEM_CRASH = "Subsystem Crash";
56
57 /* module type */
58 constexpr const char* const MODULE_SYSTEM = "SYSTEM";
59
60 /* fault event type */
61 constexpr const char* const EVENT_SYSREBOOT = "SYSREBOOT";
62 constexpr const char* const EVENT_LONGPRESS = "LONGPRESS";
63 constexpr const char* const EVENT_COMBINATIONKEY = "COMBINATIONKEY";
64 constexpr const char* const EVENT_SUBSYSREBOOT = "SUBSYSREBOOT";
65 constexpr const char* const EVENT_POWEROFF = "POWEROFF";
66 constexpr const char* const EVENT_PANIC = "PANIC";
67 constexpr const char* const EVENT_OOPS = "OOPS";
68 constexpr const char* const EVENT_SYS_WATCHDOG = "SYSWATCHDOG";
69 constexpr const char* const EVENT_HUNGTASK = "HUNGTASK";
70 }
71
72 struct ErrorInfo {
73 char event[EVENT_MAX_LEN];
74 char category[CATEGORY_MAX_LEN];
75 char module[MODULE_MAX_LEN];
76 char errorTime[TIMESTAMP_MAX_LEN];
77 char errorDesc[ERROR_DESC_MAX_LEN];
78 };
79
80
81 struct ErrorInfoToCategory {
82 const char *module;
83 struct {
84 const char *event;
85 const char *category;
86 const char *topCategory;
87 } map;
88 };
89
90 struct ErrorInfoToCategory g_errorInfoCategories[] = {
91 {
92 MODULE_SYSTEM,
93 {EVENT_SYSREBOOT, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
94 },
95 {
96 MODULE_SYSTEM,
97 {EVENT_LONGPRESS, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
98 },
99 {
100 MODULE_SYSTEM,
101 {EVENT_COMBINATIONKEY, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
102 },
103 {
104 MODULE_SYSTEM,
105 {EVENT_SUBSYSREBOOT, CATEGORY_SYSTEM_REBOOT, TOP_CATEGORY_SYSTEM_RESET}
106 },
107 {
108 MODULE_SYSTEM,
109 {EVENT_POWEROFF, CATEGORY_SYSTEM_POWEROFF, TOP_CATEGORY_SYSTEM_POWEROFF}
110 },
111 {
112 MODULE_SYSTEM,
113 {EVENT_PANIC, CATEGORY_SYSTEM_PANIC, TOP_CATEGORY_SYSTEM_RESET}
114 },
115 {
116 MODULE_SYSTEM,
117 {EVENT_OOPS, CATEGORY_SYSTEM_OOPS, TOP_CATEGORY_SYSTEM_RESET}
118 },
119 {
120 MODULE_SYSTEM,
121 {EVENT_SYS_WATCHDOG, CATEGORY_SYSTEM_WATCHDOG, TOP_CATEGORY_FREEZE}
122 },
123 {
124 MODULE_SYSTEM,
125 {EVENT_HUNGTASK, CATEGORY_SYSTEM_HUNGTASK, TOP_CATEGORY_FREEZE}
126 },
127 };
128
GetTopCategory(const char * module,const char * event)129 static const char *GetTopCategory(const char *module, const char *event)
130 {
131 if ((!module || !event)) {
132 HIVIEW_LOGE("module: %{public}s, event: %{public}s\n", module ? module : "NULL", event ? event : "NULL");
133 return TOP_CATEGORY_SUBSYSTEM_CRASH;
134 }
135 int i;
136 int count = sizeof(g_errorInfoCategories) / sizeof(ErrorInfoToCategory);
137 for (i = 0; i < count; i++) {
138 if (!strcmp(g_errorInfoCategories[i].module, module) &&
139 !strcmp(g_errorInfoCategories[i].map.event, event)) {
140 return g_errorInfoCategories[i].map.topCategory;
141 }
142 }
143 if (!strcmp(module, MODULE_SYSTEM)) {
144 return TOP_CATEGORY_SYSTEM_RESET;
145 }
146 return TOP_CATEGORY_SUBSYSTEM_CRASH;
147 }
148
GetCategory(const char * module,const char * event)149 static const char *GetCategory(const char *module, const char *event)
150 {
151 if ((!module || !event)) {
152 HIVIEW_LOGE("module: %{public}s, event: %{public}s\n", module ? module : "NULL", event ? event : "NULL");
153 return CATEGORY_SUBSYSTEM_CUSTOM;
154 }
155 int i;
156 int count = sizeof(g_errorInfoCategories) / sizeof(ErrorInfoToCategory);
157 for (i = 0; i < count; i++) {
158 if (!strcmp(g_errorInfoCategories[i].module, module) &&
159 !strcmp(g_errorInfoCategories[i].map.event, event)) {
160 return g_errorInfoCategories[i].map.category;
161 }
162 }
163 if (!strcmp(module, MODULE_SYSTEM)) {
164 return CATEGORY_SYSTEM_CUSTOM;
165 }
166 return CATEGORY_SUBSYSTEM_CUSTOM;
167 }
168
SaveHistoryLog(string bboxTime,string bboxSysreset,ErrorInfo * info)169 static void SaveHistoryLog(string bboxTime, string bboxSysreset, ErrorInfo* info)
170 {
171 ofstream fout;
172 fout.open(HISTORY_LOG_PATH, ios::out | ios::app);
173 if (!fout.is_open()) {
174 HIVIEW_LOGE("Failed to open file: %{public}s, error=%{public}d", HISTORY_LOG_PATH, errno);
175 return;
176 }
177 fout << "[" << GetTopCategory(info->module, info->event) << "],";
178 fout << "module[" << info->module << "],";
179 fout << "category[" << GetCategory(info->module, info->event) << "],";
180 fout << "event[" << info->event << "],";
181 fout << "time[" << bboxTime << "],";
182 fout << "sysreboot[" << bboxSysreset << "],";
183 fout << "errdesc[" << info->errorDesc << "],";
184 fout << "logpath[/data/log/bbox]";
185 fout << endl;
186 HIVIEW_LOGE("GetTopCategory: %{public}s, module: %{public}s",
187 GetTopCategory(info->module, info->event), info->module);
188 HIVIEW_LOGE("category: %{public}s, event: %{public}s",
189 GetCategory(info->module, info->event), info->event);
190 HIVIEW_LOGE("time: %{public}s, sysreboot: %{public}s, errorDesc: %{public}s",
191 bboxTime.c_str(), bboxSysreset.c_str(), info->errorDesc);
192 }
193
TryCreateDir(const string & dir)194 static bool TryCreateDir(const string &dir)
195 {
196 struct stat info;
197
198 if (stat(dir.c_str(), &info) != 0) {
199 constexpr mode_t defaultLogDirMode = 0770;
200 if (mkdir(dir.c_str(), defaultLogDirMode) != 0) {
201 HIVIEW_LOGE("dir: %{public}s create failed", dir.c_str());
202 return false;
203 }
204 HIVIEW_LOGI("dir: %{public}s create success", dir.c_str());
205 return true;
206 }
207
208 if (info.st_mode & S_IFDIR) {
209 HIVIEW_LOGI("dir:%{public}s already existed", dir.c_str());
210 return true;
211 }
212 HIVIEW_LOGE("path: %{public}s is file not dir", dir.c_str());
213 return false;
214 }
215
CopyPstoreFileToHistoryLog(ifstream & fin)216 static void CopyPstoreFileToHistoryLog(ifstream &fin)
217 {
218 uint64_t startTime = TimeUtil::GetMilliseconds() / TimeUtil::SEC_TO_MILLISEC;
219 string dirPath = "/data/log/bbox/" +
220 TimeUtil::TimestampFormatToDate(startTime, "%Y%m%d-%H%M%S") + "/";
221 if (!TryCreateDir(dirPath)) {
222 HIVIEW_LOGE("TryCreateDir failed. path: %{public}s", dirPath.c_str());
223 return;
224 }
225 string targetPath = dirPath + "last_kmsg";
226 ofstream fout;
227 fout.open(targetPath, ios::in | ios::out | ios::trunc);
228 if (!fout.is_open()) {
229 HIVIEW_LOGE("Failed to open file: %{public}s error=%{public}d", targetPath.c_str(), errno);
230 return;
231 }
232 fout << fin.rdbuf();
233 fout << endl;
234 }
235
RKTransData(std::string bboxTime,std::string bboxSysreset)236 void RKTransData(std::string bboxTime, std::string bboxSysreset)
237 {
238 string deviceInfo = system::GetParameter("const.product.devicetype", "");
239 if (deviceInfo != "default") {
240 return;
241 }
242 ifstream fin(SYS_FS_PSTORE_PATH);
243 if (!fin.is_open()) {
244 HIVIEW_LOGE("Failed to open file: %{public}s, error=%{public}d", SYS_FS_PSTORE_PATH, errno);
245 return;
246 }
247 ErrorInfo info = {};
248 fin.read(reinterpret_cast<char* >(&info), sizeof(ErrorInfo));
249 if (!fin) {
250 HIVIEW_LOGE("Read error_info failed");
251 return;
252 }
253 SaveHistoryLog(bboxTime, bboxSysreset, &info);
254 CopyPstoreFileToHistoryLog(fin);
255 }
256 }
257 }
258 }
259