1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "hiview_hievent.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <errno.h>
37 #include <string.h>
38
39 #include "los_memory.h"
40 #include "los_task_pri.h"
41 #include "los_process_pri.h"
42 #include "los_mux.h"
43 #include "los_mp.h"
44 #include "los_typedef.h"
45
46 #include "hievent_driver.h"
47
48 #define INT_TYPE_MAX_LEN 21
49
50 #define MAX_PATH_LEN 256
51 #define MAX_STR_LEN (10 * 1024)
52
53 /* 64K is max length of /dev/hwlog_exception */
54 #define EVENT_INFO_BUF_LEN (64 * 1024)
55 #define EVENT_INFO_PACK_BUF_LEN (2 * 1024)
56
57 #define HWLOG_ERR PRINT_ERR
58 #define HWLOG_INFO PRINT_INFO
59
60 #define BUF_POINTER_FORWARD \
61 do { \
62 if (tmplen < len) { \
63 tmp += tmplen; \
64 len -= tmplen; \
65 } else { \
66 HWLOG_ERR("string over length"); \
67 tmp += len; \
68 len = 0; \
69 } \
70 } while (0)
71
72 struct HiviewHieventPayload {
73 char *key;
74 char *value;
75 struct HiviewHieventPayload *next;
76 };
77
78 static int HiviewHieventConvertString(struct HiviewHievent *event, char **pbuf);
79
80 static struct HiviewHieventPayload *HiviewHieventPayloadCreate(void);
81
82 static void HiviewHieventPayloadDestroy(struct HiviewHieventPayload *p);
83
84 static struct HiviewHieventPayload *HiviewHieventGetPayload(struct HiviewHieventPayload *head,
85 const char *key);
86
87 static void HiviewHieventAddPayload(struct HiviewHievent *obj,
88 struct HiviewHieventPayload *payload);
89
HiviewHieventPayloadCreate(void)90 static struct HiviewHieventPayload *HiviewHieventPayloadCreate(void)
91 {
92 struct HiviewHieventPayload *payload = NULL;
93
94 payload = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR,
95 sizeof(struct HiviewHieventPayload));
96 if (!payload) {
97 return NULL;
98 }
99
100 payload->key = NULL;
101 payload->value = NULL;
102 payload->next = NULL;
103
104 return payload;
105 }
106
HiviewHieventPayloadDestroy(struct HiviewHieventPayload * p)107 static void HiviewHieventPayloadDestroy(struct HiviewHieventPayload *p)
108 {
109 if (!p) {
110 return;
111 }
112
113 if (p->value) {
114 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, p->value);
115 }
116
117 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, p->key);
118 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, p);
119 }
120
HiviewHieventGetPayload(struct HiviewHieventPayload * head,const char * key)121 static struct HiviewHieventPayload *HiviewHieventGetPayload(struct HiviewHieventPayload *head,
122 const char *key)
123 {
124 struct HiviewHieventPayload *p = head;
125
126 while (p) {
127 if (key && p->key) {
128 if (strcmp(p->key, key) == 0) {
129 return p;
130 }
131 }
132 p = p->next;
133 }
134
135 return NULL;
136 }
137
HiviewHieventAddPayload(struct HiviewHievent * obj,struct HiviewHieventPayload * payload)138 static void HiviewHieventAddPayload(struct HiviewHievent *obj,
139 struct HiviewHieventPayload *payload)
140 {
141 if (!obj->head) {
142 obj->head = payload;
143 } else {
144 struct HiviewHieventPayload *p = obj->head;
145
146 while (p->next) {
147 p = p->next;
148 }
149 p->next = payload;
150 }
151 }
152
HiviewHieventCreate(unsigned int eventid)153 struct HiviewHievent *HiviewHieventCreate(unsigned int eventid)
154 {
155 struct HiviewHievent *event = NULL;
156
157 /* combined event obj struct */
158 event = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, sizeof(*event));
159 if (!event) {
160 return NULL;
161 }
162
163 (VOID)memset_s(event, sizeof(*event), 0, sizeof(*event));
164 event->eventid = eventid;
165 HWLOG_INFO("%s : %u\n", __func__, eventid);
166
167 return (void *)event;
168 }
169
HiviewHieventPutIntegral(struct HiviewHievent * event,const char * key,long value)170 int HiviewHieventPutIntegral(struct HiviewHievent *event,
171 const char *key, long value)
172 {
173 int ret;
174 struct HiviewHieventPayload *payload = NULL;
175
176 if ((!event) || (!key)) {
177 HWLOG_ERR("Bad input event or key for %s", __func__);
178 return -EINVAL;
179 }
180
181 payload = HiviewHieventGetPayload(event->head, key);
182 if (!payload) {
183 payload = HiviewHieventPayloadCreate();
184 if (!payload) {
185 return -ENOMEM;
186 }
187 payload->key = strdup(key);
188 HiviewHieventAddPayload(event, payload);
189 }
190
191 if (payload->value) {
192 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, payload->value);
193 }
194
195 payload->value = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, INT_TYPE_MAX_LEN);
196 if (!payload->value) {
197 return -ENOMEM;
198 }
199 (VOID)memset_s(payload->value, INT_TYPE_MAX_LEN, 0, INT_TYPE_MAX_LEN);
200 ret = snprintf_s(payload->value, INT_TYPE_MAX_LEN, INT_TYPE_MAX_LEN - 1,
201 "%d", (int)value);
202 if (ret < 0) {
203 return -ENOMEM;
204 }
205
206 return 0;
207 }
208
HiviewHieventPutString(struct HiviewHievent * event,const char * key,const char * value)209 int HiviewHieventPutString(struct HiviewHievent *event,
210 const char *key, const char *value)
211 {
212 struct HiviewHieventPayload *payload = NULL;
213 int len;
214
215 if ((!event) || (!key) || (!value)) {
216 HWLOG_ERR("Bad key for %s", __func__);
217 return -EINVAL;
218 }
219
220 payload = HiviewHieventGetPayload(event->head, key);
221 if (!payload) {
222 payload = HiviewHieventPayloadCreate();
223 if (!payload) {
224 return -ENOMEM;
225 }
226 payload->key = strdup(key);
227 HiviewHieventAddPayload(event, payload);
228 }
229
230 if (payload->value) {
231 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, payload->value);
232 }
233
234 len = strlen(value);
235 /* prevent length larger than MAX_STR_LEN */
236 if (len > MAX_STR_LEN) {
237 len = MAX_STR_LEN;
238 }
239 payload->value = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, len + 1);
240 if (!payload->value) {
241 return -ENOMEM;
242 }
243 (VOID)memset_s(payload->value, len + 1, 0, len + 1);
244 if (EOK == strncpy_s(payload->value, len + 1, value, len)) {
245 payload->value[len] = '\0';
246 }
247
248 return 0;
249 }
250
HiviewHieventSetTime(struct HiviewHievent * event,long long seconds)251 int HiviewHieventSetTime(struct HiviewHievent *event, long long seconds)
252 {
253 if ((!event) || (seconds == 0)) {
254 HWLOG_ERR("Bad input for %s", __func__);
255 return -EINVAL;
256 }
257 event->time = seconds;
258 return 0;
259 }
260
AppendArrayItem(char ** pool,int poolLen,const char * path)261 static int AppendArrayItem(char **pool, int poolLen, const char *path)
262 {
263 int i;
264
265 if ((!path) || (path[0] == 0)) {
266 HWLOG_ERR("Bad path %s", __func__);
267 return -EINVAL;
268 }
269
270 if (strlen(path) > MAX_PATH_LEN) {
271 HWLOG_ERR("file path over max: %d", MAX_PATH_LEN);
272 return -EINVAL;
273 }
274
275 for (i = 0; i < poolLen; i++) {
276 if (pool[i] != 0) {
277 continue;
278 }
279 pool[i] = strdup(path);
280 if (pool[i] == NULL) {
281 return -ENOMEM;
282 }
283 break;
284 }
285
286 if (i == MAX_PATH_NUMBER) {
287 HWLOG_ERR("Too many paths");
288 return -EINVAL;
289 }
290
291 return 0;
292 }
293
HiviewHieventAddFilePath(struct HiviewHievent * event,const char * path)294 int HiviewHieventAddFilePath(struct HiviewHievent *event, const char *path)
295 {
296 if (!event) {
297 HWLOG_ERR("Bad path %s", __func__);
298 return -EINVAL;
299 }
300 return AppendArrayItem(event->filePath, MAX_PATH_NUMBER, path);
301 }
302
303 /* make string ":" to "::", ";" to ";;", and remove newline character
304 * for example: "abc:def;ghi" transfer to "abc::def;;ghi"
305 */
HiviewHieventMakeRegular(char * value)306 static char *HiviewHieventMakeRegular(char *value)
307 {
308 int count = 0;
309 int len = 0;
310 char *temp = value;
311 char *regular = NULL;
312 char *regularTemp = NULL;
313
314 while (*temp != '\0') {
315 if (*temp == ':') {
316 count++;
317 } else if (*temp == ';') {
318 count++;
319 } else if ((*temp == '\n') || (*temp == '\r')) {
320 *temp = ' ';
321 }
322 temp++;
323 len++;
324 }
325
326 /* no need to transfer, just return old value */
327 if (count == 0) {
328 return value;
329 }
330
331 size_t regularLen = len + count * 2 + 1; // 2 char in a byte
332 regular = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, regularLen);
333 if (!regular) {
334 return NULL;
335 }
336 (VOID)memset_s(regular, regularLen, 0, regularLen);
337 regularTemp = regular;
338 temp = value;
339 while (*temp != 0) {
340 if ((*temp == ':') || (*temp == ';')) {
341 *regularTemp++ = *temp;
342 }
343 *regularTemp++ = *temp;
344 temp++;
345 }
346 *regularTemp = '\0';
347
348 return regular;
349 }
350
LogBufToException(char category,int level,char logType,char sn,const char * msg,int msglen)351 int LogBufToException(char category, int level, char logType,
352 char sn, const char *msg, int msglen)
353 {
354 struct IdapHeader *hdr;
355 size_t bufLen = sizeof(int) + sizeof(struct IdapHeader) + msglen;
356 char *buffer = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, bufLen);
357 if (!buffer) {
358 return -ENOMEM;
359 }
360
361 int *checkCode = (int *)buffer;
362 *checkCode = CHECK_CODE;
363
364 hdr = (struct IdapHeader *)(buffer + sizeof(int));
365 hdr->level = level;
366 hdr->category = category;
367 hdr->logType = logType;
368 hdr->sn = sn;
369
370 int ret = memcpy_s(buffer + sizeof(int) + sizeof(struct IdapHeader),
371 msglen, msg, msglen);
372 if (ret != EOK) {
373 goto out;
374 }
375
376 ret = HieventWriteInternal(buffer, bufLen);
377
378 out:
379 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, buffer);
380
381 return ret;
382 }
383
HiviewHieventFillPayload(struct HiviewHievent * event,char ** pbuf,char * tmp,int length)384 static int HiviewHieventFillPayload(struct HiviewHievent *event, char **pbuf,
385 char *tmp, int length)
386 {
387 struct HiviewHieventPayload *p = event->head;
388 int len = length;
389 int tmplen = 0;
390 unsigned int keycount = 0;
391 while (p) {
392 char *value = NULL;
393 char *regularValue = NULL;
394 int needFree = 1;
395
396 if (!p->value) {
397 p = p->next;
398 continue;
399 }
400 if (keycount == 0) {
401 tmplen = snprintf_s(tmp, len, len - 1, " --extra ");
402 BUF_POINTER_FORWARD;
403 }
404 keycount++;
405
406 /* fill key */
407 if (p->key) {
408 tmplen = snprintf_s(tmp, len, len - 1, "%s:", p->key);
409 }
410 BUF_POINTER_FORWARD;
411 /* fill value */
412 tmplen = 0;
413
414 value = p->value;
415 regularValue = HiviewHieventMakeRegular(value);
416 if (!regularValue) {
417 regularValue = "NULL";
418 needFree = 0;
419 }
420 tmplen = snprintf_s(tmp, len, len - 1, "%s;", regularValue);
421 if ((value != regularValue) && needFree) {
422 free(regularValue);
423 }
424 BUF_POINTER_FORWARD;
425 p = p->next;
426 }
427 return len;
428 }
429
HiviewHieventConvertString(struct HiviewHievent * event,char ** pbuf)430 static int HiviewHieventConvertString(struct HiviewHievent *event, char **pbuf)
431 {
432 int len;
433 char *tmp = NULL;
434 int tmplen = 0;
435 unsigned int i;
436
437 char *buf = LOS_MemAlloc((VOID *)OS_SYS_MEM_ADDR, EVENT_INFO_BUF_LEN);
438 if (!buf) {
439 *pbuf = NULL;
440 return 0;
441 }
442 (VOID)memset_s(buf, EVENT_INFO_BUF_LEN, 0, EVENT_INFO_BUF_LEN);
443 len = EVENT_INFO_BUF_LEN;
444 tmp = buf;
445
446 /* fill eventid */
447 tmplen = snprintf_s(tmp, len, len - 1, "eventid %d", event->eventid);
448 BUF_POINTER_FORWARD;
449
450 /* fill the path */
451 for (i = 0; i < MAX_PATH_NUMBER; i++) {
452 if (!event->filePath[i]) {
453 break;
454 }
455 tmplen = snprintf_s(tmp, len, len - 1, " -i %s",
456 event->filePath[i]);
457 BUF_POINTER_FORWARD;
458 }
459
460 /* fill time */
461 if (event->time) {
462 tmplen = snprintf_s(tmp, len, len - 1, " -t %lld", event->time);
463 BUF_POINTER_FORWARD;
464 }
465
466 /* fill the payload info */
467 len = HiviewHieventFillPayload(event, pbuf, tmp, len);
468 *pbuf = buf;
469 return (EVENT_INFO_BUF_LEN - len);
470 }
471
472 #define IDAP_LOGTYPE_CMD 1
HiviewHieventWriteLogException(char * str,const int strlen)473 static int HiviewHieventWriteLogException(char *str, const int strlen)
474 {
475 char tempchr;
476 char *strptr = str;
477 int leftBufLen = strlen + 1;
478 int sentcnt = 0;
479
480 while (leftBufLen > 0) {
481 if (leftBufLen > EVENT_INFO_PACK_BUF_LEN) {
482 tempchr = strptr[EVENT_INFO_PACK_BUF_LEN - 1];
483 strptr[EVENT_INFO_PACK_BUF_LEN - 1] = '\0';
484 (void)LogBufToException(0, 0, IDAP_LOGTYPE_CMD, 1,
485 strptr, EVENT_INFO_PACK_BUF_LEN);
486 leftBufLen -= (EVENT_INFO_PACK_BUF_LEN - 1);
487 strptr += (EVENT_INFO_PACK_BUF_LEN - 1);
488 strptr[0] = tempchr;
489 sentcnt++;
490 } else {
491 (void)LogBufToException(0, 0, IDAP_LOGTYPE_CMD, 0,
492 strptr, leftBufLen);
493 sentcnt++;
494 break;
495 }
496 }
497
498 return sentcnt;
499 }
500
HiviewHieventReport(struct HiviewHievent * obj)501 int HiviewHieventReport(struct HiviewHievent *obj)
502 {
503 char *str = NULL;
504 int bufLen;
505 int sentPacket;
506
507 if (!obj) {
508 HWLOG_ERR("Bad event %s", __func__);
509 return -EINVAL;
510 }
511
512 bufLen = HiviewHieventConvertString(obj, &str);
513 if (!str) {
514 return -EINVAL;
515 }
516 sentPacket = HiviewHieventWriteLogException(str, bufLen);
517 HWLOG_INFO("report: %s", str);
518 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, str);
519
520 return sentPacket;
521 }
522
HiviewHieventDestroy(struct HiviewHievent * event)523 void HiviewHieventDestroy(struct HiviewHievent *event)
524 {
525 int i;
526 struct HiviewHieventPayload *p = NULL;
527
528 if (!event) {
529 return;
530 }
531 p = event->head;
532 while (p) {
533 struct HiviewHieventPayload *del = p;
534
535 p = p->next;
536 HiviewHieventPayloadDestroy(del);
537 }
538 event->head = NULL;
539 for (i = 0; i < MAX_PATH_NUMBER; i++) {
540 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, event->filePath[i]);
541 event->filePath[i] = NULL;
542 }
543 LOS_MemFree((VOID *)OS_SYS_MEM_ADDR, event);
544 }
545
HiviewHieventFlush(void)546 void HiviewHieventFlush(void)
547 {
548 // magic number 0x7BBE69BD for notify hiview to flush hievent file
549 struct HiviewHievent *hievent = HiviewHieventCreate(0x7BBE69BD);
550 (void)HiviewHieventReport(hievent);
551 HiviewHieventDestroy(hievent);
552 }
553