diff options
author | Steven Rostedt <srostedt@redhat.com> | 2010-06-17 16:07:49 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2010-06-17 16:07:49 -0400 |
commit | 315ff6f8c9e9e899d655d75d5f5203c8b0047b0b (patch) | |
tree | 47158ca633c750382ad56eb69f1aba43783f5de4 | |
parent | 11b828a7f5759ee6de214a102ee97d7b712bb47e (diff) |
parse-events: Handle '*' in TP_printk format
When the "*" (next arg is length) is used in the TP_printk format,
it is currently not handled. This will cause a shift in the arguments
that are passed in causing all arguments after to be corrupted.
Reported-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | parse-events.c | 66 |
1 files changed, 53 insertions, 13 deletions
diff --git a/parse-events.c b/parse-events.c index 13c41aa..c0118aa 100644 --- a/parse-events.c +++ b/parse-events.c | |||
@@ -3042,12 +3042,14 @@ static unsigned long long eval_flag(const char *flag) | |||
3042 | } | 3042 | } |
3043 | 3043 | ||
3044 | static void print_str_arg(struct trace_seq *s, void *data, int size, | 3044 | static void print_str_arg(struct trace_seq *s, void *data, int size, |
3045 | struct event_format *event, struct print_arg *arg) | 3045 | struct event_format *event, |
3046 | int len_arg, struct print_arg *arg) | ||
3046 | { | 3047 | { |
3047 | struct pevent *pevent = event->pevent; | 3048 | struct pevent *pevent = event->pevent; |
3048 | struct print_flag_sym *flag; | 3049 | struct print_flag_sym *flag; |
3049 | unsigned long long val, fval; | 3050 | unsigned long long val, fval; |
3050 | unsigned long addr; | 3051 | unsigned long addr; |
3052 | int len_as_arg = len_arg >= 0; | ||
3051 | char *str; | 3053 | char *str; |
3052 | int print; | 3054 | int print; |
3053 | int len; | 3055 | int len; |
@@ -3082,7 +3084,10 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3082 | str = malloc_or_die(len + 1); | 3084 | str = malloc_or_die(len + 1); |
3083 | memcpy(str, data + arg->field.field->offset, len); | 3085 | memcpy(str, data + arg->field.field->offset, len); |
3084 | str[len] = 0; | 3086 | str[len] = 0; |
3085 | trace_seq_puts(s, str); | 3087 | if (len_as_arg) |
3088 | trace_seq_printf(s, "%.*s", len_arg, str); | ||
3089 | else | ||
3090 | trace_seq_puts(s, str); | ||
3086 | free(str); | 3091 | free(str); |
3087 | break; | 3092 | break; |
3088 | case PRINT_FLAGS: | 3093 | case PRINT_FLAGS: |
@@ -3091,13 +3096,19 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3091 | for (flag = arg->flags.flags; flag; flag = flag->next) { | 3096 | for (flag = arg->flags.flags; flag; flag = flag->next) { |
3092 | fval = eval_flag(flag->value); | 3097 | fval = eval_flag(flag->value); |
3093 | if (!val && !fval) { | 3098 | if (!val && !fval) { |
3094 | trace_seq_puts(s, flag->str); | 3099 | if (len_as_arg) |
3100 | trace_seq_printf(s, "%.*s", len_arg, flag->str); | ||
3101 | else | ||
3102 | trace_seq_puts(s, flag->str); | ||
3095 | break; | 3103 | break; |
3096 | } | 3104 | } |
3097 | if (fval && (val & fval) == fval) { | 3105 | if (fval && (val & fval) == fval) { |
3098 | if (print && arg->flags.delim) | 3106 | if (print && arg->flags.delim) |
3099 | trace_seq_puts(s, arg->flags.delim); | 3107 | trace_seq_puts(s, arg->flags.delim); |
3100 | trace_seq_puts(s, flag->str); | 3108 | if (len_as_arg) |
3109 | trace_seq_printf(s, "%.*s", len_arg, flag->str); | ||
3110 | else | ||
3111 | trace_seq_puts(s, flag->str); | ||
3101 | print = 1; | 3112 | print = 1; |
3102 | val &= ~fval; | 3113 | val &= ~fval; |
3103 | } | 3114 | } |
@@ -3108,7 +3119,10 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3108 | for (flag = arg->symbol.symbols; flag; flag = flag->next) { | 3119 | for (flag = arg->symbol.symbols; flag; flag = flag->next) { |
3109 | fval = eval_flag(flag->value); | 3120 | fval = eval_flag(flag->value); |
3110 | if (val == fval) { | 3121 | if (val == fval) { |
3111 | trace_seq_puts(s, flag->str); | 3122 | if (len_as_arg) |
3123 | trace_seq_printf(s, "%.*s", len_arg, flag->str); | ||
3124 | else | ||
3125 | trace_seq_puts(s, flag->str); | ||
3112 | break; | 3126 | break; |
3113 | } | 3127 | } |
3114 | } | 3128 | } |
@@ -3127,7 +3141,10 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3127 | } | 3141 | } |
3128 | str_offset = data2host4(pevent, data + arg->string.offset); | 3142 | str_offset = data2host4(pevent, data + arg->string.offset); |
3129 | str_offset &= 0xffff; | 3143 | str_offset &= 0xffff; |
3130 | trace_seq_puts(s, ((char *)data) + str_offset); | 3144 | if (len_as_arg) |
3145 | trace_seq_printf(s, "%.*s", len_arg, ((char *)data) + str_offset); | ||
3146 | else | ||
3147 | trace_seq_puts(s, ((char *)data) + str_offset); | ||
3131 | break; | 3148 | break; |
3132 | } | 3149 | } |
3133 | case PRINT_OP: | 3150 | case PRINT_OP: |
@@ -3138,9 +3155,9 @@ static void print_str_arg(struct trace_seq *s, void *data, int size, | |||
3138 | return; | 3155 | return; |
3139 | val = eval_num_arg(data, size, event, arg->op.left); | 3156 | val = eval_num_arg(data, size, event, arg->op.left); |
3140 | if (val) | 3157 | if (val) |
3141 | print_str_arg(s, data, size, event, arg->op.right->op.left); | 3158 | print_str_arg(s, data, size, event, len_arg, arg->op.right->op.left); |
3142 | else | 3159 | else |
3143 | print_str_arg(s, data, size, event, arg->op.right->op.right); | 3160 | print_str_arg(s, data, size, event, len_arg, arg->op.right->op.right); |
3144 | break; | 3161 | break; |
3145 | case PRINT_FUNC: | 3162 | case PRINT_FUNC: |
3146 | process_defined_func(s, data, size, event, arg); | 3163 | process_defined_func(s, data, size, event, arg); |
@@ -3185,7 +3202,7 @@ process_defined_func(struct trace_seq *s, void *data, int size, | |||
3185 | break; | 3202 | break; |
3186 | case PEVENT_FUNC_ARG_STRING: | 3203 | case PEVENT_FUNC_ARG_STRING: |
3187 | trace_seq_init(&str); | 3204 | trace_seq_init(&str); |
3188 | print_str_arg(&str, data, size, event, farg); | 3205 | print_str_arg(&str, data, size, event, -1, farg); |
3189 | trace_seq_terminate(&str); | 3206 | trace_seq_terminate(&str); |
3190 | string = malloc_or_die(sizeof(*string)); | 3207 | string = malloc_or_die(sizeof(*string)); |
3191 | string->next = strings; | 3208 | string->next = strings; |
@@ -3494,6 +3511,8 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3494 | char *bprint_fmt = NULL; | 3511 | char *bprint_fmt = NULL; |
3495 | char format[32]; | 3512 | char format[32]; |
3496 | int show_func; | 3513 | int show_func; |
3514 | int len_as_arg; | ||
3515 | int len_arg; | ||
3497 | int len; | 3516 | int len; |
3498 | int ls; | 3517 | int ls; |
3499 | 3518 | ||
@@ -3535,6 +3554,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3535 | } else if (*ptr == '%') { | 3554 | } else if (*ptr == '%') { |
3536 | saveptr = ptr; | 3555 | saveptr = ptr; |
3537 | show_func = 0; | 3556 | show_func = 0; |
3557 | len_as_arg = 0; | ||
3538 | cont_process: | 3558 | cont_process: |
3539 | ptr++; | 3559 | ptr++; |
3540 | switch (*ptr) { | 3560 | switch (*ptr) { |
@@ -3550,6 +3570,14 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3550 | case 'L': | 3570 | case 'L': |
3551 | ls = 2; | 3571 | ls = 2; |
3552 | goto cont_process; | 3572 | goto cont_process; |
3573 | case '*': | ||
3574 | /* The argument is the length. */ | ||
3575 | if (!arg) | ||
3576 | die("no argument match"); | ||
3577 | len_arg = eval_num_arg(data, size, event, arg); | ||
3578 | len_as_arg = 1; | ||
3579 | arg = arg->next; | ||
3580 | goto cont_process; | ||
3553 | case '.': | 3581 | case '.': |
3554 | case 'z': | 3582 | case 'z': |
3555 | case 'Z': | 3583 | case 'Z': |
@@ -3617,13 +3645,23 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3617 | } | 3645 | } |
3618 | switch (ls) { | 3646 | switch (ls) { |
3619 | case 0: | 3647 | case 0: |
3620 | trace_seq_printf(s, format, (int)val); | 3648 | if (len_as_arg) |
3649 | trace_seq_printf(s, format, len_arg, (int)val); | ||
3650 | else | ||
3651 | trace_seq_printf(s, format, (int)val); | ||
3621 | break; | 3652 | break; |
3622 | case 1: | 3653 | case 1: |
3623 | trace_seq_printf(s, format, (long)val); | 3654 | if (len_as_arg) |
3655 | trace_seq_printf(s, format, len_arg, (long)val); | ||
3656 | else | ||
3657 | trace_seq_printf(s, format, (long)val); | ||
3624 | break; | 3658 | break; |
3625 | case 2: | 3659 | case 2: |
3626 | trace_seq_printf(s, format, (long long)val); | 3660 | if (len_as_arg) |
3661 | trace_seq_printf(s, format, len_arg, | ||
3662 | (long long)val); | ||
3663 | else | ||
3664 | trace_seq_printf(s, format, (long long)val); | ||
3627 | break; | 3665 | break; |
3628 | default: | 3666 | default: |
3629 | die("bad count (%d)", ls); | 3667 | die("bad count (%d)", ls); |
@@ -3633,7 +3671,9 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
3633 | if (!arg) | 3671 | if (!arg) |
3634 | die("no matching argument"); | 3672 | die("no matching argument"); |
3635 | 3673 | ||
3636 | print_str_arg(s, data, size, event, arg); | 3674 | if (!len_as_arg) |
3675 | len_arg = -1; | ||
3676 | print_str_arg(s, data, size, event, len_arg, arg); | ||
3637 | arg = arg->next; | 3677 | arg = arg->next; |
3638 | break; | 3678 | break; |
3639 | default: | 3679 | default: |