Commit 81e9b994 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo

Merge tag 'libtraceevent-core-for-acme' of...

Merge tag 'libtraceevent-core-for-acme' of git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf into perf/core

libtraceevent/core improvements

* Remaining backport of trace-cmd's libparseevent
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parents 1dc12760 f6ced60f
...@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func, ...@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func,
item->mod = NULL; item->mod = NULL;
item->addr = addr; item->addr = addr;
pevent->funclist = item; if (!item->func || (mod && !item->mod))
die("malloc func");
pevent->funclist = item;
pevent->func_count++; pevent->func_count++;
return 0; return 0;
...@@ -511,12 +513,12 @@ struct printk_list { ...@@ -511,12 +513,12 @@ struct printk_list {
static int printk_cmp(const void *a, const void *b) static int printk_cmp(const void *a, const void *b)
{ {
const struct func_map *fa = a; const struct printk_map *pa = a;
const struct func_map *fb = b; const struct printk_map *pb = b;
if (fa->addr < fb->addr) if (pa->addr < pb->addr)
return -1; return -1;
if (fa->addr > fb->addr) if (pa->addr > pb->addr)
return 1; return 1;
return 0; return 0;
...@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt, ...@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
item = malloc_or_die(sizeof(*item)); item = malloc_or_die(sizeof(*item));
item->next = pevent->printklist; item->next = pevent->printklist;
pevent->printklist = item;
item->printk = strdup(fmt); item->printk = strdup(fmt);
item->addr = addr; item->addr = addr;
if (!item->printk)
die("malloc fmt");
pevent->printklist = item;
pevent->printk_count++; pevent->printk_count++;
return 0; return 0;
...@@ -628,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event) ...@@ -628,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event)
{ {
int i; int i;
if (!pevent->events) pevent->events = realloc(pevent->events, sizeof(event) *
pevent->events = malloc_or_die(sizeof(event)); (pevent->nr_events + 1));
else
pevent->events =
realloc(pevent->events, sizeof(event) *
(pevent->nr_events + 1));
if (!pevent->events) if (!pevent->events)
die("Can not allocate events"); die("Can not allocate events");
...@@ -781,6 +782,25 @@ int pevent_peek_char(void) ...@@ -781,6 +782,25 @@ int pevent_peek_char(void)
return __peek_char(); return __peek_char();
} }
static int extend_token(char **tok, char *buf, int size)
{
char *newtok = realloc(*tok, size);
if (!newtok) {
free(*tok);
*tok = NULL;
return -1;
}
if (!*tok)
strcpy(newtok, buf);
else
strcat(newtok, buf);
*tok = newtok;
return 0;
}
static enum event_type force_token(const char *str, char **tok); static enum event_type force_token(const char *str, char **tok);
static enum event_type __read_token(char **tok) static enum event_type __read_token(char **tok)
...@@ -865,17 +885,10 @@ static enum event_type __read_token(char **tok) ...@@ -865,17 +885,10 @@ static enum event_type __read_token(char **tok)
do { do {
if (i == (BUFSIZ - 1)) { if (i == (BUFSIZ - 1)) {
buf[i] = 0; buf[i] = 0;
if (*tok) { tok_size += BUFSIZ;
*tok = realloc(*tok, tok_size + BUFSIZ);
if (!*tok)
return EVENT_NONE;
strcat(*tok, buf);
} else
*tok = strdup(buf);
if (!*tok) if (extend_token(tok, buf, tok_size) < 0)
return EVENT_NONE; return EVENT_NONE;
tok_size += BUFSIZ;
i = 0; i = 0;
} }
last_ch = ch; last_ch = ch;
...@@ -914,17 +927,10 @@ static enum event_type __read_token(char **tok) ...@@ -914,17 +927,10 @@ static enum event_type __read_token(char **tok)
while (get_type(__peek_char()) == type) { while (get_type(__peek_char()) == type) {
if (i == (BUFSIZ - 1)) { if (i == (BUFSIZ - 1)) {
buf[i] = 0; buf[i] = 0;
if (*tok) { tok_size += BUFSIZ;
*tok = realloc(*tok, tok_size + BUFSIZ);
if (!*tok)
return EVENT_NONE;
strcat(*tok, buf);
} else
*tok = strdup(buf);
if (!*tok) if (extend_token(tok, buf, tok_size) < 0)
return EVENT_NONE; return EVENT_NONE;
tok_size += BUFSIZ;
i = 0; i = 0;
} }
ch = __read_char(); ch = __read_char();
...@@ -933,14 +939,7 @@ static enum event_type __read_token(char **tok) ...@@ -933,14 +939,7 @@ static enum event_type __read_token(char **tok)
out: out:
buf[i] = 0; buf[i] = 0;
if (*tok) { if (extend_token(tok, buf, tok_size + i + 1) < 0)
*tok = realloc(*tok, tok_size + i);
if (!*tok)
return EVENT_NONE;
strcat(*tok, buf);
} else
*tok = strdup(buf);
if (!*tok)
return EVENT_NONE; return EVENT_NONE;
if (type == EVENT_ITEM) { if (type == EVENT_ITEM) {
...@@ -1261,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1261,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
field->flags |= FIELD_IS_POINTER; field->flags |= FIELD_IS_POINTER;
if (field->type) { if (field->type) {
field->type = realloc(field->type, char *new_type;
strlen(field->type) + new_type = realloc(field->type,
strlen(last_token) + 2); strlen(field->type) +
strlen(last_token) + 2);
if (!new_type) {
free(last_token);
goto fail;
}
field->type = new_type;
strcat(field->type, " "); strcat(field->type, " ");
strcat(field->type, last_token); strcat(field->type, last_token);
free(last_token); free(last_token);
...@@ -1288,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1288,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
if (strcmp(token, "[") == 0) { if (strcmp(token, "[") == 0) {
enum event_type last_type = type; enum event_type last_type = type;
char *brackets = token; char *brackets = token;
char *new_brackets;
int len; int len;
field->flags |= FIELD_IS_ARRAY; field->flags |= FIELD_IS_ARRAY;
...@@ -1307,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1307,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
len = 1; len = 1;
last_type = type; last_type = type;
brackets = realloc(brackets, new_brackets = realloc(brackets,
strlen(brackets) + strlen(brackets) +
strlen(token) + len); strlen(token) + len);
if (!new_brackets) {
free(brackets);
goto fail;
}
brackets = new_brackets;
if (len == 2) if (len == 2)
strcat(brackets, " "); strcat(brackets, " ");
strcat(brackets, token); strcat(brackets, token);
...@@ -1325,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1325,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
free_token(token); free_token(token);
brackets = realloc(brackets, strlen(brackets) + 2); new_brackets = realloc(brackets, strlen(brackets) + 2);
if (!new_brackets) {
free(brackets);
goto fail;
}
brackets = new_brackets;
strcat(brackets, "]"); strcat(brackets, "]");
/* add brackets to type */ /* add brackets to type */
...@@ -1336,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1336,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f
* the format: type [] item; * the format: type [] item;
*/ */
if (type == EVENT_ITEM) { if (type == EVENT_ITEM) {
field->type = realloc(field->type, char *new_type;
strlen(field->type) + new_type = realloc(field->type,
strlen(field->name) + strlen(field->type) +
strlen(brackets) + 2); strlen(field->name) +
strlen(brackets) + 2);
if (!new_type) {
free(brackets);
goto fail;
}
field->type = new_type;
strcat(field->type, " "); strcat(field->type, " ");
strcat(field->type, field->name); strcat(field->type, field->name);
free_token(field->name); free_token(field->name);
...@@ -1347,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f ...@@ -1347,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
field->name = token; field->name = token;
type = read_token(&token); type = read_token(&token);
} else { } else {
field->type = realloc(field->type, char *new_type;
strlen(field->type) + new_type = realloc(field->type,
strlen(brackets) + 1); strlen(field->type) +
strlen(brackets) + 1);
if (!new_type) {
free(brackets);
goto fail;
}
field->type = new_type;
strcat(field->type, brackets); strcat(field->type, brackets);
} }
free(brackets); free(brackets);
...@@ -1732,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) ...@@ -1732,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
/* could just be a type pointer */ /* could just be a type pointer */
if ((strcmp(arg->op.op, "*") == 0) && if ((strcmp(arg->op.op, "*") == 0) &&
type == EVENT_DELIM && (strcmp(token, ")") == 0)) { type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
char *new_atom;
if (left->type != PRINT_ATOM) if (left->type != PRINT_ATOM)
die("bad pointer type"); die("bad pointer type");
left->atom.atom = realloc(left->atom.atom, new_atom = realloc(left->atom.atom,
strlen(left->atom.atom) + 3); strlen(left->atom.atom) + 3);
if (!new_atom)
goto out_free;
left->atom.atom = new_atom;
strcat(left->atom.atom, " *"); strcat(left->atom.atom, " *");
free(arg->op.op); free(arg->op.op);
*arg = *left; *arg = *left;
...@@ -2152,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** ...@@ -2152,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
if (value == NULL) if (value == NULL)
goto out_free; goto out_free;
field->value = strdup(value); field->value = strdup(value);
if (field->value == NULL)
goto out_free;
free_arg(arg); free_arg(arg);
arg = alloc_arg(); arg = alloc_arg();
...@@ -2165,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char ** ...@@ -2165,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
if (value == NULL) if (value == NULL)
goto out_free; goto out_free;
field->str = strdup(value); field->str = strdup(value);
if (field->str == NULL)
goto out_free;
free_arg(arg); free_arg(arg);
arg = NULL; arg = NULL;
...@@ -2590,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg, ...@@ -2590,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
} }
/* atoms can be more than one token long */ /* atoms can be more than one token long */
while (type == EVENT_ITEM) { while (type == EVENT_ITEM) {
atom = realloc(atom, strlen(atom) + strlen(token) + 2); char *new_atom;
new_atom = realloc(atom,
strlen(atom) + strlen(token) + 2);
if (!new_atom) {
free(atom);
*tok = NULL;
free_token(token);
return EVENT_ERROR;
}
atom = new_atom;
strcat(atom, " "); strcat(atom, " ");
strcat(atom, token); strcat(atom, token);
free_token(token); free_token(token);
...@@ -2884,7 +2931,7 @@ static int get_common_info(struct pevent *pevent, ...@@ -2884,7 +2931,7 @@ static int get_common_info(struct pevent *pevent,
event = pevent->events[0]; event = pevent->events[0];
field = pevent_find_common_field(event, type); field = pevent_find_common_field(event, type);
if (!field) if (!field)
die("field '%s' not found", type); return -1;
*offset = field->offset; *offset = field->offset;
*size = field->size; *size = field->size;
...@@ -2935,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data) ...@@ -2935,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data)
static int parse_common_lock_depth(struct pevent *pevent, void *data) static int parse_common_lock_depth(struct pevent *pevent, void *data)
{ {
int ret; return __parse_common(pevent, data,
&pevent->ld_size, &pevent->ld_offset,
ret = __parse_common(pevent, data, "common_lock_depth");
&pevent->ld_size, &pevent->ld_offset, }
"common_lock_depth");
if (ret < 0)
return -1;
return ret; static int parse_common_migrate_disable(struct pevent *pevent, void *data)
{
return __parse_common(pevent, data,
&pevent->ld_size, &pevent->ld_offset,
"common_migrate_disable");
} }
static int events_id_cmp(const void *a, const void *b); static int events_id_cmp(const void *a, const void *b);
...@@ -3370,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, ...@@ -3370,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
break; break;
} }
case PRINT_BSTRING: case PRINT_BSTRING:
trace_seq_printf(s, format, arg->string.string); print_str_to_seq(s, format, len_arg, arg->string.string);
break; break;
case PRINT_OP: case PRINT_OP:
/* /*
...@@ -3434,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size, ...@@ -3434,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size,
string = malloc_or_die(sizeof(*string)); string = malloc_or_die(sizeof(*string));
string->next = strings; string->next = strings;
string->str = strdup(str.buffer); string->str = strdup(str.buffer);
if (!string->str)
die("malloc str");
args[i] = (unsigned long long)string->str;
strings = string; strings = string;
trace_seq_destroy(&str); trace_seq_destroy(&str);
break; break;
...@@ -3471,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc ...@@ -3471,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
unsigned long long ip, val; unsigned long long ip, val;
char *ptr; char *ptr;
void *bptr; void *bptr;
int vsize;
field = pevent->bprint_buf_field; field = pevent->bprint_buf_field;
ip_field = pevent->bprint_ip_field; ip_field = pevent->bprint_ip_field;
...@@ -3519,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc ...@@ -3519,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
goto process_again; goto process_again;
case '0' ... '9': case '0' ... '9':
goto process_again; goto process_again;
case '.':
goto process_again;
case 'p': case 'p':
ls = 1; ls = 1;
/* fall through */ /* fall through */
...@@ -3526,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc ...@@ -3526,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
case 'u': case 'u':
case 'x': case 'x':
case 'i': case 'i':
/* the pointers are always 4 bytes aligned */
bptr = (void *)(((unsigned long)bptr + 3) &
~3);
switch (ls) { switch (ls) {
case 0: case 0:
ls = 4; vsize = 4;
break; break;
case 1: case 1:
ls = pevent->long_size; vsize = pevent->long_size;
break; break;
case 2: case 2:
ls = 8; vsize = 8;
break;
default: default:
vsize = ls; /* ? */
break; break;
} }
val = pevent_read_number(pevent, bptr, ls); /* fall through */
bptr += ls; case '*':
if (*ptr == '*')
vsize = 4;
/* the pointers are always 4 bytes aligned */
bptr = (void *)(((unsigned long)bptr + 3) &
~3);
val = pevent_read_number(pevent, bptr, vsize);
bptr += vsize;
arg = alloc_arg(); arg = alloc_arg();
arg->next = NULL; arg->next = NULL;
arg->type = PRINT_ATOM; arg->type = PRINT_ATOM;
...@@ -3550,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc ...@@ -3550,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
sprintf(arg->atom.atom, "%lld", val); sprintf(arg->atom.atom, "%lld", val);
*next = arg; *next = arg;
next = &arg->next; next = &arg->next;
/*
* The '*' case means that an arg is used as the length.
* We need to continue to figure out for what.
*/
if (*ptr == '*')
goto process_again;
break; break;
case 's': case 's':
arg = alloc_arg(); arg = alloc_arg();
arg->next = NULL; arg->next = NULL;
arg->type = PRINT_BSTRING; arg->type = PRINT_BSTRING;
arg->string.string = strdup(bptr); arg->string.string = strdup(bptr);
if (!arg->string.string)
break;
bptr += strlen(bptr) + 1; bptr += strlen(bptr) + 1;
*next = arg; *next = arg;
next = &arg->next; next = &arg->next;
...@@ -3841,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -3841,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
} else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') { } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
print_mac_arg(s, *(ptr+1), data, size, event, arg); print_mac_arg(s, *(ptr+1), data, size, event, arg);
ptr++; ptr++;
arg = arg->next;
break; break;
} }
...@@ -3877,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -3877,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
break; break;
} }
} }
if (pevent->long_size == 8 && ls) { if (pevent->long_size == 8 && ls &&
sizeof(long) != 8) {
char *p; char *p;
ls = 2; ls = 2;
/* make %l into %ll */ /* make %l into %ll */
p = strchr(format, 'l'); p = strchr(format, 'l');
if (p) if (p)
memmove(p, p+1, strlen(p)+1); memmove(p+1, p, strlen(p)+1);
else if (strcmp(format, "%p") == 0) else if (strcmp(format, "%p") == 0)
strcpy(format, "0x%llx"); strcpy(format, "0x%llx");
} }
...@@ -3961,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -3961,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
* pevent_data_lat_fmt - parse the data for the latency format * pevent_data_lat_fmt - parse the data for the latency format
* @pevent: a handle to the pevent * @pevent: a handle to the pevent
* @s: the trace_seq to write to * @s: the trace_seq to write to
* @data: the raw data to read from * @record: the record to read from
* @size: currently unused.
* *
* This parses out the Latency format (interrupts disabled, * This parses out the Latency format (interrupts disabled,
* need rescheduling, in hard/soft interrupt, preempt count * need rescheduling, in hard/soft interrupt, preempt count
...@@ -3972,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, ...@@ -3972,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
struct trace_seq *s, struct pevent_record *record) struct trace_seq *s, struct pevent_record *record)
{ {
static int check_lock_depth = 1; static int check_lock_depth = 1;
static int check_migrate_disable = 1;
static int lock_depth_exists; static int lock_depth_exists;
static int migrate_disable_exists;
unsigned int lat_flags; unsigned int lat_flags;
unsigned int pc; unsigned int pc;
int lock_depth; int lock_depth;
int migrate_disable;
int hardirq; int hardirq;
int softirq; int softirq;
void *data = record->data; void *data = record->data;
...@@ -3983,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent, ...@@ -3983,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent,
lat_flags = parse_common_flags(pevent, data); lat_flags = parse_common_flags(pevent, data);
pc = parse_common_pc(pevent, data); pc = parse_common_pc(pevent, data);
/* lock_depth may not always exist */ /* lock_depth may not always exist */
if (check_lock_depth) {
struct format_field *field;
struct event_format *event;
check_lock_depth = 0;
event = pevent->events[0];
field = pevent_find_common_field(event, "common_lock_depth");
if (field)
lock_depth_exists = 1;
}
if (lock_depth_exists) if (lock_depth_exists)
lock_depth = parse_common_lock_depth(pevent, data); lock_depth = parse_common_lock_depth(pevent, data);
else if (check_lock_depth) {
lock_depth = parse_common_lock_depth(pevent, data);
if (lock_depth < 0)
check_lock_depth = 0;
else
lock_depth_exists = 1;
}
/* migrate_disable may not always exist */
if (migrate_disable_exists)
migrate_disable = parse_common_migrate_disable(pevent, data);
else if (check_migrate_disable) {
migrate_disable = parse_common_migrate_disable(pevent, data);
if (migrate_disable < 0)
check_migrate_disable = 0;
else
migrate_disable_exists = 1;
}
hardirq = lat_flags & TRACE_FLAG_HARDIRQ; hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
softirq = lat_flags & TRACE_FLAG_SOFTIRQ; softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
...@@ -4013,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent, ...@@ -4013,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
else else
trace_seq_putc(s, '.'); trace_seq_putc(s, '.');
if (migrate_disable_exists) {
if (migrate_disable < 0)
trace_seq_putc(s, '.');
else
trace_seq_printf(s, "%d", migrate_disable);
}
if (lock_depth_exists) { if (lock_depth_exists) {
if (lock_depth < 0) if (lock_depth < 0)
trace_seq_putc(s, '.'); trace_seq_putc(s, '.');
...@@ -4079,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid) ...@@ -4079,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
* pevent_data_comm_from_pid - parse the data into the print format * pevent_data_comm_from_pid - parse the data into the print format
* @s: the trace_seq to write to * @s: the trace_seq to write to
* @event: the handle to the event * @event: the handle to the event
* @cpu: the cpu the event was recorded on * @record: the record to read from
* @data: the raw data
* @size: the size of the raw data
* @nsecs: the timestamp of the event
* *
* This parses the raw @data using the given @event information and * This parses the raw @data using the given @event information and
* writes the print format into the trace_seq. * writes the print format into the trace_seq.
...@@ -4631,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent, ...@@ -4631,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent,
die("failed to read event id"); die("failed to read event id");
event->system = strdup(sys); event->system = strdup(sys);
if (!event->system)
die("failed to allocate system");
/* Add pevent to event so that it can be referenced */ /* Add pevent to event so that it can be referenced */
event->pevent = pevent; event->pevent = pevent;
...@@ -4672,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent, ...@@ -4672,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent,
list = &arg->next; list = &arg->next;
arg->type = PRINT_FIELD; arg->type = PRINT_FIELD;
arg->field.name = strdup(field->name); arg->field.name = strdup(field->name);
if (!arg->field.name) {
do_warning("failed to allocate field name");
event->flags |= EVENT_FL_FAILED;
return -1;
}
arg->field.field = field; arg->field.field = field;
} }
return 0; return 0;
...@@ -4843,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event, ...@@ -4843,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
* @record: The record with the field name. * @record: The record with the field name.
* @err: print default error if failed. * @err: print default error if failed.
* *
* Returns: 0 on success, -1 field not fould, or 1 if buffer is full. * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
*/ */
int pevent_print_num_field(struct trace_seq *s, const char *fmt, int pevent_print_num_field(struct trace_seq *s, const char *fmt,
struct event_format *event, const char *name, struct event_format *event, const char *name,
...@@ -4885,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func) ...@@ -4885,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func)
* pevent_register_print_function - register a helper function * pevent_register_print_function - register a helper function
* @pevent: the handle to the pevent * @pevent: the handle to the pevent
* @func: the function to process the helper function * @func: the function to process the helper function
* @ret_type: the return type of the helper function
* @name: the name of the helper function * @name: the name of the helper function
* @parameters: A list of enum pevent_func_arg_type * @parameters: A list of enum pevent_func_arg_type
* *
* Some events may have helper functions in the print format arguments. * Some events may have helper functions in the print format arguments.
* This allows a plugin to dynmically create a way to process one * This allows a plugin to dynamically create a way to process one
* of these functions. * of these functions.
* *
* The @parameters is a variable list of pevent_func_arg_type enums that * The @parameters is a variable list of pevent_func_arg_type enums that
...@@ -4960,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent, ...@@ -4960,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent,
} }
/** /**
* pevent_register_event_handle - register a way to parse an event * pevent_register_event_handler - register a way to parse an event
* @pevent: the handle to the pevent * @pevent: the handle to the pevent
* @id: the id of the event to register * @id: the id of the event to register
* @sys_name: the system name the event belongs to * @sys_name: the system name the event belongs to
* @event_name: the name of the event * @event_name: the name of the event
* @func: the function to call to parse the event information * @func: the function to call to parse the event information
* @context: the data to be passed to @func
* *
* This function allows a developer to override the parsing of * This function allows a developer to override the parsing of
* a given event. If for some reason the default print format * a given event. If for some reason the default print format
...@@ -5015,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent, ...@@ -5015,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent,
if (sys_name) if (sys_name)
handle->sys_name = strdup(sys_name); handle->sys_name = strdup(sys_name);
if ((event_name && !handle->event_name) ||
(sys_name && !handle->sys_name)) {
die("Failed to allocate event/sys name");
}
handle->func = func; handle->func = func;
handle->next = pevent->handlers; handle->next = pevent->handlers;
pevent->handlers = handle; pevent->handlers = handle;
......
...@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok) ...@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
(strcmp(token, "=") == 0 || strcmp(token, "!") == 0) && (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
pevent_peek_char() == '~') { pevent_peek_char() == '~') {
/* append it */ /* append it */
*tok = malloc(3); *tok = malloc_or_die(3);
sprintf(*tok, "%c%c", *token, '~'); sprintf(*tok, "%c%c", *token, '~');
free_token(token); free_token(token);
/* Now remove the '~' from the buffer */ /* Now remove the '~' from the buffer */
...@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id) ...@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
if (filter_type) if (filter_type)
return filter_type; return filter_type;
if (!filter->filters) filter->event_filters = realloc(filter->event_filters,
filter->event_filters = sizeof(*filter->event_filters) *
malloc_or_die(sizeof(*filter->event_filters)); (filter->filters + 1));
else { if (!filter->event_filters)
filter->event_filters = die("Could not allocate filter");
realloc(filter->event_filters,
sizeof(*filter->event_filters) *
(filter->filters + 1));
if (!filter->event_filters)
die("Could not allocate filter");
}
for (i = 0; i < filter->filters; i++) { for (i = 0; i < filter->filters; i++) {
if (filter->event_filters[i].event_id > id) if (filter->event_filters[i].event_id > id)
...@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter, ...@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
{ {
struct filter_type *filter_type; struct filter_type *filter_type;
int count = 0; int count = 0;
int *ids; int *ids = NULL;
int i; int i;
if (!filter->filters) if (!filter->filters)
...@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter, ...@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
default: default:
break; break;
} }
if (count)
ids = realloc(ids, sizeof(*ids) * (count + 1)); ids = realloc(ids, sizeof(*ids) * (count + 1));
else
ids = malloc(sizeof(*ids));
if (!ids) if (!ids)
die("Can't allocate ids"); die("Can't allocate ids");
ids[count++] = filter_type->event_id; ids[count++] = filter_type->event_id;
...@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event, ...@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record) static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
{ {
const char *val = record->data + arg->str.field->offset; struct event_format *event;
struct pevent *pevent;
unsigned long long addr;
const char *val = NULL;
char hex[64];
/* /* If the field is not a string convert it */
* We need to copy the data since we can't be sure the field if (arg->str.field->flags & FIELD_IS_STRING) {
* is null terminated. val = record->data + arg->str.field->offset;
*/
if (*(val + arg->str.field->size - 1)) { /*
/* copy it */ * We need to copy the data since we can't be sure the field
memcpy(arg->str.buffer, val, arg->str.field->size); * is null terminated.
/* the buffer is already NULL terminated */ */
val = arg->str.buffer; if (*(val + arg->str.field->size - 1)) {
/* copy it */
memcpy(arg->str.buffer, val, arg->str.field->size);
/* the buffer is already NULL terminated */
val = arg->str.buffer;
}
} else {
event = arg->str.field->event;
pevent = event->pevent;
addr = get_value(event, arg->str.field, record);
if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
/* convert to a kernel symbol */
val = pevent_find_function(pevent, addr);
if (val == NULL) {
/* just use the hex of the string name */
snprintf(hex, 64, "0x%llx", addr);
val = hex;
}
} }
return val; return val;
} }
...@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) ...@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
char *lstr; char *lstr;
char *rstr; char *rstr;
char *op; char *op;
char *str; char *str = NULL;
int len; int len;
lstr = arg_to_str(filter, arg->exp.left); lstr = arg_to_str(filter, arg->exp.left);
rstr = arg_to_str(filter, arg->exp.right); rstr = arg_to_str(filter, arg->exp.right);
if (!lstr || !rstr)
goto out;
switch (arg->exp.type) { switch (arg->exp.type) {
case FILTER_EXP_ADD: case FILTER_EXP_ADD:
...@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg) ...@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
len = strlen(op) + strlen(lstr) + strlen(rstr) + 4; len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
str = malloc_or_die(len); str = malloc_or_die(len);
snprintf(str, len, "%s %s %s", lstr, op, rstr); snprintf(str, len, "%s %s %s", lstr, op, rstr);
out:
free(lstr); free(lstr);
free(rstr); free(rstr);
...@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) ...@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
lstr = arg_to_str(filter, arg->num.left); lstr = arg_to_str(filter, arg->num.left);
rstr = arg_to_str(filter, arg->num.right); rstr = arg_to_str(filter, arg->num.right);
if (!lstr || !rstr)
goto out;
switch (arg->num.type) { switch (arg->num.type) {
case FILTER_CMP_EQ: case FILTER_CMP_EQ:
...@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg) ...@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
break; break;
} }
out:
free(lstr); free(lstr);
free(rstr); free(rstr);
return str; return str;
...@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil ...@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
/* The best way to compare complex filters is with strings */ /* The best way to compare complex filters is with strings */
str1 = arg_to_str(filter1, filter_type1->filter); str1 = arg_to_str(filter1, filter_type1->filter);
str2 = arg_to_str(filter2, filter_type2->filter); str2 = arg_to_str(filter2, filter_type2->filter);
result = strcmp(str1, str2) != 0; if (str1 && str2)
result = strcmp(str1, str2) != 0;
else
/* bail out if allocation fails */
result = 1;
free(str1); free(str1);
free(str2); free(str2);
if (result) if (result)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment