#include <ctype.h>
#include <errno.h>
#include <stdint.h>
+#include <limits.h>
#include "event-parse.h"
#include "event-utils.h"
struct cmdline *cmdlines;
int i;
- cmdlines = malloc_or_die(sizeof(*cmdlines) * pevent->cmdline_count);
+ cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
+ if (!cmdlines)
+ return -1;
i = 0;
while (cmdlist) {
if (!pid)
return "<idle>";
- if (!pevent->cmdlines)
- cmdline_init(pevent);
+ if (!pevent->cmdlines && cmdline_init(pevent))
+ return "<not enough memory for cmdlines!>";
key.pid = pid;
if (!pid)
return 1;
- if (!pevent->cmdlines)
- cmdline_init(pevent);
+ if (!pevent->cmdlines && cmdline_init(pevent))
+ return 0;
key.pid = pid;
return -1;
}
- cmdlines[pevent->cmdline_count].pid = pid;
cmdlines[pevent->cmdline_count].comm = strdup(comm);
- if (!cmdlines[pevent->cmdline_count].comm)
- die("malloc comm");
+ if (!cmdlines[pevent->cmdline_count].comm) {
+ free(cmdlines);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ cmdlines[pevent->cmdline_count].pid = pid;
if (cmdlines[pevent->cmdline_count].comm)
pevent->cmdline_count++;
if (pevent->cmdlines)
return add_new_comm(pevent, comm, pid);
- item = malloc_or_die(sizeof(*item));
+ item = malloc(sizeof(*item));
+ if (!item)
+ return -1;
+
item->comm = strdup(comm);
- if (!item->comm)
- die("malloc comm");
+ if (!item->comm) {
+ free(item);
+ return -1;
+ }
item->pid = pid;
item->next = pevent->cmdlist;
struct func_map *func_map;
int i;
- func_map = malloc_or_die(sizeof(*func_map) * (pevent->func_count + 1));
+ func_map = malloc(sizeof(*func_map) * (pevent->func_count + 1));
+ if (!func_map)
+ return -1;
+
funclist = pevent->funclist;
i = 0;
int pevent_register_function(struct pevent *pevent, char *func,
unsigned long long addr, char *mod)
{
- struct func_list *item;
+ struct func_list *item = malloc(sizeof(*item));
- item = malloc_or_die(sizeof(*item));
+ if (!item)
+ return -1;
item->next = pevent->funclist;
item->func = strdup(func);
- if (mod)
+ if (!item->func)
+ goto out_free;
+
+ if (mod) {
item->mod = strdup(mod);
- else
+ if (!item->mod)
+ goto out_free_func;
+ } else
item->mod = NULL;
item->addr = addr;
- if (!item->func || (mod && !item->mod))
- die("malloc func");
-
pevent->funclist = item;
pevent->func_count++;
return 0;
+
+out_free_func:
+ free(item->func);
+ item->func = NULL;
+out_free:
+ free(item);
+ errno = ENOMEM;
+ return -1;
}
/**
return 0;
}
-static void printk_map_init(struct pevent *pevent)
+static int printk_map_init(struct pevent *pevent)
{
struct printk_list *printklist;
struct printk_list *item;
struct printk_map *printk_map;
int i;
- printk_map = malloc_or_die(sizeof(*printk_map) * (pevent->printk_count + 1));
+ printk_map = malloc(sizeof(*printk_map) * (pevent->printk_count + 1));
+ if (!printk_map)
+ return -1;
printklist = pevent->printklist;
pevent->printk_map = printk_map;
pevent->printklist = NULL;
+
+ return 0;
}
static struct printk_map *
struct printk_map *printk;
struct printk_map key;
- if (!pevent->printk_map)
- printk_map_init(pevent);
+ if (!pevent->printk_map && printk_map_init(pevent))
+ return NULL;
key.addr = addr;
int pevent_register_print_string(struct pevent *pevent, char *fmt,
unsigned long long addr)
{
- struct printk_list *item;
+ struct printk_list *item = malloc(sizeof(*item));
- item = malloc_or_die(sizeof(*item));
+ if (!item)
+ return -1;
item->next = pevent->printklist;
- item->printk = strdup(fmt);
item->addr = addr;
+ item->printk = strdup(fmt);
if (!item->printk)
- die("malloc fmt");
+ goto out_free;
pevent->printklist = item;
pevent->printk_count++;
return 0;
+
+out_free:
+ free(item);
+ errno = ENOMEM;
+ return -1;
}
/**
return calloc(1, sizeof(struct event_format));
}
-static void add_event(struct pevent *pevent, struct event_format *event)
+static int add_event(struct pevent *pevent, struct event_format *event)
{
int i;
+ struct event_format **events = realloc(pevent->events, sizeof(event) *
+ (pevent->nr_events + 1));
+ if (!events)
+ return -1;
- pevent->events = realloc(pevent->events, sizeof(event) *
- (pevent->nr_events + 1));
- if (!pevent->events)
- die("Can not allocate events");
+ pevent->events = events;
for (i = 0; i < pevent->nr_events; i++) {
if (pevent->events[i]->id > event->id)
pevent->nr_events++;
event->pevent = pevent;
+
+ return 0;
}
static int event_item_type(enum event_type type)
}
if (!field->type) {
- die("no type found");
+ do_warning("%s: no type found", __func__);
goto fail;
}
field->name = last_token;
free_token(token);
type = read_token(&token);
if (type == EVENT_NONE) {
- die("failed to find token");
+ do_warning("failed to find token");
goto fail;
}
}
left = alloc_arg();
right = alloc_arg();
+ if (!arg || !left || !right) {
+ do_warning("%s: not enough memory!", __func__);
+ /* arg will be freed at out_free */
+ free_arg(left);
+ free_arg(right);
+ goto out_free;
+ }
+
arg->type = PRINT_OP;
arg->op.left = left;
arg->op.right = right;
char *token = NULL;
arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s: not enough memory!", __func__);
+ /* '*tok' is set to top->op.op. No need to free. */
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
*tok = NULL;
type = process_arg(event, arg, &token);
if (arg->type == PRINT_OP && !arg->op.left) {
/* handle single op */
if (token[1]) {
- die("bad op token %s", token);
+ do_warning("bad op token %s", token);
goto out_free;
}
switch (token[0]) {
/* make an empty left */
left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
left->type = PRINT_NULL;
arg->op.left = left;
right = alloc_arg();
+ if (!right)
+ goto out_warn_free;
+
arg->op.right = right;
/* do not free the token, it belongs to an op */
} else if (strcmp(token, "?") == 0) {
left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
/* copy the top arg to the left */
*left = *arg;
strcmp(token, "!=") == 0) {
left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
/* copy the top arg to the left */
*left = *arg;
type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
char *new_atom;
- if (left->type != PRINT_ATOM)
- die("bad pointer type");
+ if (left->type != PRINT_ATOM) {
+ do_warning("bad pointer type");
+ goto out_free;
+ }
new_atom = realloc(left->atom.atom,
strlen(left->atom.atom) + 3);
if (!new_atom)
- goto out_free;
+ goto out_warn_free;
left->atom.atom = new_atom;
strcat(left->atom.atom, " *");
}
right = alloc_arg();
+ if (!right)
+ goto out_warn_free;
+
type = process_arg_token(event, right, tok, type);
arg->op.right = right;
} else if (strcmp(token, "[") == 0) {
left = alloc_arg();
+ if (!left)
+ goto out_warn_free;
+
*left = *arg;
arg->type = PRINT_OP;
return type;
- out_free:
+out_warn_free:
+ do_warning("%s: not enough memory!", __func__);
+out_free:
free_token(token);
*tok = NULL;
return EVENT_ERROR;
return val;
}
- ref = malloc_or_die(len);
+ ref = malloc(len);
+ if (!ref) {
+ do_warning("%s: not enough memory!", __func__);
+ return val;
+ }
memcpy(ref, type, len);
/* chop off the " *" */
static unsigned long long
eval_type(unsigned long long val, struct print_arg *arg, int pointer)
{
- if (arg->type != PRINT_TYPE)
- die("expected type argument");
+ if (arg->type != PRINT_TYPE) {
+ do_warning("expected type argument");
+ return 0;
+ }
return eval_type_str(val, arg->typecast.type, pointer);
}
case PRINT_STRING:
case PRINT_BSTRING:
default:
- die("invalid eval type %d", arg->type);
+ do_warning("invalid eval type %d", arg->type);
break;
}
break;
arg = alloc_arg();
+ if (!arg)
+ goto out_free;
free_token(token);
type = process_arg(event, arg, &token);
free_arg(arg);
arg = alloc_arg();
+ if (!arg)
+ goto out_free;
free_token(token);
type = process_arg(event, arg, &token);
arg->type = PRINT_FLAGS;
field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out_free;
+ }
type = process_arg(event, field, &token);
arg->type = PRINT_SYMBOL;
field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out_free;
+ }
type = process_arg(event, field, &token);
if (test_type_token(type, token, EVENT_DELIM, ","))
arg->type = PRINT_HEX;
field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out_free;
+ }
+
type = process_arg(event, field, &token);
if (test_type_token(type, token, EVENT_DELIM, ","))
free_token(token);
field = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
+
type = process_arg(event, field, &token);
if (test_type_token(type, token, EVENT_DELIM, ")"))
free_token(token);
arg = alloc_arg();
+ if (!field) {
+ do_warning("%s: not enough memory!", __func__);
+ *tok = NULL;
+ return EVENT_ERROR;
+ }
+
type = process_arg(event, arg, &token);
if (type == EVENT_ERROR)
goto out_free_arg;
/* make this a typecast and contine */
/* prevous must be an atom */
- if (arg->type != PRINT_ATOM)
- die("previous needed to be PRINT_ATOM");
+ if (arg->type != PRINT_ATOM) {
+ do_warning("previous needed to be PRINT_ATOM");
+ goto out_free;
+ }
item_arg = alloc_arg();
+ if (!item_arg) {
+ do_warning("%s: not enough memory!", __func__);
+ goto out_free;
+ }
arg->type = PRINT_TYPE;
arg->typecast.type = arg->atom.atom;
{
struct pevent_function_handler *func;
+ if (!pevent)
+ return NULL;
+
for (func = pevent->func_handlers; func; func = func->next) {
if (strcmp(func->name, func_name) == 0)
break;
next_arg = &(arg->func.args);
for (i = 0; i < func->nr_args; i++) {
farg = alloc_arg();
+ if (!farg) {
+ do_warning("%s: not enough memory!", __func__);
+ return EVENT_ERROR;
+ }
+
type = process_arg(event, farg, &token);
if (i < (func->nr_args - 1))
test = ",";
case EVENT_ERROR ... EVENT_NEWLINE:
default:
- die("unexpected type %d", type);
+ do_warning("unexpected type %d", type);
+ return EVENT_ERROR;
}
*tok = token;
}
arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s: not enough memory!", __func__);
+ return -1;
+ }
type = process_arg(event, arg, &token);
* All events should have the same common elements.
* Pick any event to find where the type is;
*/
- if (!pevent->events)
- die("no event_list!");
+ if (!pevent->events) {
+ do_warning("no event_list!");
+ return -1;
+ }
event = pevent->events[0];
field = pevent_find_common_field(event, type);
if (!arg->field.field) {
arg->field.field = pevent_find_any_field(event, arg->field.name);
if (!arg->field.field)
- die("field %s not found", arg->field.name);
+ goto out_warning_field;
+
}
/* must be a number */
val = pevent_read_number(pevent, data + arg->field.field->offset,
if (!larg->field.field) {
larg->field.field =
pevent_find_any_field(event, larg->field.name);
- if (!larg->field.field)
- die("field %s not found", larg->field.name);
+ if (!larg->field.field) {
+ arg = larg;
+ goto out_warning_field;
+ }
}
field_size = larg->field.field->elementsize;
offset = larg->field.field->offset +
val = left != right;
break;
default:
- die("unknown op '%s'", arg->op.op);
+ goto out_warning_op;
}
break;
case '~':
val = left <= right;
break;
default:
- die("unknown op '%s'", arg->op.op);
+ goto out_warning_op;
}
break;
case '>':
val = left >= right;
break;
default:
- die("unknown op '%s'", arg->op.op);
+ goto out_warning_op;
}
break;
case '=':
if (arg->op.op[1] != '=')
- die("unknown op '%s'", arg->op.op);
+ goto out_warning_op;
+
val = left == right;
break;
case '-':
val = left * right;
break;
default:
- die("unknown op '%s'", arg->op.op);
+ goto out_warning_op;
}
break;
default: /* not sure what to do there */
return 0;
}
return val;
+
+out_warning_op:
+ do_warning("%s: unknown op '%s'", __func__, arg->op.op);
+ return 0;
+
+out_warning_field:
+ do_warning("%s: field %s not found", __func__, arg->field.name);
+ return 0;
}
struct flag {
field = arg->field.field;
if (!field) {
field = pevent_find_any_field(event, arg->field.name);
- if (!field)
- die("field %s not found", arg->field.name);
+ if (!field) {
+ str = arg->field.name;
+ goto out_warning_field;
+ }
arg->field.field = field;
}
/* Zero sized fields, mean the rest of the data */
trace_seq_printf(s, "%lx", addr);
break;
}
- str = malloc_or_die(len + 1);
+ str = malloc(len + 1);
+ if (!str) {
+ do_warning("%s: not enough memory!", __func__);
+ return;
+ }
memcpy(str, data + field->offset, len);
str[len] = 0;
print_str_to_seq(s, format, len_arg, str);
str = arg->hex.field->field.name;
field = pevent_find_any_field(event, str);
if (!field)
- die("field %s not found", str);
+ goto out_warning_field;
arg->hex.field->field.field = field;
}
hex = data + field->offset;
/* well... */
break;
}
+
+ return;
+
+out_warning_field:
+ do_warning("%s: field %s not found", __func__, arg->field.name);
}
static unsigned long long
farg = arg->func.args;
param = func_handle->params;
- args = malloc_or_die(sizeof(*args) * func_handle->nr_args);
+ ret = ULLONG_MAX;
+ args = malloc(sizeof(*args) * func_handle->nr_args);
+ if (!args)
+ goto out;
+
for (i = 0; i < func_handle->nr_args; i++) {
switch (param->type) {
case PEVENT_FUNC_ARG_INT:
trace_seq_init(&str);
print_str_arg(&str, data, size, event, "%s", -1, farg);
trace_seq_terminate(&str);
- string = malloc_or_die(sizeof(*string));
+ string = malloc(sizeof(*string));
+ if (!string) {
+ do_warning("%s(%d): malloc str", __func__, __LINE__);
+ goto out_free;
+ }
string->next = strings;
string->str = strdup(str.buffer);
- if (!string->str)
- die("malloc str");
-
+ if (!string->str) {
+ free(string);
+ do_warning("%s(%d): malloc str", __func__, __LINE__);
+ goto out_free;
+ }
args[i] = (uintptr_t)string->str;
strings = string;
trace_seq_destroy(&str);
* Something went totally wrong, this is not
* an input error, something in this code broke.
*/
- die("Unexpected end of arguments\n");
- break;
+ do_warning("Unexpected end of arguments\n");
+ goto out_free;
}
farg = farg->next;
param = param->next;
}
ret = (*func_handle->func)(s, args);
+out_free:
free(args);
while (strings) {
string = strings;
if (!field) {
field = pevent_find_field(event, "buf");
- if (!field)
- die("can't find buffer field for binary printk");
+ if (!field) {
+ do_warning("can't find buffer field for binary printk");
+ return NULL;
+ }
ip_field = pevent_find_field(event, "ip");
- if (!ip_field)
- die("can't find ip field for binary printk");
+ if (!ip_field) {
+ do_warning("can't find ip field for binary printk");
+ return NULL;
+ }
pevent->bprint_buf_field = field;
pevent->bprint_ip_field = ip_field;
}
* The first arg is the IP pointer.
*/
args = alloc_arg();
+ if (!args) {
+ do_warning("%s(%d): not enough memory!", __func__, __LINE__);
+ return NULL;
+ }
arg = args;
arg->next = NULL;
next = &arg->next;
val = pevent_read_number(pevent, bptr, vsize);
bptr += vsize;
arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s(%d): not enough memory!",
+ __func__, __LINE__);
+ goto out_free;
+ }
arg->next = NULL;
arg->type = PRINT_ATOM;
if (asprintf(&arg->atom.atom, "%lld", val) < 0) {
break;
case 's':
arg = alloc_arg();
+ if (!arg) {
+ do_warning("%s(%d): not enough memory!",
+ __func__, __LINE__);
+ goto out_free;
+ }
arg->next = NULL;
arg->type = PRINT_BSTRING;
arg->string.string = strdup(bptr);
if (!arg->string.string)
- break;
+ goto out_free;
bptr += strlen(bptr) + 1;
*next = arg;
next = &arg->next;
if (!field) {
field = pevent_find_field(event, "fmt");
- if (!field)
- die("can't find format field for binary printk");
+ if (!field) {
+ do_warning("can't find format field for binary printk");
+ return NULL;
+ }
pevent->bprint_fmt_field = field;
}
if (!arg->field.field) {
arg->field.field =
pevent_find_any_field(event, arg->field.name);
- if (!arg->field.field)
- die("field %s not found", arg->field.name);
+ if (!arg->field.field) {
+ do_warning("%s: field %s not found",
+ __func__, arg->field.name);
+ return;
+ }
}
if (arg->field.field->size != 6) {
trace_seq_printf(s, "INVALIDMAC");
struct format_field *field;
int i = 0;
- fields = malloc_or_die(sizeof(*fields) * (count + 1));
+ fields = malloc(sizeof(*fields) * (count + 1));
+ if (!fields)
+ return NULL;
+
for (field = list; field; field = field->next) {
fields[i++] = field;
if (i == count + 1) {
}
/**
- * pevent_parse_event - parse the event format
- * @pevent: the handle to the pevent
+ * __pevent_parse_format - parse the event format
* @buf: the buffer storing the event format string
* @size: the size of @buf
* @sys: the system the event belongs to
*
* /sys/kernel/debug/tracing/events/.../.../format
*/
-enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
- unsigned long size, const char *sys)
+enum pevent_errno __pevent_parse_format(struct event_format **eventp,
+ struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys)
{
struct event_format *event;
int ret;
init_input_buf(buf, size);
- event = alloc_event();
+ *eventp = event = alloc_event();
if (!event)
return PEVENT_ERRNO__MEM_ALLOC_FAILED;
* If the event has an override, don't print warnings if the event
* print format fails to parse.
*/
- if (find_event_handle(pevent, event))
+ if (pevent && find_event_handle(pevent, event))
show_warning = 0;
ret = event_read_print(event);
+ show_warning = 1;
+
if (ret < 0) {
- show_warning = 1;
ret = PEVENT_ERRNO__READ_PRINT_FAILED;
goto event_parse_failed;
}
- show_warning = 1;
-
- add_event(pevent, event);
if (!ret && (event->flags & EVENT_FL_ISFTRACE)) {
struct format_field *field;
list = &event->print_fmt.args;
for (field = event->format.fields; field; field = field->next) {
arg = alloc_arg();
+ if (!arg) {
+ event->flags |= EVENT_FL_FAILED;
+ return PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED;
+ }
arg->type = PRINT_FIELD;
arg->field.name = strdup(field->name);
if (!arg->field.name) {
return 0;
}
-#define PRINT_ARGS 0
- if (PRINT_ARGS && event->print_fmt.args)
- print_args(event->print_fmt.args);
-
return 0;
event_parse_failed:
event->flags |= EVENT_FL_FAILED;
- /* still add it even if it failed */
- add_event(pevent, event);
return ret;
event_alloc_failed:
free(event->system);
free(event->name);
free(event);
+ *eventp = NULL;
+ return ret;
+}
+
+/**
+ * pevent_parse_format - parse the event format
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf,
+ unsigned long size, const char *sys)
+{
+ return __pevent_parse_format(eventp, NULL, buf, size, sys);
+}
+
+/**
+ * pevent_parse_event - parse the event format
+ * @pevent: the handle to the pevent
+ * @buf: the buffer storing the event format string
+ * @size: the size of @buf
+ * @sys: the system the event belongs to
+ *
+ * This parses the event format and creates an event structure
+ * to quickly parse raw data for a given event.
+ *
+ * These files currently come from:
+ *
+ * /sys/kernel/debug/tracing/events/.../.../format
+ */
+enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
+ unsigned long size, const char *sys)
+{
+ struct event_format *event = NULL;
+ int ret = __pevent_parse_format(&event, pevent, buf, size, sys);
+
+ if (event == NULL)
+ return ret;
+
+ if (add_event(pevent, event)) {
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto event_add_failed;
+ }
+
+#define PRINT_ARGS 0
+ if (PRINT_ARGS && event->print_fmt.args)
+ print_args(event->print_fmt.args);
+
+ return 0;
+
+event_add_failed:
+ pevent_free_format(event);
return ret;
}
free_format_fields(format->fields);
}
-static void free_event(struct event_format *event)
+void pevent_free_format(struct event_format *event)
{
free(event->name);
free(event->system);
}
for (i = 0; i < pevent->nr_events; i++)
- free_event(pevent->events[i]);
+ pevent_free_format(pevent->events[i]);
while (pevent->handlers) {
handle = pevent->handlers;