tools:acrn-crashlog: unify the event analyzing process in crashlog

This patch unifies the event analyzing process in the
crashlog_sender functions:
a. analyze android events in android_events.c.
b. unify the analyzing output form of vm events and crash events.
c. concentrate the event analyzing process to the same function.

Tracked-On: #1024
Signed-off-by: Liu, Xinwu <xinwu.liu@intel.com>
Reviewed-by: Liu, Xiaojing <xiaojing.liu@intel.com>
Acked-by: Chen, Gang <gang.c.chen@intel.com>
This commit is contained in:
Liu, Xinwu 2019-04-19 11:13:00 +08:00 committed by ACRN System Integration
parent 13d50c2296
commit 901ce53971
7 changed files with 204 additions and 114 deletions

View File

@ -448,3 +448,47 @@ void refresh_vm_history(struct sender_t *sender,
} }
} }
} }
int android_event_analyze(const char *msg, size_t len, char **result,
size_t *rsize)
{
char *data;
char *tail;
size_t data_len;
char event[ANDROID_WORD_LEN];
char longtime[ANDROID_WORD_LEN];
char type[ANDROID_WORD_LEN];
char rest[PATH_MAX];
char vmkey[ANDROID_WORD_LEN];
const char * const format =
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
if (str_split_ere(msg, len, format, strlen(format), event,
sizeof(event), vmkey, sizeof(vmkey), longtime,
sizeof(longtime), type, sizeof(type), rest,
sizeof(rest)) != 5) {
LOGE("try to analyze an invalid line (%s), skip\n", msg);
return -1;
}
data_len = strnlen(vmkey, sizeof(vmkey)) + 1;
data_len += strnlen(event, sizeof(event)) + 1;
data_len += strnlen(type, sizeof(type)) + 1;
data_len += strnlen(rest, sizeof(rest)) + 1;
data = malloc(data_len);
if (!data)
return -1;
tail = (char *)mempcpy(data, vmkey, strnlen(vmkey, sizeof(vmkey)));
*(tail++) = '\0';
tail = (char *)mempcpy(tail, event, strnlen(event, sizeof(event)));
*(tail++) = '\0';
tail = (char *)mempcpy(tail, type, strnlen(type, sizeof(type)));
*(tail++) = '\0';
*(char *)mempcpy(tail, rest, strnlen(rest, sizeof(rest))) = '\0';
*result = data;
*rsize = data_len;
return 0;
}

View File

@ -125,38 +125,56 @@ static int crash_match_content(const struct crash_t *crash, const char *file)
crash_has_mightcontents(crash, file); crash_has_mightcontents(crash, file);
} }
static ssize_t _get_data(const char *file, const struct crash_t *crash, static int _get_data(const char *file, const struct crash_t *crash,
char **data, const int index) char **data, size_t *dsize, const int index)
{ {
const char *search_key; const char *search_key;
char *value; char *value;
char *end; char *end;
char *data_new;
ssize_t size; ssize_t size;
const size_t max_size = 255; const size_t max_size = 255;
search_key = crash->data[index]; search_key = crash->data[index];
if (!search_key) if (!search_key)
return 0; goto empty;
value = strrstr(file, search_key); value = strrstr(file, search_key);
if (!value) if (!value)
return 0; goto empty;
end = strchr(value, '\n'); end = strchr(value, '\n');
if (!end) if (!end)
return 0; goto empty;
size = MIN(max_size, (size_t)(end - value)); size = MIN(max_size, (size_t)(end - value));
if (!size) if (!size)
goto empty;
data_new = realloc(*data, *dsize + size + 1);
if (!data_new) {
LOGE("failed to realloc\n");
return -1;
}
strncpy(data_new + *dsize, value, size);
*(data_new + *dsize + size) = 0;
*data = data_new;
*dsize += size;
return 0; return 0;
empty:
data_new = realloc(*data, *dsize + 1);
if (!data_new) {
LOGE("failed to realloc\n");
return -1;
}
*data = malloc(size + 1); *(data_new + *dsize) = 0;
if (*data == NULL)
return -ENOMEM;
strncpy(*data, value, size); *data = data_new;
*(*data + size) = 0; *dsize += 1;
return size; return 0;
} }
/** /**
@ -165,48 +183,29 @@ static ssize_t _get_data(const char *file, const struct crash_t *crash,
* *
* @param file Starting address of file cache. * @param file Starting address of file cache.
* @param crash Crash need checking. * @param crash Crash need checking.
* @param[out] data0 Searched result, according to 'data0' configuread in crash. * @param[out] data Searched result, according to 'data' configuread in crash.
* @param[out] data1 Searched result, according to 'data1' configuread in crash.
* @param[out] data2 Searched result, according to 'data2' configuread in crash.
* *
* @return 0 if successful, or -1 if not. * @return 0 if successful, or -1 if not.
*/ */
static int get_data(const char *file, const struct crash_t *crash, static int get_data(const char *file, const struct crash_t *crash,
char **data0, size_t *d0len, char **data1, char **r_data, size_t *r_dsize)
size_t *d1len, char **data2, size_t *d2len)
{ {
ssize_t res; char *data = NULL;
size_t dsize = 0;
int i;
/* to find strings which match conf words */ /* to find strings which match conf words */
res = _get_data(file, crash, data0, 0); for (i = 0; i < DATA_MAX; i++) {
if (res < 0) if (_get_data(file, crash, &data, &dsize, i) == -1)
goto fail; goto fail;
*d0len = (size_t)res; }
res = _get_data(file, crash, data1, 1);
if (res < 0)
goto free_data0;
*d1len = (size_t)res;
res = _get_data(file, crash, data2, 2);
if (res < 0)
goto free_data1;
*d2len = (size_t)res;
*r_data = data;
*r_dsize = dsize;
return 0; return 0;
free_data1:
if (*data1)
free(*data1);
free_data0:
if (*data0)
free(*data0);
fail: fail:
*data0 = NULL; if (data)
*data1 = NULL; free(data);
*data2 = NULL;
*d0len = 0;
*d1len = 0;
*d2len = 0;
return -1; return -1;
} }
@ -276,18 +275,14 @@ static struct crash_t *crash_find_matched_child(const struct crash_t *crash,
* *
* @param rcrash Root crash obtained from channel. * @param rcrash Root crash obtained from channel.
* @param rtrfile_fmt Path fmt of trigger file of root crash. * @param rtrfile_fmt Path fmt of trigger file of root crash.
* @param[out] data0 Searched result, according to 'data0' configuread in crash. * @param[out] data Searched result, according to 'data' configuread in crash.
* @param[out] data1 Searched result, according to 'data1' configuread in crash.
* @param[out] data2 Searched result, according to 'data2' configuread in crash.
* *
* @return a pointer to the calculated crash structure if successful, * @return a pointer to the calculated crash structure if successful,
* or NULL if not. * or NULL if not.
*/ */
static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash, static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash,
const char *rtrfile_fmt, const char *rtrfile_fmt,
char **data0, size_t *d0len, char **data, size_t *dsize)
char **data1, size_t *d1len,
char **data2, size_t *d2len)
{ {
int count; int count;
const struct crash_t *crash; const struct crash_t *crash;
@ -298,15 +293,9 @@ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash,
unsigned long size; unsigned long size;
int i; int i;
if (!rcrash || !data0 || !d0len || !data1 || !d1len || !data2 || !d2len) if (!rcrash || !data || !dsize)
return NULL; return NULL;
*data0 = NULL;
*data1 = NULL;
*data2 = NULL;
*d0len = 0;
*d1len = 0;
*d2len = 0;
crash = rcrash; crash = rcrash;
while (1) { while (1) {
@ -339,8 +328,7 @@ static struct crash_t *crash_reclassify_by_content(const struct crash_t *rcrash,
if (!size) if (!size)
goto free_files; goto free_files;
if (get_data(content, ret_crash, data0, d0len, data1, d1len, if (get_data(content, ret_crash, data, dsize) == -1)
data2, d2len) == -1)
LOGE("failed to get data\n"); LOGE("failed to get data\n");
free(content); free(content);

View File

@ -41,5 +41,6 @@ struct vm_event_t {
void refresh_vm_history(struct sender_t *sender, void refresh_vm_history(struct sender_t *sender,
int (*fn)(const char*, size_t, const struct vm_t *)); int (*fn)(const char*, size_t, const struct vm_t *));
int android_event_analyze(const char *msg, size_t len, char **result,
size_t *rsize);
#endif #endif

View File

@ -92,7 +92,6 @@ struct crash_t {
int wd; int wd;
int level; int level;
struct crash_t *(*reclassify)(const struct crash_t *, const char*, struct crash_t *(*reclassify)(const struct crash_t *, const char*,
char**, size_t *, char**, size_t *,
char**, size_t *); char**, size_t *);
}; };

View File

@ -720,9 +720,8 @@ static void telemd_send(struct event_t *e)
} }
#endif #endif
static void crashlog_send_crash(struct event_t *e) static void crashlog_send_crash(struct event_t *e, char *data, size_t dlen)
{ {
struct crash_t *crash;
char *key; char *key;
char *data0; char *data0;
char *data1; char *data1;
@ -730,34 +729,14 @@ static void crashlog_send_crash(struct event_t *e)
size_t d0len; size_t d0len;
size_t d1len; size_t d1len;
size_t d2len; size_t d2len;
char *trfile = NULL; struct crash_t *crash = (struct crash_t *)e->private;
struct crash_t *rcrash = (struct crash_t *)e->private;
if (!strcmp(rcrash->trigger->type, "dir")) {
if (asprintf(&trfile, "%s/%s", rcrash->trigger->path,
e->path) == -1) {
LOGE("out of memory\n");
return;
}
}
crash = rcrash->reclassify(rcrash, trfile, &data0, &d0len, &data1,
&d1len, &data2, &d2len);
if (trfile)
free(trfile);
if (crash == NULL) {
LOGE("failed to reclassify rcrash (%s)\n", rcrash->name);
return;
}
/* change the class for other senders */
e->private = (void *)crash;
key = generate_event_id("CRASH", 5, (const char *)crash->name, key = generate_event_id("CRASH", 5, (const char *)crash->name,
crash->name_len, KEY_SHORT); crash->name_len, KEY_SHORT);
if (key == NULL) { if (key == NULL) {
LOGE("failed to generate event id, error (%s)\n", LOGE("failed to generate event id, error (%s)\n",
strerror(errno)); strerror(errno));
goto free_data; return;
} }
/* check space before collecting logs */ /* check space before collecting logs */
@ -766,6 +745,12 @@ static void crashlog_send_crash(struct event_t *e)
goto free_key; goto free_key;
} }
data0 = strings_ind(data, dlen, 0, &d0len);
data1 = strings_ind(data, dlen, 1, &d1len);
data2 = strings_ind(data, dlen, 2, &d2len);
if (!data1 || !data1 || !data2)
goto free_key;
if (to_collect_logs(crash) || !strcmp(e->channel, "inotify")) { if (to_collect_logs(crash) || !strcmp(e->channel, "inotify")) {
struct log_t *log; struct log_t *log;
int id; int id;
@ -816,13 +801,6 @@ static void crashlog_send_crash(struct event_t *e)
free_key: free_key:
free(key); free(key);
free_data:
if (data0)
free(data0);
if (data1)
free(data1);
if (data2)
free(data2);
} }
static void crashlog_send_info(struct event_t *e) static void crashlog_send_info(struct event_t *e)
@ -906,39 +884,35 @@ static void crashlog_send_reboot(void)
free(key); free(key);
} }
static void crashlog_send_vmevent(struct event_t *e) static void crashlog_send_vmevent(struct event_t *e, char *data, size_t dlen)
{ {
char event[ANDROID_WORD_LEN]; char *vmkey;
char longtime[ANDROID_WORD_LEN]; char *event;
char type[ANDROID_WORD_LEN]; char *type;
char rest[PATH_MAX]; char *rest;
char vmkey[ANDROID_WORD_LEN]; size_t klen;
char *vmlogpath = NULL; size_t elen;
size_t tlen;
size_t rlen;
char *vmlogpath;
char *key; char *key;
char *log; char *log;
int res; int res;
int cnt; int cnt;
ext2_filsys datafs; ext2_filsys datafs;
struct sender_t *crashlog = get_sender_by_name("crashlog"); struct sender_t *crashlog = get_sender_by_name("crashlog");
struct vm_event_t *vme; struct vm_event_t *vme = (struct vm_event_t *)e->private;
enum vmrecord_mark_t mark = SUCCESS; enum vmrecord_mark_t mark = SUCCESS;
const char * const vm_format =
ANDROID_ENEVT_FMT ANDROID_KEY_FMT ANDROID_LONGTIME_FMT
ANDROID_TYPE_FMT ANDROID_LINE_REST_FMT;
if (!crashlog) if (!crashlog)
return; return;
vme = (struct vm_event_t *)e->private; vmkey = strings_ind(data, dlen, 0, &klen);
res = str_split_ere(vme->vm_msg, vme->vm_msg_len, vm_format, event = strings_ind(data, dlen, 1, &elen);
strlen(vm_format), event, sizeof(event), type = strings_ind(data, dlen, 2, &tlen);
vmkey, sizeof(vmkey), longtime, sizeof(longtime), rest = strings_ind(data, dlen, 3, &rlen);
type, sizeof(type), rest, sizeof(rest)); if (!vmkey || !event || !type || !rest)
if (res != 5) {
LOGE("get an invalid line from (%s), skip\n", vme->vm->name);
return; return;
}
key = generate_event_id("SOS", 3, (const char *)vmkey, key = generate_event_id("SOS", 3, (const char *)vmkey,
strnlen(vmkey, ANDROID_WORD_LEN), KEY_SHORT); strnlen(vmkey, ANDROID_WORD_LEN), KEY_SHORT);
@ -1013,12 +987,60 @@ mark_record:
return; return;
} }
static int crashlog_event_analyze(struct event_t *e, char **result,
size_t *rsize)
{
struct crash_t *rcrash;
struct crash_t *crash;
char *trfile = NULL;
struct vm_event_t *vme;
switch (e->event_type) {
case CRASH:
rcrash = (struct crash_t *)e->private;
if (!strcmp(rcrash->trigger->type, "dir")) {
if (asprintf(&trfile, "%s/%s", rcrash->trigger->path,
e->path) == -1) {
LOGE("failed to asprintf\n");
return -1;
}
}
crash = rcrash->reclassify(rcrash, trfile, result, rsize);
if (trfile)
free(trfile);
if (!crash) {
LOGE("failed to reclassify (%s)\n", rcrash->name);
return -1;
}
/* change the class */
e->private = (void *)crash;
break;
case VM:
vme = (struct vm_event_t *)e->private;
if (android_event_analyze(vme->vm_msg, vme->vm_msg_len,
result, rsize) == -1) {
LOGE("failed to analyze android event\n");
return -1;
}
break;
default:
break;
}
return 0;
}
static void crashlog_send(struct event_t *e) static void crashlog_send(struct event_t *e)
{ {
int id; int id;
struct log_t *log; struct log_t *log;
size_t rsize = 0;
char *result = NULL;
if (crashlog_event_analyze(e, &result, &rsize) == -1) {
LOGE("failed to analyze event\n");
return;
}
for_each_log(id, log, conf) { for_each_log(id, log, conf) {
if (!log) if (!log)
continue; continue;
@ -1027,7 +1049,7 @@ static void crashlog_send(struct event_t *e)
} }
switch (e->event_type) { switch (e->event_type) {
case CRASH: case CRASH:
crashlog_send_crash(e); crashlog_send_crash(e, result, rsize);
break; break;
case INFO: case INFO:
crashlog_send_info(e); crashlog_send_info(e);
@ -1039,11 +1061,13 @@ static void crashlog_send(struct event_t *e)
crashlog_send_reboot(); crashlog_send_reboot();
break; break;
case VM: case VM:
crashlog_send_vmevent(e); crashlog_send_vmevent(e, result, rsize);
break; break;
default: default:
LOGE("unsupoorted event type %d\n", e->event_type); LOGE("unsupoorted event type %d\n", e->event_type);
} }
if (result)
free(result);
} }
int init_sender(void) int init_sender(void)

View File

@ -16,6 +16,7 @@ ssize_t strlinelen(const char *str, size_t size);
char *strrstr(const char *s, const char *str); char *strrstr(const char *s, const char *str);
char *strtrim(char *str, size_t len); char *strtrim(char *str, size_t len);
int strcnt(char *str, char c); int strcnt(char *str, char c);
char *strings_ind(char *strings, size_t size, int index, size_t *slen);
int str_split_ere(const char *str, size_t slen, int str_split_ere(const char *str, size_t slen,
const char *fmt, size_t flen, ...); const char *fmt, size_t flen, ...);
#endif #endif

View File

@ -156,6 +156,39 @@ int strcnt(char *str, char c)
return cnt; return cnt;
} }
char *strings_ind(char *strings, size_t size, int index, size_t *slen)
{
int i = 0;
size_t len;
char *start = strings;
char *str_tail;
size_t left;
if (!strings || !size)
return NULL;
str_tail = memchr((void *)strings, '\0', size);
if (!str_tail)
return NULL;
while (1) {
len = str_tail - start;
if (i++ == index)
break;
left = strings + size - str_tail - 1;
if (!left)
return NULL;
start = str_tail + 1;
str_tail = memchr((void *)start, '\0', left);
if (!str_tail)
break;
}
if (slen)
*slen = len;
return start;
}
static int reg_match(const char *str, const char *pattern, static int reg_match(const char *str, const char *pattern,
char *matched_sub, size_t matched_space, char *matched_sub, size_t matched_space,
size_t *end_off) size_t *end_off)