Loading include/uapi/linux/perf_event.h +1 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,7 @@ enum perf_event_type { * u32 min; * u64 ino; * u64 ino_generation; * u32 prot, flags; * char filename[]; * struct sample_id sample_id; * }; Loading kernel/events/core.c +33 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ #include <linux/mm_types.h> #include <linux/cgroup.h> #include <linux/module.h> #include <linux/mman.h> #include "internal.h" Loading Loading @@ -5128,6 +5129,7 @@ struct perf_mmap_event { int maj, min; u64 ino; u64 ino_generation; u32 prot, flags; struct { struct perf_event_header header; Loading Loading @@ -5169,6 +5171,8 @@ static void perf_event_mmap_output(struct perf_event *event, mmap_event->event_id.header.size += sizeof(mmap_event->min); mmap_event->event_id.header.size += sizeof(mmap_event->ino); mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation); mmap_event->event_id.header.size += sizeof(mmap_event->prot); mmap_event->event_id.header.size += sizeof(mmap_event->flags); } perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); Loading @@ -5187,6 +5191,8 @@ static void perf_event_mmap_output(struct perf_event *event, perf_output_put(&handle, mmap_event->min); perf_output_put(&handle, mmap_event->ino); perf_output_put(&handle, mmap_event->ino_generation); perf_output_put(&handle, mmap_event->prot); perf_output_put(&handle, mmap_event->flags); } __output_copy(&handle, mmap_event->file_name, Loading @@ -5205,6 +5211,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) struct file *file = vma->vm_file; int maj = 0, min = 0; u64 ino = 0, gen = 0; u32 prot = 0, flags = 0; unsigned int size; char tmp[16]; char *buf = NULL; Loading Loading @@ -5235,6 +5242,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) gen = inode->i_generation; maj = MAJOR(dev); min = MINOR(dev); if (vma->vm_flags & VM_READ) prot |= PROT_READ; if (vma->vm_flags & VM_WRITE) prot |= PROT_WRITE; if (vma->vm_flags & VM_EXEC) prot |= PROT_EXEC; if (vma->vm_flags & VM_MAYSHARE) flags = MAP_SHARED; else flags = MAP_PRIVATE; if (vma->vm_flags & VM_DENYWRITE) flags |= MAP_DENYWRITE; if (vma->vm_flags & VM_MAYEXEC) flags |= MAP_EXECUTABLE; if (vma->vm_flags & VM_LOCKED) flags |= MAP_LOCKED; if (vma->vm_flags & VM_HUGETLB) flags |= MAP_HUGETLB; goto got_name; } else { name = (char *)arch_vma_name(vma); Loading Loading @@ -5275,6 +5304,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) mmap_event->min = min; mmap_event->ino = ino; mmap_event->ino_generation = gen; mmap_event->prot = prot; mmap_event->flags = flags; if (!(vma->vm_flags & VM_EXEC)) mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA; Loading Loading @@ -5315,6 +5346,8 @@ void perf_event_mmap(struct vm_area_struct *vma) /* .min (attr_mmap2 only) */ /* .ino (attr_mmap2 only) */ /* .ino_generation (attr_mmap2 only) */ /* .prot (attr_mmap2 only) */ /* .flags (attr_mmap2 only) */ }; perf_event_mmap_event(&mmap_event); Loading Loading @@ -6897,10 +6930,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, if (ret) return -EFAULT; /* disabled for now */ if (attr->mmap2) return -EINVAL; if (attr->__reserved_1) return -EINVAL; Loading tools/lib/traceevent/event-parse.c +113 −0 Original line number Diff line number Diff line Loading @@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg) case PRINT_BSTRING: free(arg->string.string); break; case PRINT_BITMASK: free(arg->bitmask.bitmask); break; case PRINT_DYNAMIC_ARRAY: free(arg->dynarray.index); break; Loading Loading @@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val) case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; Loading Loading @@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg) case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); break; Loading Loading @@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg, return EVENT_ERROR; } static enum event_type process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg, char **tok) { enum event_type type; char *token; if (read_expect_type(EVENT_ITEM, &token) < 0) goto out_free; arg->type = PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; if (read_expected(EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); *tok = token; return type; out_free: free_token(token); out_err: *tok = NULL; return EVENT_ERROR; } static struct pevent_function_handler * find_func_handler(struct pevent *pevent, char *func_name) { Loading Loading @@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg, free_token(token); return process_str(event, arg, tok); } if (strcmp(token, "__get_bitmask") == 0) { free_token(token); return process_bitmask(event, arg, tok); } if (strcmp(token, "__get_dynamic_array") == 0) { free_token(token); return process_dynamic_array(event, arg, tok); Loading Loading @@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg return eval_type(val, arg, 0); case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: return 0; case PRINT_FUNC: { struct trace_seq s; Loading Loading @@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format, trace_seq_printf(s, format, str); } static void print_bitmask_to_seq(struct pevent *pevent, struct trace_seq *s, const char *format, int len_arg, const void *data, int size) { int nr_bits = size * 8; int str_size = (nr_bits + 3) / 4; int len = 0; char buf[3]; char *str; int index; int i; /* * The kernel likes to put in commas every 32 bits, we * can do the same. */ str_size += (nr_bits - 1) / 32; str = malloc(str_size + 1); if (!str) { do_warning("%s: not enough memory!", __func__); return; } str[str_size] = 0; /* Start out with -2 for the two chars per byte */ for (i = str_size - 2; i >= 0; i -= 2) { /* * data points to a bit mask of size bytes. * In the kernel, this is an array of long words, thus * endianess is very important. */ if (pevent->file_bigendian) index = size - (len + 1); else index = len; snprintf(buf, 3, "%02x", *((unsigned char *)data + index)); memcpy(str + i, buf, 2); len++; if (!(len & 3) && i > 0) { i--; str[i] = ','; } } if (len_arg >= 0) trace_seq_printf(s, format, len_arg, str); else trace_seq_printf(s, format, str); free(str); } static void print_str_arg(struct trace_seq *s, void *data, int size, struct event_format *event, const char *format, int len_arg, struct print_arg *arg) Loading Loading @@ -3691,6 +3784,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, case PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; case PRINT_BITMASK: { int bitmask_offset; int bitmask_size; if (arg->bitmask.offset == -1) { struct format_field *f; f = pevent_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; } bitmask_offset = data2host4(pevent, data + arg->bitmask.offset); bitmask_size = bitmask_offset >> 16; bitmask_offset &= 0xffff; print_bitmask_to_seq(pevent, s, format, len_arg, data + bitmask_offset, bitmask_size); break; } case PRINT_OP: /* * The only op for string should be ? : Loading Loading @@ -4822,6 +4932,9 @@ static void print_args(struct print_arg *args) case PRINT_BSTRING: printf("__get_str(%s)", args->string.string); break; case PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; case PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); Loading tools/lib/traceevent/event-parse.h +22 −3 Original line number Diff line number Diff line Loading @@ -107,8 +107,8 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s, typedef int (*pevent_plugin_load_func)(struct pevent *pevent); typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); struct plugin_option { struct plugin_option *next; struct pevent_plugin_option { struct pevent_plugin_option *next; void *handle; char *file; char *name; Loading @@ -135,7 +135,7 @@ struct plugin_option { * PEVENT_PLUGIN_OPTIONS: (optional) * Plugin options that can be set before loading * * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = { * struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = { * { * .name = "option-name", * .plugin_alias = "overide-file-name", (optional) Loading Loading @@ -208,6 +208,11 @@ struct print_arg_string { int offset; }; struct print_arg_bitmask { char *bitmask; int offset; }; struct print_arg_field { char *name; struct format_field *field; Loading Loading @@ -274,6 +279,7 @@ enum print_arg_type { PRINT_DYNAMIC_ARRAY, PRINT_OP, PRINT_FUNC, PRINT_BITMASK, }; struct print_arg { Loading @@ -288,6 +294,7 @@ struct print_arg { struct print_arg_hex hex; struct print_arg_func func; struct print_arg_string string; struct print_arg_bitmask bitmask; struct print_arg_op op; struct print_arg_dynarray dynarray; }; Loading Loading @@ -354,6 +361,8 @@ enum pevent_func_arg_type { enum pevent_flag { PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */ PEVENT_DISABLE_SYS_PLUGINS = 1 << 1, PEVENT_DISABLE_PLUGINS = 1 << 2, }; #define PEVENT_ERRORS \ Loading Loading @@ -410,9 +419,19 @@ enum pevent_errno { struct plugin_list; #define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) struct plugin_list *traceevent_load_plugins(struct pevent *pevent); void traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent); char **traceevent_plugin_list_options(void); void traceevent_plugin_free_options_list(char **list); int traceevent_plugin_add_options(const char *name, struct pevent_plugin_option *options); void traceevent_plugin_remove_options(struct pevent_plugin_option *options); void traceevent_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct plugin_list *list); struct cmdline; struct cmdline_list; Loading tools/lib/traceevent/event-plugin.c +202 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include <stdio.h> #include <string.h> #include <dlfcn.h> #include <stdlib.h> Loading @@ -30,12 +31,207 @@ #define LOCAL_PLUGIN_DIR ".traceevent/plugins" static struct registered_plugin_options { struct registered_plugin_options *next; struct pevent_plugin_option *options; } *registered_options; static struct trace_plugin_options { struct trace_plugin_options *next; char *plugin; char *option; char *value; } *trace_plugin_options; struct plugin_list { struct plugin_list *next; char *name; void *handle; }; /** * traceevent_plugin_list_options - get list of plugin options * * Returns an array of char strings that list the currently registered * plugin options in the format of <plugin>:<option>. This list can be * used by toggling the option. * * Returns NULL if there's no options registered. On error it returns * INVALID_PLUGIN_LIST_OPTION * * Must be freed with traceevent_plugin_free_options_list(). */ char **traceevent_plugin_list_options(void) { struct registered_plugin_options *reg; struct pevent_plugin_option *op; char **list = NULL; char *name; int count = 0; for (reg = registered_options; reg; reg = reg->next) { for (op = reg->options; op->name; op++) { char *alias = op->plugin_alias ? op->plugin_alias : op->file; char **temp = list; name = malloc(strlen(op->name) + strlen(alias) + 2); if (!name) goto err; sprintf(name, "%s:%s", alias, op->name); list = realloc(list, count + 2); if (!list) { list = temp; free(name); goto err; } list[count++] = name; list[count] = NULL; } } return list; err: while (--count >= 0) free(list[count]); free(list); return INVALID_PLUGIN_LIST_OPTION; } void traceevent_plugin_free_options_list(char **list) { int i; if (!list) return; if (list == INVALID_PLUGIN_LIST_OPTION) return; for (i = 0; list[i]; i++) free(list[i]); free(list); } static int update_option(const char *file, struct pevent_plugin_option *option) { struct trace_plugin_options *op; char *plugin; if (option->plugin_alias) { plugin = strdup(option->plugin_alias); if (!plugin) return -1; } else { char *p; plugin = strdup(file); if (!plugin) return -1; p = strstr(plugin, "."); if (p) *p = '\0'; } /* first look for named options */ for (op = trace_plugin_options; op; op = op->next) { if (!op->plugin) continue; if (strcmp(op->plugin, plugin) != 0) continue; if (strcmp(op->option, option->name) != 0) continue; option->value = op->value; option->set ^= 1; goto out; } /* first look for unnamed options */ for (op = trace_plugin_options; op; op = op->next) { if (op->plugin) continue; if (strcmp(op->option, option->name) != 0) continue; option->value = op->value; option->set ^= 1; break; } out: free(plugin); return 0; } /** * traceevent_plugin_add_options - Add a set of options by a plugin * @name: The name of the plugin adding the options * @options: The set of options being loaded * * Sets the options with the values that have been added by user. */ int traceevent_plugin_add_options(const char *name, struct pevent_plugin_option *options) { struct registered_plugin_options *reg; reg = malloc(sizeof(*reg)); if (!reg) return -1; reg->next = registered_options; reg->options = options; registered_options = reg; while (options->name) { update_option(name, options); options++; } return 0; } /** * traceevent_plugin_remove_options - remove plugin options that were registered * @options: Options to removed that were registered with traceevent_plugin_add_options */ void traceevent_plugin_remove_options(struct pevent_plugin_option *options) { struct registered_plugin_options **last; struct registered_plugin_options *reg; for (last = ®istered_options; *last; last = &(*last)->next) { if ((*last)->options == options) { reg = *last; *last = reg->next; free(reg); return; } } } /** * traceevent_print_plugins - print out the list of plugins loaded * @s: the trace_seq descripter to write to * @prefix: The prefix string to add before listing the option name * @suffix: The suffix string ot append after the option name * @list: The list of plugins (usually returned by traceevent_load_plugins() * * Writes to the trace_seq @s the list of plugins (files) that is * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating: * @prefix = " ", @suffix = "\n". */ void traceevent_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct plugin_list *list) { while (list) { trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix); list = list->next; } } static void load_plugin(struct pevent *pevent, const char *path, const char *file, void *data) Loading Loading @@ -148,12 +344,17 @@ load_plugins(struct pevent *pevent, const char *suffix, char *path; char *envdir; if (pevent->flags & PEVENT_DISABLE_PLUGINS) return; /* * If a system plugin directory was defined, * check that first. */ #ifdef PLUGIN_DIR load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); if (!(pevent->flags & PEVENT_DISABLE_SYS_PLUGINS)) load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); #endif /* Loading Loading
include/uapi/linux/perf_event.h +1 −0 Original line number Diff line number Diff line Loading @@ -705,6 +705,7 @@ enum perf_event_type { * u32 min; * u64 ino; * u64 ino_generation; * u32 prot, flags; * char filename[]; * struct sample_id sample_id; * }; Loading
kernel/events/core.c +33 −4 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ #include <linux/mm_types.h> #include <linux/cgroup.h> #include <linux/module.h> #include <linux/mman.h> #include "internal.h" Loading Loading @@ -5128,6 +5129,7 @@ struct perf_mmap_event { int maj, min; u64 ino; u64 ino_generation; u32 prot, flags; struct { struct perf_event_header header; Loading Loading @@ -5169,6 +5171,8 @@ static void perf_event_mmap_output(struct perf_event *event, mmap_event->event_id.header.size += sizeof(mmap_event->min); mmap_event->event_id.header.size += sizeof(mmap_event->ino); mmap_event->event_id.header.size += sizeof(mmap_event->ino_generation); mmap_event->event_id.header.size += sizeof(mmap_event->prot); mmap_event->event_id.header.size += sizeof(mmap_event->flags); } perf_event_header__init_id(&mmap_event->event_id.header, &sample, event); Loading @@ -5187,6 +5191,8 @@ static void perf_event_mmap_output(struct perf_event *event, perf_output_put(&handle, mmap_event->min); perf_output_put(&handle, mmap_event->ino); perf_output_put(&handle, mmap_event->ino_generation); perf_output_put(&handle, mmap_event->prot); perf_output_put(&handle, mmap_event->flags); } __output_copy(&handle, mmap_event->file_name, Loading @@ -5205,6 +5211,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) struct file *file = vma->vm_file; int maj = 0, min = 0; u64 ino = 0, gen = 0; u32 prot = 0, flags = 0; unsigned int size; char tmp[16]; char *buf = NULL; Loading Loading @@ -5235,6 +5242,28 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) gen = inode->i_generation; maj = MAJOR(dev); min = MINOR(dev); if (vma->vm_flags & VM_READ) prot |= PROT_READ; if (vma->vm_flags & VM_WRITE) prot |= PROT_WRITE; if (vma->vm_flags & VM_EXEC) prot |= PROT_EXEC; if (vma->vm_flags & VM_MAYSHARE) flags = MAP_SHARED; else flags = MAP_PRIVATE; if (vma->vm_flags & VM_DENYWRITE) flags |= MAP_DENYWRITE; if (vma->vm_flags & VM_MAYEXEC) flags |= MAP_EXECUTABLE; if (vma->vm_flags & VM_LOCKED) flags |= MAP_LOCKED; if (vma->vm_flags & VM_HUGETLB) flags |= MAP_HUGETLB; goto got_name; } else { name = (char *)arch_vma_name(vma); Loading Loading @@ -5275,6 +5304,8 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) mmap_event->min = min; mmap_event->ino = ino; mmap_event->ino_generation = gen; mmap_event->prot = prot; mmap_event->flags = flags; if (!(vma->vm_flags & VM_EXEC)) mmap_event->event_id.header.misc |= PERF_RECORD_MISC_MMAP_DATA; Loading Loading @@ -5315,6 +5346,8 @@ void perf_event_mmap(struct vm_area_struct *vma) /* .min (attr_mmap2 only) */ /* .ino (attr_mmap2 only) */ /* .ino_generation (attr_mmap2 only) */ /* .prot (attr_mmap2 only) */ /* .flags (attr_mmap2 only) */ }; perf_event_mmap_event(&mmap_event); Loading Loading @@ -6897,10 +6930,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, if (ret) return -EFAULT; /* disabled for now */ if (attr->mmap2) return -EINVAL; if (attr->__reserved_1) return -EINVAL; Loading
tools/lib/traceevent/event-parse.c +113 −0 Original line number Diff line number Diff line Loading @@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg) case PRINT_BSTRING: free(arg->string.string); break; case PRINT_BITMASK: free(arg->bitmask.bitmask); break; case PRINT_DYNAMIC_ARRAY: free(arg->dynarray.index); break; Loading Loading @@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val) case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); ret = 0; Loading Loading @@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg) case PRINT_FIELD ... PRINT_SYMBOL: case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: default: do_warning("invalid eval type %d", arg->type); break; Loading Loading @@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg, return EVENT_ERROR; } static enum event_type process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg, char **tok) { enum event_type type; char *token; if (read_expect_type(EVENT_ITEM, &token) < 0) goto out_free; arg->type = PRINT_BITMASK; arg->bitmask.bitmask = token; arg->bitmask.offset = -1; if (read_expected(EVENT_DELIM, ")") < 0) goto out_err; type = read_token(&token); *tok = token; return type; out_free: free_token(token); out_err: *tok = NULL; return EVENT_ERROR; } static struct pevent_function_handler * find_func_handler(struct pevent *pevent, char *func_name) { Loading Loading @@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg, free_token(token); return process_str(event, arg, tok); } if (strcmp(token, "__get_bitmask") == 0) { free_token(token); return process_bitmask(event, arg, tok); } if (strcmp(token, "__get_dynamic_array") == 0) { free_token(token); return process_dynamic_array(event, arg, tok); Loading Loading @@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg return eval_type(val, arg, 0); case PRINT_STRING: case PRINT_BSTRING: case PRINT_BITMASK: return 0; case PRINT_FUNC: { struct trace_seq s; Loading Loading @@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format, trace_seq_printf(s, format, str); } static void print_bitmask_to_seq(struct pevent *pevent, struct trace_seq *s, const char *format, int len_arg, const void *data, int size) { int nr_bits = size * 8; int str_size = (nr_bits + 3) / 4; int len = 0; char buf[3]; char *str; int index; int i; /* * The kernel likes to put in commas every 32 bits, we * can do the same. */ str_size += (nr_bits - 1) / 32; str = malloc(str_size + 1); if (!str) { do_warning("%s: not enough memory!", __func__); return; } str[str_size] = 0; /* Start out with -2 for the two chars per byte */ for (i = str_size - 2; i >= 0; i -= 2) { /* * data points to a bit mask of size bytes. * In the kernel, this is an array of long words, thus * endianess is very important. */ if (pevent->file_bigendian) index = size - (len + 1); else index = len; snprintf(buf, 3, "%02x", *((unsigned char *)data + index)); memcpy(str + i, buf, 2); len++; if (!(len & 3) && i > 0) { i--; str[i] = ','; } } if (len_arg >= 0) trace_seq_printf(s, format, len_arg, str); else trace_seq_printf(s, format, str); free(str); } static void print_str_arg(struct trace_seq *s, void *data, int size, struct event_format *event, const char *format, int len_arg, struct print_arg *arg) Loading Loading @@ -3691,6 +3784,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, case PRINT_BSTRING: print_str_to_seq(s, format, len_arg, arg->string.string); break; case PRINT_BITMASK: { int bitmask_offset; int bitmask_size; if (arg->bitmask.offset == -1) { struct format_field *f; f = pevent_find_any_field(event, arg->bitmask.bitmask); arg->bitmask.offset = f->offset; } bitmask_offset = data2host4(pevent, data + arg->bitmask.offset); bitmask_size = bitmask_offset >> 16; bitmask_offset &= 0xffff; print_bitmask_to_seq(pevent, s, format, len_arg, data + bitmask_offset, bitmask_size); break; } case PRINT_OP: /* * The only op for string should be ? : Loading Loading @@ -4822,6 +4932,9 @@ static void print_args(struct print_arg *args) case PRINT_BSTRING: printf("__get_str(%s)", args->string.string); break; case PRINT_BITMASK: printf("__get_bitmask(%s)", args->bitmask.bitmask); break; case PRINT_TYPE: printf("(%s)", args->typecast.type); print_args(args->typecast.item); Loading
tools/lib/traceevent/event-parse.h +22 −3 Original line number Diff line number Diff line Loading @@ -107,8 +107,8 @@ typedef int (*pevent_event_handler_func)(struct trace_seq *s, typedef int (*pevent_plugin_load_func)(struct pevent *pevent); typedef int (*pevent_plugin_unload_func)(struct pevent *pevent); struct plugin_option { struct plugin_option *next; struct pevent_plugin_option { struct pevent_plugin_option *next; void *handle; char *file; char *name; Loading @@ -135,7 +135,7 @@ struct plugin_option { * PEVENT_PLUGIN_OPTIONS: (optional) * Plugin options that can be set before loading * * struct plugin_option PEVENT_PLUGIN_OPTIONS[] = { * struct pevent_plugin_option PEVENT_PLUGIN_OPTIONS[] = { * { * .name = "option-name", * .plugin_alias = "overide-file-name", (optional) Loading Loading @@ -208,6 +208,11 @@ struct print_arg_string { int offset; }; struct print_arg_bitmask { char *bitmask; int offset; }; struct print_arg_field { char *name; struct format_field *field; Loading Loading @@ -274,6 +279,7 @@ enum print_arg_type { PRINT_DYNAMIC_ARRAY, PRINT_OP, PRINT_FUNC, PRINT_BITMASK, }; struct print_arg { Loading @@ -288,6 +294,7 @@ struct print_arg { struct print_arg_hex hex; struct print_arg_func func; struct print_arg_string string; struct print_arg_bitmask bitmask; struct print_arg_op op; struct print_arg_dynarray dynarray; }; Loading Loading @@ -354,6 +361,8 @@ enum pevent_func_arg_type { enum pevent_flag { PEVENT_NSEC_OUTPUT = 1, /* output in NSECS */ PEVENT_DISABLE_SYS_PLUGINS = 1 << 1, PEVENT_DISABLE_PLUGINS = 1 << 2, }; #define PEVENT_ERRORS \ Loading Loading @@ -410,9 +419,19 @@ enum pevent_errno { struct plugin_list; #define INVALID_PLUGIN_LIST_OPTION ((char **)((unsigned long)-1)) struct plugin_list *traceevent_load_plugins(struct pevent *pevent); void traceevent_unload_plugins(struct plugin_list *plugin_list, struct pevent *pevent); char **traceevent_plugin_list_options(void); void traceevent_plugin_free_options_list(char **list); int traceevent_plugin_add_options(const char *name, struct pevent_plugin_option *options); void traceevent_plugin_remove_options(struct pevent_plugin_option *options); void traceevent_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct plugin_list *list); struct cmdline; struct cmdline_list; Loading
tools/lib/traceevent/event-plugin.c +202 −1 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #include <stdio.h> #include <string.h> #include <dlfcn.h> #include <stdlib.h> Loading @@ -30,12 +31,207 @@ #define LOCAL_PLUGIN_DIR ".traceevent/plugins" static struct registered_plugin_options { struct registered_plugin_options *next; struct pevent_plugin_option *options; } *registered_options; static struct trace_plugin_options { struct trace_plugin_options *next; char *plugin; char *option; char *value; } *trace_plugin_options; struct plugin_list { struct plugin_list *next; char *name; void *handle; }; /** * traceevent_plugin_list_options - get list of plugin options * * Returns an array of char strings that list the currently registered * plugin options in the format of <plugin>:<option>. This list can be * used by toggling the option. * * Returns NULL if there's no options registered. On error it returns * INVALID_PLUGIN_LIST_OPTION * * Must be freed with traceevent_plugin_free_options_list(). */ char **traceevent_plugin_list_options(void) { struct registered_plugin_options *reg; struct pevent_plugin_option *op; char **list = NULL; char *name; int count = 0; for (reg = registered_options; reg; reg = reg->next) { for (op = reg->options; op->name; op++) { char *alias = op->plugin_alias ? op->plugin_alias : op->file; char **temp = list; name = malloc(strlen(op->name) + strlen(alias) + 2); if (!name) goto err; sprintf(name, "%s:%s", alias, op->name); list = realloc(list, count + 2); if (!list) { list = temp; free(name); goto err; } list[count++] = name; list[count] = NULL; } } return list; err: while (--count >= 0) free(list[count]); free(list); return INVALID_PLUGIN_LIST_OPTION; } void traceevent_plugin_free_options_list(char **list) { int i; if (!list) return; if (list == INVALID_PLUGIN_LIST_OPTION) return; for (i = 0; list[i]; i++) free(list[i]); free(list); } static int update_option(const char *file, struct pevent_plugin_option *option) { struct trace_plugin_options *op; char *plugin; if (option->plugin_alias) { plugin = strdup(option->plugin_alias); if (!plugin) return -1; } else { char *p; plugin = strdup(file); if (!plugin) return -1; p = strstr(plugin, "."); if (p) *p = '\0'; } /* first look for named options */ for (op = trace_plugin_options; op; op = op->next) { if (!op->plugin) continue; if (strcmp(op->plugin, plugin) != 0) continue; if (strcmp(op->option, option->name) != 0) continue; option->value = op->value; option->set ^= 1; goto out; } /* first look for unnamed options */ for (op = trace_plugin_options; op; op = op->next) { if (op->plugin) continue; if (strcmp(op->option, option->name) != 0) continue; option->value = op->value; option->set ^= 1; break; } out: free(plugin); return 0; } /** * traceevent_plugin_add_options - Add a set of options by a plugin * @name: The name of the plugin adding the options * @options: The set of options being loaded * * Sets the options with the values that have been added by user. */ int traceevent_plugin_add_options(const char *name, struct pevent_plugin_option *options) { struct registered_plugin_options *reg; reg = malloc(sizeof(*reg)); if (!reg) return -1; reg->next = registered_options; reg->options = options; registered_options = reg; while (options->name) { update_option(name, options); options++; } return 0; } /** * traceevent_plugin_remove_options - remove plugin options that were registered * @options: Options to removed that were registered with traceevent_plugin_add_options */ void traceevent_plugin_remove_options(struct pevent_plugin_option *options) { struct registered_plugin_options **last; struct registered_plugin_options *reg; for (last = ®istered_options; *last; last = &(*last)->next) { if ((*last)->options == options) { reg = *last; *last = reg->next; free(reg); return; } } } /** * traceevent_print_plugins - print out the list of plugins loaded * @s: the trace_seq descripter to write to * @prefix: The prefix string to add before listing the option name * @suffix: The suffix string ot append after the option name * @list: The list of plugins (usually returned by traceevent_load_plugins() * * Writes to the trace_seq @s the list of plugins (files) that is * returned by traceevent_load_plugins(). Use @prefix and @suffix for formating: * @prefix = " ", @suffix = "\n". */ void traceevent_print_plugins(struct trace_seq *s, const char *prefix, const char *suffix, const struct plugin_list *list) { while (list) { trace_seq_printf(s, "%s%s%s", prefix, list->name, suffix); list = list->next; } } static void load_plugin(struct pevent *pevent, const char *path, const char *file, void *data) Loading Loading @@ -148,12 +344,17 @@ load_plugins(struct pevent *pevent, const char *suffix, char *path; char *envdir; if (pevent->flags & PEVENT_DISABLE_PLUGINS) return; /* * If a system plugin directory was defined, * check that first. */ #ifdef PLUGIN_DIR load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); if (!(pevent->flags & PEVENT_DISABLE_SYS_PLUGINS)) load_plugins_dir(pevent, suffix, PLUGIN_DIR, load_plugin, data); #endif /* Loading