aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Munsie <imunsie@au1.ibm.com>2010-05-13 02:03:47 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-05-14 09:13:14 -0400
commitb8bcc46f9d54288f8df6ad41a7b2abca7b65c780 (patch)
tree0aaee0850e9fac93308125fed28c9cd4691c09db
parentde8153c870ee2b74905076362f784ef42dd5ed9e (diff)
trace-cmd: Correctly handle arrays
[ Taken from a perf patch. I got the OK from Ian Musie to include this under LGPL ] Previously, perf was assuming that an array from an ftrace event was an array of longs, which will not always be the case. Additionally, long_size is not even being initialised, so it would fail to read the data and would erroneously report that the array was filled with zeroes. This patch adds two extra entries into the field structure - arraylen and elementsize, so that the code can easily look them up instead of assuming that the elements are long_size. The element size is currently derived by the size of the entire array and the number of elements within the array. This problem can be demonstrated with: perf record -e raw_syscalls:sys_enter -a sleep 0.1 perf trace Without this patch, output similar to the following is produced: perf-4355 [004] 1871.504685: sys_enter: NR 319 (0, 0, 0, 0, 0, 0) perf-4355 [004] 1871.504723: sys_enter: NR 3 (0, 0, 0, 0, 0, 0) perf-4355 [004] 1871.504733: sys_enter: NR 204 (0, 0, 0, 0, 0, 0) After applying this patch, the output looks like: perf-4355 [004] 1871.504685: sys_enter: NR 319 (10247ac0, ffffffff, 5, ffffffff, 0, 107a80d8) perf-4355 [004] 1871.504723: sys_enter: NR 3 (a, ffb6fcf0, 20, ffffffff, 0, 10112c20) perf-4355 [004] 1871.504733: sys_enter: NR 204 (a, 4, 800, 6, 0, 10112c20) Signed-off-by: Ian Munsie <imunsie@au1.ibm.com> LKML-Reference: <1273730632-21008-3-git-send-email-imunsie@au1.ibm.com> [ Fixed array handling ] Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--parse-events.c25
-rw-r--r--parse-events.h2
2 files changed, 23 insertions, 4 deletions
diff --git a/parse-events.c b/parse-events.c
index 59596ae..9873ef0 100644
--- a/parse-events.c
+++ b/parse-events.c
@@ -1248,6 +1248,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1248 field->flags |= FIELD_IS_ARRAY; 1248 field->flags |= FIELD_IS_ARRAY;
1249 1249
1250 type = read_token(&token); 1250 type = read_token(&token);
1251
1252 if (type == EVENT_ITEM)
1253 field->arraylen = strtoul(token, NULL, 0);
1254 else
1255 field->arraylen = 0;
1256
1251 while (strcmp(token, "]") != 0) { 1257 while (strcmp(token, "]") != 0) {
1252 if (last_type == EVENT_ITEM && 1258 if (last_type == EVENT_ITEM &&
1253 type == EVENT_ITEM) 1259 type == EVENT_ITEM)
@@ -1262,6 +1268,8 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1262 if (len == 2) 1268 if (len == 2)
1263 strcat(brackets, " "); 1269 strcat(brackets, " ");
1264 strcat(brackets, token); 1270 strcat(brackets, token);
1271 /* We only care about the last token */
1272 field->arraylen = strtoul(token, NULL, 0);
1265 free_token(token); 1273 free_token(token);
1266 type = read_token(&token); 1274 type = read_token(&token);
1267 if (type == EVENT_NONE) { 1275 if (type == EVENT_NONE) {
@@ -1367,6 +1375,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
1367 1375
1368 free_token(token); 1376 free_token(token);
1369 1377
1378 if (field->flags & FIELD_IS_ARRAY) {
1379 if (field->arraylen)
1380 field->elementsize = field->size / field->arraylen;
1381 else
1382 field->elementsize = event->pevent->long_size;
1383 } else
1384 field->elementsize = field->size;
1385
1370 *fields = field; 1386 *fields = field;
1371 fields = &field->next; 1387 fields = &field->next;
1372 1388
@@ -2889,13 +2905,13 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
2889 die("field %s not found", larg->field.name); 2905 die("field %s not found", larg->field.name);
2890 } 2906 }
2891 offset = larg->field.field->offset + 2907 offset = larg->field.field->offset +
2892 right * pevent->long_size; 2908 right * larg->field.field->elementsize;
2893 break; 2909 break;
2894 default: 2910 default:
2895 goto default_op; /* oops, all bets off */ 2911 goto default_op; /* oops, all bets off */
2896 } 2912 }
2897 val = pevent_read_number(pevent, 2913 val = pevent_read_number(pevent,
2898 data + offset, pevent->long_size); 2914 data + offset, larg->field.field->elementsize);
2899 if (typearg) 2915 if (typearg)
2900 val = eval_type(val, typearg, 1); 2916 val = eval_type(val, typearg, 1);
2901 break; 2917 break;
@@ -4269,6 +4285,9 @@ int pevent_parse_event(struct pevent *pevent,
4269 4285
4270 event->system = strdup(sys); 4286 event->system = strdup(sys);
4271 4287
4288 /* Add pevent to event so that it can be referenced */
4289 event->pevent = pevent;
4290
4272 ret = event_read_format(event); 4291 ret = event_read_format(event);
4273 if (ret < 0) { 4292 if (ret < 0) {
4274 do_warning("failed to read event format for %s", event->name); 4293 do_warning("failed to read event format for %s", event->name);
@@ -4282,8 +4301,6 @@ int pevent_parse_event(struct pevent *pevent,
4282 if (find_event_handle(pevent, event)) 4301 if (find_event_handle(pevent, event))
4283 show_warning = 0; 4302 show_warning = 0;
4284 4303
4285 /* Add pevent to event so that function list can be referenced */
4286 event->pevent = pevent;
4287 ret = event_read_print(event); 4304 ret = event_read_print(event);
4288 if (ret < 0) { 4305 if (ret < 0) {
4289 do_warning("failed to read event print fmt for %s", 4306 do_warning("failed to read event print fmt for %s",
diff --git a/parse-events.h b/parse-events.h
index 0c6a330..0283f57 100644
--- a/parse-events.h
+++ b/parse-events.h
@@ -118,6 +118,8 @@ struct format_field {
118 char *name; 118 char *name;
119 int offset; 119 int offset;
120 int size; 120 int size;
121 unsigned int arraylen;
122 unsigned int elementsize;
121 unsigned long flags; 123 unsigned long flags;
122}; 124};
123 125