user_events: Add print_fmt generation support for basic types
Addes print_fmt format generation for basic types that are supported for user processes. Only supports sizes that are the same on 32 and 64 bit. Link: https://lkml.kernel.org/r/20220118204326.2169-3-beaub@linux.microsoft.com Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
This commit is contained in:
parent
7f5a08c79d
commit
aa3b2b4c66
|
@ -359,6 +359,114 @@ static int user_event_parse_fields(struct user_event *user, char *args)
|
|||
|
||||
static struct trace_event_fields user_event_fields_array[1];
|
||||
|
||||
static const char *user_field_format(const char *type)
|
||||
{
|
||||
if (strcmp(type, "s64") == 0)
|
||||
return "%lld";
|
||||
if (strcmp(type, "u64") == 0)
|
||||
return "%llu";
|
||||
if (strcmp(type, "s32") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "u32") == 0)
|
||||
return "%u";
|
||||
if (strcmp(type, "int") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "unsigned int") == 0)
|
||||
return "%u";
|
||||
if (strcmp(type, "s16") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "u16") == 0)
|
||||
return "%u";
|
||||
if (strcmp(type, "short") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "unsigned short") == 0)
|
||||
return "%u";
|
||||
if (strcmp(type, "s8") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "u8") == 0)
|
||||
return "%u";
|
||||
if (strcmp(type, "char") == 0)
|
||||
return "%d";
|
||||
if (strcmp(type, "unsigned char") == 0)
|
||||
return "%u";
|
||||
if (strstr(type, "char[") != 0)
|
||||
return "%s";
|
||||
|
||||
/* Unknown, likely struct, allowed treat as 64-bit */
|
||||
return "%llu";
|
||||
}
|
||||
|
||||
static bool user_field_is_dyn_string(const char *type, const char **str_func)
|
||||
{
|
||||
if (str_has_prefix(type, "__data_loc ")) {
|
||||
*str_func = "__get_str";
|
||||
goto check;
|
||||
}
|
||||
|
||||
if (str_has_prefix(type, "__rel_loc ")) {
|
||||
*str_func = "__get_rel_str";
|
||||
goto check;
|
||||
}
|
||||
|
||||
return false;
|
||||
check:
|
||||
return strstr(type, "char") != 0;
|
||||
}
|
||||
|
||||
#define LEN_OR_ZERO (len ? len - pos : 0)
|
||||
static int user_event_set_print_fmt(struct user_event *user, char *buf, int len)
|
||||
{
|
||||
struct ftrace_event_field *field, *next;
|
||||
struct list_head *head = &user->fields;
|
||||
int pos = 0, depth = 0;
|
||||
const char *str_func;
|
||||
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
|
||||
|
||||
list_for_each_entry_safe_reverse(field, next, head, link) {
|
||||
if (depth != 0)
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO, " ");
|
||||
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO, "%s=%s",
|
||||
field->name, user_field_format(field->type));
|
||||
|
||||
depth++;
|
||||
}
|
||||
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO, "\"");
|
||||
|
||||
list_for_each_entry_safe_reverse(field, next, head, link) {
|
||||
if (user_field_is_dyn_string(field->type, &str_func))
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO,
|
||||
", %s(%s)", str_func, field->name);
|
||||
else
|
||||
pos += snprintf(buf + pos, LEN_OR_ZERO,
|
||||
", REC->%s", field->name);
|
||||
}
|
||||
|
||||
return pos + 1;
|
||||
}
|
||||
#undef LEN_OR_ZERO
|
||||
|
||||
static int user_event_create_print_fmt(struct user_event *user)
|
||||
{
|
||||
char *print_fmt;
|
||||
int len;
|
||||
|
||||
len = user_event_set_print_fmt(user, NULL, 0);
|
||||
|
||||
print_fmt = kmalloc(len, GFP_KERNEL);
|
||||
|
||||
if (!print_fmt)
|
||||
return -ENOMEM;
|
||||
|
||||
user_event_set_print_fmt(user, print_fmt, len);
|
||||
|
||||
user->call.print_fmt = print_fmt;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum print_line_t user_event_print_trace(struct trace_iterator *iter,
|
||||
int flags,
|
||||
struct trace_event *event)
|
||||
|
@ -392,6 +500,7 @@ static int destroy_user_event(struct user_event *user)
|
|||
clear_bit(user->index, page_bitmap);
|
||||
hash_del(&user->node);
|
||||
|
||||
kfree(user->call.print_fmt);
|
||||
kfree(EVENT_NAME(user));
|
||||
kfree(user);
|
||||
|
||||
|
@ -669,8 +778,10 @@ static int user_event_parse(char *name, char *args, char *flags,
|
|||
if (ret)
|
||||
goto put_user;
|
||||
|
||||
/* Minimal print format */
|
||||
user->call.print_fmt = "\"\"";
|
||||
ret = user_event_create_print_fmt(user);
|
||||
|
||||
if (ret)
|
||||
goto put_user;
|
||||
|
||||
user->call.data = user;
|
||||
user->call.class = &user->class;
|
||||
|
|
Loading…
Reference in New Issue