|
@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func,
|
|
|
item->mod = NULL;
|
|
|
item->addr = addr;
|
|
|
|
|
|
- pevent->funclist = item;
|
|
|
+ if (!item->func || (mod && !item->mod))
|
|
|
+ die("malloc func");
|
|
|
|
|
|
+ pevent->funclist = item;
|
|
|
pevent->func_count++;
|
|
|
|
|
|
return 0;
|
|
@@ -511,12 +513,12 @@ struct printk_list {
|
|
|
|
|
|
static int printk_cmp(const void *a, const void *b)
|
|
|
{
|
|
|
- const struct func_map *fa = a;
|
|
|
- const struct func_map *fb = b;
|
|
|
+ const struct printk_map *pa = a;
|
|
|
+ const struct printk_map *pb = b;
|
|
|
|
|
|
- if (fa->addr < fb->addr)
|
|
|
+ if (pa->addr < pb->addr)
|
|
|
return -1;
|
|
|
- if (fa->addr > fb->addr)
|
|
|
+ if (pa->addr > pb->addr)
|
|
|
return 1;
|
|
|
|
|
|
return 0;
|
|
@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
|
|
|
item = malloc_or_die(sizeof(*item));
|
|
|
|
|
|
item->next = pevent->printklist;
|
|
|
- pevent->printklist = item;
|
|
|
item->printk = strdup(fmt);
|
|
|
item->addr = addr;
|
|
|
|
|
|
+ if (!item->printk)
|
|
|
+ die("malloc fmt");
|
|
|
+
|
|
|
+ pevent->printklist = item;
|
|
|
pevent->printk_count++;
|
|
|
|
|
|
return 0;
|
|
@@ -628,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event)
|
|
|
{
|
|
|
int i;
|
|
|
|
|
|
- if (!pevent->events)
|
|
|
- pevent->events = malloc_or_die(sizeof(event));
|
|
|
- else
|
|
|
- pevent->events =
|
|
|
- realloc(pevent->events, sizeof(event) *
|
|
|
- (pevent->nr_events + 1));
|
|
|
+ pevent->events = realloc(pevent->events, sizeof(event) *
|
|
|
+ (pevent->nr_events + 1));
|
|
|
if (!pevent->events)
|
|
|
die("Can not allocate events");
|
|
|
|
|
@@ -781,6 +782,25 @@ int pevent_peek_char(void)
|
|
|
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 __read_token(char **tok)
|
|
@@ -865,17 +885,10 @@ static enum event_type __read_token(char **tok)
|
|
|
do {
|
|
|
if (i == (BUFSIZ - 1)) {
|
|
|
buf[i] = 0;
|
|
|
- if (*tok) {
|
|
|
- *tok = realloc(*tok, tok_size + BUFSIZ);
|
|
|
- if (!*tok)
|
|
|
- return EVENT_NONE;
|
|
|
- strcat(*tok, buf);
|
|
|
- } else
|
|
|
- *tok = strdup(buf);
|
|
|
+ tok_size += BUFSIZ;
|
|
|
|
|
|
- if (!*tok)
|
|
|
+ if (extend_token(tok, buf, tok_size) < 0)
|
|
|
return EVENT_NONE;
|
|
|
- tok_size += BUFSIZ;
|
|
|
i = 0;
|
|
|
}
|
|
|
last_ch = ch;
|
|
@@ -914,17 +927,10 @@ static enum event_type __read_token(char **tok)
|
|
|
while (get_type(__peek_char()) == type) {
|
|
|
if (i == (BUFSIZ - 1)) {
|
|
|
buf[i] = 0;
|
|
|
- if (*tok) {
|
|
|
- *tok = realloc(*tok, tok_size + BUFSIZ);
|
|
|
- if (!*tok)
|
|
|
- return EVENT_NONE;
|
|
|
- strcat(*tok, buf);
|
|
|
- } else
|
|
|
- *tok = strdup(buf);
|
|
|
+ tok_size += BUFSIZ;
|
|
|
|
|
|
- if (!*tok)
|
|
|
+ if (extend_token(tok, buf, tok_size) < 0)
|
|
|
return EVENT_NONE;
|
|
|
- tok_size += BUFSIZ;
|
|
|
i = 0;
|
|
|
}
|
|
|
ch = __read_char();
|
|
@@ -933,14 +939,7 @@ static enum event_type __read_token(char **tok)
|
|
|
|
|
|
out:
|
|
|
buf[i] = 0;
|
|
|
- if (*tok) {
|
|
|
- *tok = realloc(*tok, tok_size + i);
|
|
|
- if (!*tok)
|
|
|
- return EVENT_NONE;
|
|
|
- strcat(*tok, buf);
|
|
|
- } else
|
|
|
- *tok = strdup(buf);
|
|
|
- if (!*tok)
|
|
|
+ if (extend_token(tok, buf, tok_size + i + 1) < 0)
|
|
|
return EVENT_NONE;
|
|
|
|
|
|
if (type == EVENT_ITEM) {
|
|
@@ -1261,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
field->flags |= FIELD_IS_POINTER;
|
|
|
|
|
|
if (field->type) {
|
|
|
- field->type = realloc(field->type,
|
|
|
- strlen(field->type) +
|
|
|
- strlen(last_token) + 2);
|
|
|
+ char *new_type;
|
|
|
+ new_type = realloc(field->type,
|
|
|
+ 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, last_token);
|
|
|
free(last_token);
|
|
@@ -1288,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
if (strcmp(token, "[") == 0) {
|
|
|
enum event_type last_type = type;
|
|
|
char *brackets = token;
|
|
|
+ char *new_brackets;
|
|
|
int len;
|
|
|
|
|
|
field->flags |= FIELD_IS_ARRAY;
|
|
@@ -1307,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
len = 1;
|
|
|
last_type = type;
|
|
|
|
|
|
- brackets = realloc(brackets,
|
|
|
- strlen(brackets) +
|
|
|
- strlen(token) + len);
|
|
|
+ new_brackets = realloc(brackets,
|
|
|
+ strlen(brackets) +
|
|
|
+ strlen(token) + len);
|
|
|
+ if (!new_brackets) {
|
|
|
+ free(brackets);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ brackets = new_brackets;
|
|
|
if (len == 2)
|
|
|
strcat(brackets, " ");
|
|
|
strcat(brackets, token);
|
|
@@ -1325,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
|
|
|
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, "]");
|
|
|
|
|
|
/* add brackets to type */
|
|
@@ -1336,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
* the format: type [] item;
|
|
|
*/
|
|
|
if (type == EVENT_ITEM) {
|
|
|
- field->type = realloc(field->type,
|
|
|
- strlen(field->type) +
|
|
|
- strlen(field->name) +
|
|
|
- strlen(brackets) + 2);
|
|
|
+ char *new_type;
|
|
|
+ new_type = realloc(field->type,
|
|
|
+ strlen(field->type) +
|
|
|
+ strlen(field->name) +
|
|
|
+ strlen(brackets) + 2);
|
|
|
+ if (!new_type) {
|
|
|
+ free(brackets);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ field->type = new_type;
|
|
|
strcat(field->type, " ");
|
|
|
strcat(field->type, field->name);
|
|
|
free_token(field->name);
|
|
@@ -1347,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
|
|
|
field->name = token;
|
|
|
type = read_token(&token);
|
|
|
} else {
|
|
|
- field->type = realloc(field->type,
|
|
|
- strlen(field->type) +
|
|
|
- strlen(brackets) + 1);
|
|
|
+ char *new_type;
|
|
|
+ new_type = realloc(field->type,
|
|
|
+ strlen(field->type) +
|
|
|
+ strlen(brackets) + 1);
|
|
|
+ if (!new_type) {
|
|
|
+ free(brackets);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
+ field->type = new_type;
|
|
|
strcat(field->type, brackets);
|
|
|
}
|
|
|
free(brackets);
|
|
@@ -1732,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
|
|
|
/* could just be a type pointer */
|
|
|
if ((strcmp(arg->op.op, "*") == 0) &&
|
|
|
type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
|
|
|
+ char *new_atom;
|
|
|
+
|
|
|
if (left->type != PRINT_ATOM)
|
|
|
die("bad pointer type");
|
|
|
- left->atom.atom = realloc(left->atom.atom,
|
|
|
+ new_atom = realloc(left->atom.atom,
|
|
|
strlen(left->atom.atom) + 3);
|
|
|
+ if (!new_atom)
|
|
|
+ goto out_free;
|
|
|
+
|
|
|
+ left->atom.atom = new_atom;
|
|
|
strcat(left->atom.atom, " *");
|
|
|
free(arg->op.op);
|
|
|
*arg = *left;
|
|
@@ -2152,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
|
|
|
if (value == NULL)
|
|
|
goto out_free;
|
|
|
field->value = strdup(value);
|
|
|
+ if (field->value == NULL)
|
|
|
+ goto out_free;
|
|
|
|
|
|
free_arg(arg);
|
|
|
arg = alloc_arg();
|
|
@@ -2165,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
|
|
|
if (value == NULL)
|
|
|
goto out_free;
|
|
|
field->str = strdup(value);
|
|
|
+ if (field->str == NULL)
|
|
|
+ goto out_free;
|
|
|
free_arg(arg);
|
|
|
arg = NULL;
|
|
|
|
|
@@ -2590,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
|
|
|
}
|
|
|
/* atoms can be more than one token long */
|
|
|
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, token);
|
|
|
free_token(token);
|
|
@@ -2884,7 +2931,7 @@ static int get_common_info(struct pevent *pevent,
|
|
|
event = pevent->events[0];
|
|
|
field = pevent_find_common_field(event, type);
|
|
|
if (!field)
|
|
|
- die("field '%s' not found", type);
|
|
|
+ return -1;
|
|
|
|
|
|
*offset = field->offset;
|
|
|
*size = field->size;
|
|
@@ -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)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = __parse_common(pevent, data,
|
|
|
- &pevent->ld_size, &pevent->ld_offset,
|
|
|
- "common_lock_depth");
|
|
|
- if (ret < 0)
|
|
|
- return -1;
|
|
|
+ return __parse_common(pevent, data,
|
|
|
+ &pevent->ld_size, &pevent->ld_offset,
|
|
|
+ "common_lock_depth");
|
|
|
+}
|
|
|
|
|
|
- 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);
|
|
@@ -3370,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
|
|
|
break;
|
|
|
}
|
|
|
case PRINT_BSTRING:
|
|
|
- trace_seq_printf(s, format, arg->string.string);
|
|
|
+ print_str_to_seq(s, format, len_arg, arg->string.string);
|
|
|
break;
|
|
|
case PRINT_OP:
|
|
|
/*
|
|
@@ -3434,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size,
|
|
|
string = malloc_or_die(sizeof(*string));
|
|
|
string->next = strings;
|
|
|
string->str = strdup(str.buffer);
|
|
|
+ if (!string->str)
|
|
|
+ die("malloc str");
|
|
|
+
|
|
|
+ args[i] = (unsigned long long)string->str;
|
|
|
strings = string;
|
|
|
trace_seq_destroy(&str);
|
|
|
break;
|
|
@@ -3471,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
|
|
|
unsigned long long ip, val;
|
|
|
char *ptr;
|
|
|
void *bptr;
|
|
|
+ int vsize;
|
|
|
|
|
|
field = pevent->bprint_buf_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
|
|
|
goto process_again;
|
|
|
case '0' ... '9':
|
|
|
goto process_again;
|
|
|
+ case '.':
|
|
|
+ goto process_again;
|
|
|
case 'p':
|
|
|
ls = 1;
|
|
|
/* fall through */
|
|
@@ -3526,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
|
|
|
case 'u':
|
|
|
case 'x':
|
|
|
case 'i':
|
|
|
- /* the pointers are always 4 bytes aligned */
|
|
|
- bptr = (void *)(((unsigned long)bptr + 3) &
|
|
|
- ~3);
|
|
|
switch (ls) {
|
|
|
case 0:
|
|
|
- ls = 4;
|
|
|
+ vsize = 4;
|
|
|
break;
|
|
|
case 1:
|
|
|
- ls = pevent->long_size;
|
|
|
+ vsize = pevent->long_size;
|
|
|
break;
|
|
|
case 2:
|
|
|
- ls = 8;
|
|
|
+ vsize = 8;
|
|
|
+ break;
|
|
|
default:
|
|
|
+ vsize = ls; /* ? */
|
|
|
break;
|
|
|
}
|
|
|
- val = pevent_read_number(pevent, bptr, ls);
|
|
|
- bptr += ls;
|
|
|
+ /* fall through */
|
|
|
+ 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->next = NULL;
|
|
|
arg->type = PRINT_ATOM;
|
|
@@ -3550,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
|
|
|
sprintf(arg->atom.atom, "%lld", val);
|
|
|
*next = arg;
|
|
|
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;
|
|
|
case 's':
|
|
|
arg = alloc_arg();
|
|
|
arg->next = NULL;
|
|
|
arg->type = PRINT_BSTRING;
|
|
|
arg->string.string = strdup(bptr);
|
|
|
+ if (!arg->string.string)
|
|
|
+ break;
|
|
|
bptr += strlen(bptr) + 1;
|
|
|
*next = arg;
|
|
|
next = &arg->next;
|
|
@@ -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') {
|
|
|
print_mac_arg(s, *(ptr+1), data, size, event, arg);
|
|
|
ptr++;
|
|
|
+ arg = arg->next;
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -3877,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- if (pevent->long_size == 8 && ls) {
|
|
|
+ if (pevent->long_size == 8 && ls &&
|
|
|
+ sizeof(long) != 8) {
|
|
|
char *p;
|
|
|
|
|
|
ls = 2;
|
|
|
/* make %l into %ll */
|
|
|
p = strchr(format, 'l');
|
|
|
if (p)
|
|
|
- memmove(p, p+1, strlen(p)+1);
|
|
|
+ memmove(p+1, p, strlen(p)+1);
|
|
|
else if (strcmp(format, "%p") == 0)
|
|
|
strcpy(format, "0x%llx");
|
|
|
}
|
|
@@ -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: a handle to the pevent
|
|
|
* @s: the trace_seq to write to
|
|
|
- * @data: the raw data to read from
|
|
|
- * @size: currently unused.
|
|
|
+ * @record: the record to read from
|
|
|
*
|
|
|
* This parses out the Latency format (interrupts disabled,
|
|
|
* need rescheduling, in hard/soft interrupt, preempt count
|
|
@@ -3972,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
|
|
|
struct trace_seq *s, struct pevent_record *record)
|
|
|
{
|
|
|
static int check_lock_depth = 1;
|
|
|
+ static int check_migrate_disable = 1;
|
|
|
static int lock_depth_exists;
|
|
|
+ static int migrate_disable_exists;
|
|
|
unsigned int lat_flags;
|
|
|
unsigned int pc;
|
|
|
int lock_depth;
|
|
|
+ int migrate_disable;
|
|
|
int hardirq;
|
|
|
int softirq;
|
|
|
void *data = record->data;
|
|
@@ -3983,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent,
|
|
|
lat_flags = parse_common_flags(pevent, data);
|
|
|
pc = parse_common_pc(pevent, data);
|
|
|
/* 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)
|
|
|
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;
|
|
|
softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
|
|
@@ -4013,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
|
|
|
else
|
|
|
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 < 0)
|
|
|
trace_seq_putc(s, '.');
|
|
@@ -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
|
|
|
* @s: the trace_seq to write to
|
|
|
* @event: the handle to the event
|
|
|
- * @cpu: the cpu the event was recorded on
|
|
|
- * @data: the raw data
|
|
|
- * @size: the size of the raw data
|
|
|
- * @nsecs: the timestamp of the event
|
|
|
+ * @record: the record to read from
|
|
|
*
|
|
|
* This parses the raw @data using the given @event information and
|
|
|
* writes the print format into the trace_seq.
|
|
@@ -4631,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent,
|
|
|
die("failed to read event id");
|
|
|
|
|
|
event->system = strdup(sys);
|
|
|
+ if (!event->system)
|
|
|
+ die("failed to allocate system");
|
|
|
|
|
|
/* Add pevent to event so that it can be referenced */
|
|
|
event->pevent = pevent;
|
|
@@ -4672,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent,
|
|
|
list = &arg->next;
|
|
|
arg->type = PRINT_FIELD;
|
|
|
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;
|
|
|
}
|
|
|
return 0;
|
|
@@ -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.
|
|
|
* @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,
|
|
|
struct event_format *event, const char *name,
|
|
@@ -4885,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func)
|
|
|
* pevent_register_print_function - register a helper function
|
|
|
* @pevent: the handle to the pevent
|
|
|
* @func: the function to process the helper function
|
|
|
+ * @ret_type: the return type of the helper function
|
|
|
* @name: the name of the helper function
|
|
|
* @parameters: A list of enum pevent_func_arg_type
|
|
|
*
|
|
|
* 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.
|
|
|
*
|
|
|
* 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,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 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
|
|
|
* @id: the id of the event to register
|
|
|
* @sys_name: the system name the event belongs to
|
|
|
* @event_name: the name of the event
|
|
|
* @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
|
|
|
* a given event. If for some reason the default print format
|
|
@@ -5015,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent,
|
|
|
if (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->next = pevent->handlers;
|
|
|
pevent->handlers = handle;
|