diff options
Diffstat (limited to 'tools')
37 files changed, 1208 insertions, 119 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index b83184f2d484..93825a17dcce 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
| @@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg) | |||
| 765 | case PRINT_BSTRING: | 765 | case PRINT_BSTRING: |
| 766 | free(arg->string.string); | 766 | free(arg->string.string); |
| 767 | break; | 767 | break; |
| 768 | case PRINT_BITMASK: | ||
| 769 | free(arg->bitmask.bitmask); | ||
| 770 | break; | ||
| 768 | case PRINT_DYNAMIC_ARRAY: | 771 | case PRINT_DYNAMIC_ARRAY: |
| 769 | free(arg->dynarray.index); | 772 | free(arg->dynarray.index); |
| 770 | break; | 773 | break; |
| @@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val) | |||
| 2268 | case PRINT_FIELD ... PRINT_SYMBOL: | 2271 | case PRINT_FIELD ... PRINT_SYMBOL: |
| 2269 | case PRINT_STRING: | 2272 | case PRINT_STRING: |
| 2270 | case PRINT_BSTRING: | 2273 | case PRINT_BSTRING: |
| 2274 | case PRINT_BITMASK: | ||
| 2271 | default: | 2275 | default: |
| 2272 | do_warning("invalid eval type %d", arg->type); | 2276 | do_warning("invalid eval type %d", arg->type); |
| 2273 | ret = 0; | 2277 | ret = 0; |
| @@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg) | |||
| 2296 | case PRINT_FIELD ... PRINT_SYMBOL: | 2300 | case PRINT_FIELD ... PRINT_SYMBOL: |
| 2297 | case PRINT_STRING: | 2301 | case PRINT_STRING: |
| 2298 | case PRINT_BSTRING: | 2302 | case PRINT_BSTRING: |
| 2303 | case PRINT_BITMASK: | ||
| 2299 | default: | 2304 | default: |
| 2300 | do_warning("invalid eval type %d", arg->type); | 2305 | do_warning("invalid eval type %d", arg->type); |
| 2301 | break; | 2306 | break; |
| @@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg, | |||
| 2683 | return EVENT_ERROR; | 2688 | return EVENT_ERROR; |
| 2684 | } | 2689 | } |
| 2685 | 2690 | ||
| 2691 | static enum event_type | ||
| 2692 | process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg, | ||
| 2693 | char **tok) | ||
| 2694 | { | ||
| 2695 | enum event_type type; | ||
| 2696 | char *token; | ||
| 2697 | |||
| 2698 | if (read_expect_type(EVENT_ITEM, &token) < 0) | ||
| 2699 | goto out_free; | ||
| 2700 | |||
| 2701 | arg->type = PRINT_BITMASK; | ||
| 2702 | arg->bitmask.bitmask = token; | ||
| 2703 | arg->bitmask.offset = -1; | ||
| 2704 | |||
| 2705 | if (read_expected(EVENT_DELIM, ")") < 0) | ||
| 2706 | goto out_err; | ||
| 2707 | |||
| 2708 | type = read_token(&token); | ||
| 2709 | *tok = token; | ||
| 2710 | |||
| 2711 | return type; | ||
| 2712 | |||
| 2713 | out_free: | ||
| 2714 | free_token(token); | ||
| 2715 | out_err: | ||
| 2716 | *tok = NULL; | ||
| 2717 | return EVENT_ERROR; | ||
| 2718 | } | ||
| 2719 | |||
| 2686 | static struct pevent_function_handler * | 2720 | static struct pevent_function_handler * |
| 2687 | find_func_handler(struct pevent *pevent, char *func_name) | 2721 | find_func_handler(struct pevent *pevent, char *func_name) |
| 2688 | { | 2722 | { |
| @@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg, | |||
| 2797 | free_token(token); | 2831 | free_token(token); |
| 2798 | return process_str(event, arg, tok); | 2832 | return process_str(event, arg, tok); |
| 2799 | } | 2833 | } |
| 2834 | if (strcmp(token, "__get_bitmask") == 0) { | ||
| 2835 | free_token(token); | ||
| 2836 | return process_bitmask(event, arg, tok); | ||
| 2837 | } | ||
| 2800 | if (strcmp(token, "__get_dynamic_array") == 0) { | 2838 | if (strcmp(token, "__get_dynamic_array") == 0) { |
| 2801 | free_token(token); | 2839 | free_token(token); |
| 2802 | return process_dynamic_array(event, arg, tok); | 2840 | return process_dynamic_array(event, arg, tok); |
| @@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg | |||
| 3324 | return eval_type(val, arg, 0); | 3362 | return eval_type(val, arg, 0); |
| 3325 | case PRINT_STRING: | 3363 | case PRINT_STRING: |
| 3326 | case PRINT_BSTRING: | 3364 | case PRINT_BSTRING: |
| 3365 | case PRINT_BITMASK: | ||
| 3327 | return 0; | 3366 | return 0; |
| 3328 | case PRINT_FUNC: { | 3367 | case PRINT_FUNC: { |
| 3329 | struct trace_seq s; | 3368 | struct trace_seq s; |
| @@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format, | |||
| 3556 | trace_seq_printf(s, format, str); | 3595 | trace_seq_printf(s, format, str); |
| 3557 | } | 3596 | } |
| 3558 | 3597 | ||
| 3598 | static void print_bitmask_to_seq(struct pevent *pevent, | ||
| 3599 | struct trace_seq *s, const char *format, | ||
| 3600 | int len_arg, const void *data, int size) | ||
| 3601 | { | ||
| 3602 | int nr_bits = size * 8; | ||
| 3603 | int str_size = (nr_bits + 3) / 4; | ||
| 3604 | int len = 0; | ||
| 3605 | char buf[3]; | ||
| 3606 | char *str; | ||
| 3607 | int index; | ||
| 3608 | int i; | ||
| 3609 | |||
| 3610 | /* | ||
| 3611 | * The kernel likes to put in commas every 32 bits, we | ||
| 3612 | * can do the same. | ||
| 3613 | */ | ||
| 3614 | str_size += (nr_bits - 1) / 32; | ||
| 3615 | |||
| 3616 | str = malloc(str_size + 1); | ||
| 3617 | if (!str) { | ||
| 3618 | do_warning("%s: not enough memory!", __func__); | ||
| 3619 | return; | ||
| 3620 | } | ||
| 3621 | str[str_size] = 0; | ||
| 3622 | |||
| 3623 | /* Start out with -2 for the two chars per byte */ | ||
| 3624 | for (i = str_size - 2; i >= 0; i -= 2) { | ||
| 3625 | /* | ||
| 3626 | * data points to a bit mask of size bytes. | ||
| 3627 | * In the kernel, this is an array of long words, thus | ||
| 3628 | * endianess is very important. | ||
| 3629 | */ | ||
| 3630 | if (pevent->file_bigendian) | ||
| 3631 | index = size - (len + 1); | ||
| 3632 | else | ||
