cpumf/pai: Handle different size of perf_event_attr

The structure perf_event_attr sometimes gets new members appended
at the end of the structure. Then the size of the structure increases.
This may lead to the situation where sizeof(struct perf_event_attr)
calculated at the pai program compile time during s390-tools build
differs from the one used to build application programs on the target
system.

The report files written by various tools write the contents of the
perf_event_attr structure followed by indivual samples to a binary file.
The second member perf_event_attr::size contains the size of that
structure in bytes.

Use that perf_event_attr::size from the target system to scan the
report files given as command line argument. This ensure the correct
size of structure perf_event_attr is used.

Output before:
Current situation: The pai program uses a perf_event_attr structure
which contains 8 bytes less than the one used on the target system.
The first sample header (8 bytes) then actually refers to the last
eight bytes of structure perf_event_attr, which are all zeroes. This
is an invalid sample entry and the program terminates with error.

 # pai -r -V painnpa.0004043; echo $?
 painnpa.0004043 size:1344
 [0x000088] type 0 misc 0 size 0
 1

Output after:
Use the correct size of structure perf_event_attr, which was read
from be binary file, written by the tools compiled on the target system:
 # pai -r -V painnpa.0004043; echo $?
 painnpa.0004043 size:1344
 size perf_event_attr mismatch 136/144
 [0x000090] type 9 misc 1 size 58 0x13537f71715 18 event 6144 \
	 sample pid 4043/4043 15:0x8a,16:0x88,22:0x112,25:0xc0
 ...
 0

Also show an debug message when verbose mode is turned on.

Signed-off-by: Thomas Richter <tmricht@linux.ibm.com>
Reviewed-by: Jan Polensky <japo@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
Thomas Richter
2026-01-12 07:50:26 +01:00
committed by Jan Höppner
parent 4cf239b8b6
commit 52ddd291d4

View File

@@ -503,7 +503,7 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
__u64 sample_type = pa->sample_type;
int allcnt = 0, cnt = 0, rawok = 0;
struct perf_event_header *hdr;
size_t offset = sizeof(*pa);
size_t offset = pa->size;
__u64 evtnum = pa->config;
struct pai_event_out ev;
size_t limit;
@@ -514,6 +514,8 @@ static int evt_scan(char *fn, unsigned char *buf, size_t len,
unsigned char valid;
} last_csout = { 0, 0, 0 };
if (verbose && (sizeof(*pa) != pa->size))
printf("size perf_event_attr mismatch %zu/%zu\n", sizeof(*pa), offset);
while (offset < len) {
hdr = (struct perf_event_header *)(buf + offset);
memset(&ev, 0, sizeof(ev));