aboutsummaryrefslogtreecommitdiffstats
path: root/tools/lib/traceevent/event-parse.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/traceevent/event-parse.c')
-rw-r--r--tools/lib/traceevent/event-parse.c244
1 files changed, 182 insertions, 62 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index 217c82ee3665..1587ea392ad6 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -2710,7 +2710,6 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
2710 struct print_arg *farg; 2710 struct print_arg *farg;
2711 enum event_type type; 2711 enum event_type type;
2712 char *token; 2712 char *token;
2713 const char *test;
2714 int i; 2713 int i;
2715 2714
2716 arg->type = PRINT_FUNC; 2715 arg->type = PRINT_FUNC;
@@ -2727,15 +2726,19 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
2727 } 2726 }
2728 2727
2729 type = process_arg(event, farg, &token); 2728 type = process_arg(event, farg, &token);
2730 if (i < (func->nr_args - 1)) 2729 if (i < (func->nr_args - 1)) {
2731 test = ","; 2730 if (type != EVENT_DELIM || strcmp(token, ",") != 0) {
2732 else 2731 warning("Error: function '%s()' expects %d arguments but event %s only uses %d",
2733 test = ")"; 2732 func->name, func->nr_args,
2734 2733 event->name, i + 1);
2735 if (test_type_token(type, token, EVENT_DELIM, test)) { 2734 goto err;
2736 free_arg(farg); 2735 }
2737 free_token(token); 2736 } else {
2738 return EVENT_ERROR; 2737 if (type != EVENT_DELIM || strcmp(token, ")") != 0) {
2738 warning("Error: function '%s()' only expects %d arguments but event %s has more",
2739 func->name, func->nr_args, event->name);
2740 goto err;
2741 }
2739 } 2742 }
2740 2743
2741 *next_arg = farg; 2744 *next_arg = farg;
@@ -2747,6 +2750,11 @@ process_func_handler(struct event_format *event, struct pevent_function_handler
2747 *tok = token; 2750 *tok = token;
2748 2751
2749 return type; 2752 return type;
2753
2754err:
2755 free_arg(farg);
2756 free_token(token);
2757 return EVENT_ERROR;
2750} 2758}
2751 2759
2752static enum event_type 2760static enum event_type
@@ -4099,6 +4107,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4099 unsigned long long val; 4107 unsigned long long val;
4100 struct func_map *func; 4108 struct func_map *func;
4101 const char *saveptr; 4109 const char *saveptr;
4110 struct trace_seq p;
4102 char *bprint_fmt = NULL; 4111 char *bprint_fmt = NULL;
4103 char format[32]; 4112 char format[32];
4104 int show_func; 4113 int show_func;
@@ -4306,8 +4315,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
4306 format[len] = 0; 4315 format[len] = 0;
4307 if (!len_as_arg) 4316 if (!len_as_arg)
4308 len_arg = -1; 4317 len_arg = -1;
4309 print_str_arg(s, data, size, event, 4318 /* Use helper trace_seq */
4319 trace_seq_init(&p);
4320 print_str_arg(&p, data, size, event,
4310 format, len_arg, arg); 4321 format, len_arg, arg);
4322 trace_seq_terminate(&p);
4323 trace_seq_puts(s, p.buffer);
4311 arg = arg->next; 4324 arg = arg->next;
4312 break; 4325 break;
4313 default: 4326 default:
@@ -5116,8 +5129,38 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5116 return ret; 5129 return ret;
5117} 5130}
5118 5131
5132static enum pevent_errno
5133__pevent_parse_event(struct pevent *pevent,
5134 struct event_format **eventp,
5135 const char *buf, unsigned long size,
5136 const char *sys)
5137{
5138 int ret = __pevent_parse_format(eventp, pevent, buf, size, sys);
5139 struct event_format *event = *eventp;
5140
5141 if (event == NULL)
5142 return ret;
5143
5144 if (pevent && add_event(pevent, event)) {
5145 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5146 goto event_add_failed;
5147 }
5148
5149#define PRINT_ARGS 0
5150 if (PRINT_ARGS && event->print_fmt.args)
5151 print_args(event->print_fmt.args);
5152
5153 return 0;
5154
5155event_add_failed:
5156 pevent_free_format(event);
5157 return ret;
5158}
5159
5119/** 5160/**
5120 * pevent_parse_format - parse the event format 5161 * pevent_parse_format - parse the event format
5162 * @pevent: the handle to the pevent
5163 * @eventp: returned format
5121 * @buf: the buffer storing the event format string 5164 * @buf: the buffer storing the event format string
5122 * @size: the size of @buf 5165 * @size: the size of @buf
5123 * @sys: the system the event belongs to 5166 * @sys: the system the event belongs to
@@ -5129,10 +5172,12 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
5129 * 5172 *
5130 * /sys/kernel/debug/tracing/events/.../.../format 5173 * /sys/kernel/debug/tracing/events/.../.../format
5131 */ 5174 */
5132enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, 5175enum pevent_errno pevent_parse_format(struct pevent *pevent,
5176 struct event_format **eventp,
5177 const char *buf,
5133 unsigned long size, const char *sys) 5178 unsigned long size, const char *sys)
5134{ 5179{
5135 return __pevent_parse_format(eventp, NULL, buf, size, sys); 5180 return __pevent_parse_event(pevent, eventp, buf, size, sys);
5136} 5181}
5137 5182
5138/** 5183/**
@@ -5153,25 +5198,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
5153 unsigned long size, const char *sys) 5198 unsigned long size, const char *sys)
5154{ 5199{
5155 struct event_format *event = NULL; 5200 struct event_format *event = NULL;
5156 int ret = __pevent_parse_format(&event, pevent, buf, size, sys); 5201 return __pevent_parse_event(pevent, &event, buf, size, sys);
5157
5158 if (event == NULL)
5159 return ret;
5160
5161 if (add_event(pevent, event)) {
5162 ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
5163 goto event_add_failed;
5164 }
5165
5166#define PRINT_ARGS 0
5167 if (PRINT_ARGS && event->print_fmt.args)
5168 print_args(event->print_fmt.args);
5169
5170 return 0;
5171
5172event_add_failed:
5173 pevent_free_format(event);
5174 return ret;
5175} 5202}
5176 5203
5177#undef _PE 5204#undef _PE
@@ -5203,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
5203 5230
5204 idx = errnum - __PEVENT_ERRNO__START - 1; 5231 idx = errnum - __PEVENT_ERRNO__START - 1;
5205 msg = pevent_error_str[idx]; 5232 msg = pevent_error_str[idx];
5206 5233 snprintf(buf, buflen, "%s", msg);
5207 switch (errnum) {
5208 case PEVENT_ERRNO__MEM_ALLOC_FAILED:
5209 case PEVENT_ERRNO__PARSE_EVENT_FAILED:
5210 case PEVENT_ERRNO__READ_ID_FAILED:
5211 case PEVENT_ERRNO__READ_FORMAT_FAILED:
5212 case PEVENT_ERRNO__READ_PRINT_FAILED:
5213 case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
5214 case PEVENT_ERRNO__INVALID_ARG_TYPE:
5215 snprintf(buf, buflen, "%s", msg);
5216 break;
5217
5218 default:
5219 /* cannot reach here */
5220 break;
5221 }
5222 5234
5223 return 0; 5235 return 0;
5224} 5236}
@@ -5549,6 +5561,52 @@ int pevent_register_print_function(struct pevent *pevent,
5549} 5561}
5550 5562
5551/** 5563/**
5564 * pevent_unregister_print_function - unregister a helper function
5565 * @pevent: the handle to the pevent
5566 * @func: the function to process the helper function
5567 * @name: the name of the helper function
5568 *
5569 * This function removes existing print handler for function @name.
5570 *
5571 * Returns 0 if the handler was removed successully, -1 otherwise.
5572 */
5573int pevent_unregister_print_function(struct pevent *pevent,
5574 pevent_func_handler func, char *name)
5575{
5576 struct pevent_function_handler *func_handle;
5577
5578 func_handle = find_func_handler(pevent, name);
5579 if (func_handle && func_handle->func == func) {
5580 remove_func_handler(pevent, name);
5581 return 0;
5582 }
5583 return -1;
5584}
5585
5586static struct event_format *pevent_search_event(struct pevent *pevent, int id,
5587 const char *sys_name,
5588 const char *event_name)
5589{
5590 struct event_format *event;
5591
5592 if (id >= 0) {
5593 /* search by id */
5594 event = pevent_find_event(pevent, id);
5595 if (!event)
5596 return NULL;
5597 if (event_name && (strcmp(event_name, event->name) != 0))
5598 return NULL;
5599 if (sys_name && (strcmp(sys_name, event->system) != 0))
5600 return NULL;
5601 } else {
5602 event = pevent_find_event_by_name(pevent, sys_name, event_name);
5603 if (!event)
5604 return NULL;
5605 }
5606 return event;
5607}
5608
5609/**
5552 * pevent_register_event_handler - register a way to parse an event 5610 * pevent_register_event_handler - register a way to parse an event
5553 * @pevent: the handle to the pevent 5611 * @pevent: the handle to the pevent
5554 * @id: the id of the event to register 5612 * @id: the id of the event to register
@@ -5572,20 +5630,9 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
5572 struct event_format *event; 5630 struct event_format *event;
5573 struct event_handler *handle; 5631 struct event_handler *handle;
5574 5632
5575 if (id >= 0) { 5633 event = pevent_search_event(pevent, id, sys_name, event_name);
5576 /* search by id */ 5634 if (event == NULL)
5577 event = pevent_find_event(pevent, id); 5635 goto not_found;
5578 if (!event)
5579 goto not_found;
5580 if (event_name && (strcmp(event_name, event->name) != 0))
5581 goto not_found;
5582 if (sys_name && (strcmp(sys_name, event->system) != 0))
5583 goto not_found;
5584 } else {
5585 event = pevent_find_event_by_name(pevent, sys_name, event_name);
5586 if (!event)
5587 goto not_found;
5588 }
5589 5636
5590 pr_stat("overriding event (%d) %s:%s with new print handler", 5637 pr_stat("overriding event (%d) %s:%s with new print handler",
5591 event->id, event->system, event->name); 5638 event->id, event->system, event->name);
@@ -5625,6 +5672,79 @@ int pevent_register_event_handler(struct pevent *pevent, int id,
5625 return -1; 5672 return -1;
5626} 5673}
5627 5674
5675static int handle_matches(struct event_handler *handler, int id,
5676 const char *sys_name, const char *event_name,
5677 pevent_event_handler_func func, void *context)
5678{
5679 if (id >= 0 && id != handler->id)
5680 return 0;
5681
5682 if (event_name && (strcmp(event_name, handler->event_name) != 0))
5683 return 0;
5684
5685 if (sys_name && (strcmp(sys_name, handler->sys_name) != 0))
5686 return 0;
5687
5688 if (func != handler->func || context != handler->context)
5689 return 0;
5690
5691 return 1;
5692}
5693
5694/**
5695 * pevent_unregister_event_handler - unregister an existing event handler
5696 * @pevent: the handle to the pevent
5697 * @id: the id of the event to unregister
5698 * @sys_name: the system name the handler belongs to
5699 * @event_name: the name of the event handler
5700 * @func: the function to call to parse the event information
5701 * @context: the data to be passed to @func
5702 *
5703 * This function removes existing event handler (parser).
5704 *
5705 * If @id is >= 0, then it is used to find the event.
5706 * else @sys_name and @event_name are used.
5707 *
5708 * Returns 0 if handler was removed successfully, -1 if event was not found.
5709 */
5710int pevent_unregister_event_handler(struct pevent *pevent, int id,
5711 const char *sys_name, const char *event_name,
5712 pevent_event_handler_func func, void *context)
5713{
5714 struct event_format *event;
5715 struct event_handler *handle;
5716 struct event_handler **next;
5717
5718 event = pevent_search_event(pevent, id, sys_name, event_name);
5719 if (event == NULL)
5720 goto not_found;
5721
5722 if (event->handler == func && event->context == context) {
5723 pr_stat("removing override handler for event (%d) %s:%s. Going back to default handler.",
5724 event->id, event->system, event->name);
5725
5726 event->handler = NULL;
5727 event->context = NULL;
5728 return 0;
5729 }
5730
5731not_found:
5732 for (next = &pevent->handlers; *next; next = &(*next)->next) {
5733 handle = *next;
5734 if (handle_matches(handle, id, sys_name, event_name,
5735 func, context))
5736 break;
5737 }
5738
5739 if (!(*next))
5740 return -1;
5741
5742 *next = handle->next;
5743 free_handler(handle);
5744
5745 return 0;
5746}
5747
5628/** 5748/**
5629 * pevent_alloc - create a pevent handle 5749 * pevent_alloc - create a pevent handle
5630 */ 5750 */