diff options
Diffstat (limited to 'tools/lib/traceevent/event-parse.c')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 244 |
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 | |||
2754 | err: | ||
2755 | free_arg(farg); | ||
2756 | free_token(token); | ||
2757 | return EVENT_ERROR; | ||
2750 | } | 2758 | } |
2751 | 2759 | ||
2752 | static enum event_type | 2760 | static 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 | ||
5132 | static 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 | |||
5155 | event_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 | */ |
5132 | enum pevent_errno pevent_parse_format(struct event_format **eventp, const char *buf, | 5175 | enum 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 | |||
5172 | event_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 | */ | ||
5573 | int 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 | |||
5586 | static 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 | ||
5675 | static 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 | */ | ||
5710 | int 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 | |||
5731 | not_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 | */ |