Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libtraceevent: Add __rel_loc relative location attribute support

Add '__rel_loc' new dynamic data location attribute which encodes
the data location from the next to the field itself. This is similar
to the '__data_loc' but the location offset is not from the event
entry but from the next of the field.

This patch adds '__rel_loc' decoding support in the libtraceevent.

Link: https://lkml.kernel.org/r/163757343994.510314.13241077597729303802.stgit@devnote2

Cc: Beau Belgrave <beaub@linux.microsoft.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Tom Zanussi <zanussi@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>

authored by

Masami Hiramatsu and committed by
Steven Rostedt (VMware)
cd772904 b466b133

+47 -22
+40 -19
tools/lib/traceevent/event-parse.c
··· 1367 1367 return 0; 1368 1368 } 1369 1369 1370 + static int field_is_relative_dynamic(struct tep_format_field *field) 1371 + { 1372 + if (strncmp(field->type, "__rel_loc", 9) == 0) 1373 + return 1; 1374 + 1375 + return 0; 1376 + } 1377 + 1370 1378 static int field_is_long(struct tep_format_field *field) 1371 1379 { 1372 1380 /* includes long long */ ··· 1630 1622 field->flags |= TEP_FIELD_IS_STRING; 1631 1623 if (field_is_dynamic(field)) 1632 1624 field->flags |= TEP_FIELD_IS_DYNAMIC; 1625 + if (field_is_relative_dynamic(field)) 1626 + field->flags |= TEP_FIELD_IS_DYNAMIC | TEP_FIELD_IS_RELATIVE; 1633 1627 if (field_is_long(field)) 1634 1628 field->flags |= TEP_FIELD_IS_LONG; 1635 1629 ··· 2938 2928 2939 2929 arg->type = TEP_PRINT_STRING; 2940 2930 arg->string.string = token; 2941 - arg->string.offset = -1; 2931 + arg->string.field = NULL; 2942 2932 2943 2933 if (read_expected(TEP_EVENT_DELIM, ")") < 0) 2944 2934 goto out_err; ··· 2967 2957 2968 2958 arg->type = TEP_PRINT_BITMASK; 2969 2959 arg->bitmask.bitmask = token; 2970 - arg->bitmask.offset = -1; 2960 + arg->bitmask.field = NULL; 2971 2961 2972 2962 if (read_expected(TEP_EVENT_DELIM, ")") < 0) 2973 2963 goto out_err; ··· 3133 3123 free_token(token); 3134 3124 return process_int_array(event, arg, tok); 3135 3125 } 3136 - if (strcmp(token, "__get_str") == 0) { 3126 + if (strcmp(token, "__get_str") == 0 || 3127 + strcmp(token, "__get_rel_str") == 0) { 3137 3128 free_token(token); 3138 3129 return process_str(event, arg, tok); 3139 3130 } 3140 - if (strcmp(token, "__get_bitmask") == 0) { 3131 + if (strcmp(token, "__get_bitmask") == 0 || 3132 + strcmp(token, "__get_rel_bitmask") == 0) { 3141 3133 free_token(token); 3142 3134 return process_bitmask(event, arg, tok); 3143 3135 } 3144 - if (strcmp(token, "__get_dynamic_array") == 0) { 3136 + if (strcmp(token, "__get_dynamic_array") == 0 || 3137 + strcmp(token, "__get_rel_dynamic_array") == 0) { 3145 3138 free_token(token); 3146 3139 return process_dynamic_array(event, arg, tok); 3147 3140 } 3148 - if (strcmp(token, "__get_dynamic_array_len") == 0) { 3141 + if (strcmp(token, "__get_dynamic_array_len") == 0 || 3142 + strcmp(token, "__get_rel_dynamic_array_len") == 0) { 3149 3143 free_token(token); 3150 3144 return process_dynamic_array_len(event, arg, tok); 3151 3145 } ··· 4177 4163 case TEP_PRINT_STRING: { 4178 4164 int str_offset; 4179 4165 4180 - if (arg->string.offset == -1) { 4181 - struct tep_format_field *f; 4166 + if (!arg->string.field) 4167 + arg->string.field = tep_find_any_field(event, arg->string.string); 4168 + if (!arg->string.field) 4169 + break; 4182 4170 4183 - f = tep_find_any_field(event, arg->string.string); 4184 - arg->string.offset = f->offset; 4185 - } 4186 - str_offset = data2host4(tep, *(unsigned int *)(data + arg->string.offset)); 4171 + str_offset = data2host4(tep, 4172 + *(unsigned int *)(data + arg->string.field->offset)); 4187 4173 str_offset &= 0xffff; 4174 + if (arg->string.field->flags & TEP_FIELD_IS_RELATIVE) 4175 + str_offset += arg->string.field->offset + arg->string.field->size; 4188 4176 print_str_to_seq(s, format, len_arg, ((char *)data) + str_offset); 4189 4177 break; 4190 4178 } ··· 4197 4181 int bitmask_offset; 4198 4182 int bitmask_size; 4199 4183 4200 - if (arg->bitmask.offset == -1) { 4201 - struct tep_format_field *f; 4202 - 4203 - f = tep_find_any_field(event, arg->bitmask.bitmask); 4204 - arg->bitmask.offset = f->offset; 4205 - } 4206 - bitmask_offset = data2host4(tep, *(unsigned int *)(data + arg->bitmask.offset)); 4184 + if (!arg->bitmask.field) 4185 + arg->bitmask.field = tep_find_any_field(event, arg->bitmask.bitmask); 4186 + if (!arg->bitmask.field) 4187 + break; 4188 + bitmask_offset = data2host4(tep, 4189 + *(unsigned int *)(data + arg->bitmask.field->offset)); 4207 4190 bitmask_size = bitmask_offset >> 16; 4208 4191 bitmask_offset &= 0xffff; 4192 + if (arg->bitmask.field->flags & TEP_FIELD_IS_RELATIVE) 4193 + bitmask_offset += arg->bitmask.field->offset + arg->bitmask.field->size; 4209 4194 print_bitmask_to_seq(tep, s, format, len_arg, 4210 4195 data + bitmask_offset, bitmask_size); 4211 4196 break; ··· 5126 5109 offset = val; 5127 5110 len = offset >> 16; 5128 5111 offset &= 0xffff; 5112 + if (field->flags & TEP_FIELD_IS_RELATIVE) 5113 + offset += field->offset + field->size; 5129 5114 } 5130 5115 if (field->flags & TEP_FIELD_IS_STRING && 5131 5116 is_printable_array(data + offset, len)) { ··· 7006 6987 data + offset, field->size); 7007 6988 *len = offset >> 16; 7008 6989 offset &= 0xffff; 6990 + if (field->flags & TEP_FIELD_IS_RELATIVE) 6991 + offset += field->offset + field->size; 7009 6992 } else 7010 6993 *len = field->size; 7011 6994
+3 -2
tools/lib/traceevent/event-parse.h
··· 125 125 TEP_FIELD_IS_LONG = 32, 126 126 TEP_FIELD_IS_FLAG = 64, 127 127 TEP_FIELD_IS_SYMBOLIC = 128, 128 + TEP_FIELD_IS_RELATIVE = 256, 128 129 }; 129 130 130 131 struct tep_format_field { ··· 154 153 155 154 struct tep_print_arg_string { 156 155 char *string; 157 - int offset; 156 + struct tep_format_field *field; 158 157 }; 159 158 160 159 struct tep_print_arg_bitmask { 161 160 char *bitmask; 162 - int offset; 161 + struct tep_format_field *field; 163 162 }; 164 163 165 164 struct tep_print_arg_field {
+4 -1
tools/lib/traceevent/parse-filter.c
··· 1712 1712 1713 1713 if (arg->str.field->flags & TEP_FIELD_IS_DYNAMIC) { 1714 1714 addr = *(unsigned int *)val; 1715 - val = record->data + (addr & 0xffff); 1716 1715 size = addr >> 16; 1716 + addr &= 0xffff; 1717 + if (arg->str.field->flags & TEP_FIELD_IS_RELATIVE) 1718 + addr += arg->str.field->offset + arg->str.field->size; 1719 + val = record->data + addr; 1717 1720 } 1718 1721 1719 1722 /*