• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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