Skip to content

Commit 9bf6328

Browse files
namhyungacmel
authored andcommitted
perf tools: Handle old data in PERF_RECORD_ATTR
The PERF_RECORD_ATTR is used for a pipe mode to describe an event with attribute and IDs. The ID table comes after the attr and it calculate size of the table using the total record size and the attr size. n_ids = (total_record_size - end_of_the_attr_field) / sizeof(u64) This is fine for most use cases, but sometimes it saves the pipe output in a file and then process it later. And it becomes a problem if there is a change in attr size between the record and report. $ perf record -o- > perf-pipe.data # old version $ perf report -i- < perf-pipe.data # new version For example, if the attr size is 128 and it has 4 IDs, then it would save them in 168 byte like below: 8 byte: perf event header { .type = PERF_RECORD_ATTR, .size = 168 }, 128 byte: perf event attr { .size = 128, ... }, 32 byte: event IDs [] = { 1234, 1235, 1236, 1237 }, But when report later, it thinks the attr size is 136 then it only read the last 3 entries as ID. 8 byte: perf event header { .type = PERF_RECORD_ATTR, .size = 168 }, 136 byte: perf event attr { .size = 136, ... }, 24 byte: event IDs [] = { 1235, 1236, 1237 }, // 1234 is missing So it should use the recorded version of the attr. The attr has the size field already then it should honor the size when reading data. Fixes: 2c46dbb ("perf: Convert perf header attrs into attr events") Signed-off-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Ian Rogers <irogers@google.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tom Zanussi <zanussi@kernel.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20230825152552.112913-1-namhyung@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
1 parent cd4e1ef commit 9bf6328

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

tools/perf/util/header.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4378,7 +4378,8 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
43784378
union perf_event *event,
43794379
struct evlist **pevlist)
43804380
{
4381-
u32 i, ids, n_ids;
4381+
u32 i, n_ids;
4382+
u64 *ids;
43824383
struct evsel *evsel;
43834384
struct evlist *evlist = *pevlist;
43844385

@@ -4394,9 +4395,8 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
43944395

43954396
evlist__add(evlist, evsel);
43964397

4397-
ids = event->header.size;
4398-
ids -= (void *)&event->attr.id - (void *)event;
4399-
n_ids = ids / sizeof(u64);
4398+
n_ids = event->header.size - sizeof(event->header) - event->attr.attr.size;
4399+
n_ids = n_ids / sizeof(u64);
44004400
/*
44014401
* We don't have the cpu and thread maps on the header, so
44024402
* for allocating the perf_sample_id table we fake 1 cpu and
@@ -4405,8 +4405,9 @@ int perf_event__process_attr(struct perf_tool *tool __maybe_unused,
44054405
if (perf_evsel__alloc_id(&evsel->core, 1, n_ids))
44064406
return -ENOMEM;
44074407

4408+
ids = (void *)&event->attr.attr + event->attr.attr.size;
44084409
for (i = 0; i < n_ids; i++) {
4409-
perf_evlist__id_add(&evlist->core, &evsel->core, 0, i, event->attr.id[i]);
4410+
perf_evlist__id_add(&evlist->core, &evsel->core, 0, i, ids[i]);
44104411
}
44114412

44124413
return 0;

0 commit comments

Comments
 (0)