mirror of https://gitlab.com/qemu-project/qemu
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.0 KiB
Python
131 lines
4.0 KiB
Python
#!/usr/bin/env python3
|
|
#
|
|
# validate-memory-counts.py: check we instrumented memory properly
|
|
#
|
|
# This program takes two inputs:
|
|
# - the mem plugin output
|
|
# - the memory binary output
|
|
#
|
|
# Copyright (C) 2024 Linaro Ltd
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
import sys
|
|
from argparse import ArgumentParser
|
|
|
|
def extract_counts(path):
|
|
"""
|
|
Load the output from path and extract the lines containing:
|
|
|
|
Test data start: 0x40214000
|
|
Test data end: 0x40218001
|
|
Test data read: 2522280
|
|
Test data write: 262111
|
|
|
|
From the stream of data. Extract the values for use in the
|
|
validation function.
|
|
"""
|
|
start_address = None
|
|
end_address = None
|
|
read_count = 0
|
|
write_count = 0
|
|
with open(path, 'r') as f:
|
|
for line in f:
|
|
if line.startswith("Test data start:"):
|
|
start_address = int(line.split(':')[1].strip(), 16)
|
|
elif line.startswith("Test data end:"):
|
|
end_address = int(line.split(':')[1].strip(), 16)
|
|
elif line.startswith("Test data read:"):
|
|
read_count = int(line.split(':')[1].strip())
|
|
elif line.startswith("Test data write:"):
|
|
write_count = int(line.split(':')[1].strip())
|
|
return start_address, end_address, read_count, write_count
|
|
|
|
|
|
def parse_plugin_output(path, start, end):
|
|
"""
|
|
Load the plugin output from path in the form of:
|
|
|
|
Region Base, Reads, Writes, Seen all
|
|
0x0000000040004000, 31093, 0, false
|
|
0x0000000040214000, 2522280, 278579, true
|
|
0x0000000040000000, 137398, 0, false
|
|
0x0000000040210000, 54727397, 33721956, false
|
|
|
|
And extract the ranges that match test data start and end and
|
|
return the results.
|
|
"""
|
|
total_reads = 0
|
|
total_writes = 0
|
|
seen_all = False
|
|
|
|
with open(path, 'r') as f:
|
|
next(f) # Skip the header
|
|
for line in f:
|
|
|
|
if line.startswith("Region Base"):
|
|
continue
|
|
|
|
parts = line.strip().split(', ')
|
|
if len(parts) != 4:
|
|
continue
|
|
|
|
region_base = int(parts[0], 16)
|
|
reads = int(parts[1])
|
|
writes = int(parts[2])
|
|
|
|
if start <= region_base < end: # Checking if within range
|
|
total_reads += reads
|
|
total_writes += writes
|
|
seen_all = parts[3] == "true"
|
|
|
|
return total_reads, total_writes, seen_all
|
|
|
|
def main() -> None:
|
|
"""
|
|
Process the arguments, injest the program and plugin out and
|
|
verify they match up and report if they do not.
|
|
"""
|
|
parser = ArgumentParser(description="Validate memory instrumentation")
|
|
parser.add_argument('test_output',
|
|
help="The output from the test itself")
|
|
parser.add_argument('plugin_output',
|
|
help="The output from memory plugin")
|
|
parser.add_argument('--bss-cleared',
|
|
action='store_true',
|
|
help='Assume bss was cleared (and adjusts counts).')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Extract counts from memory binary
|
|
start, end, exp_reads, exp_writes = extract_counts(args.test_output)
|
|
|
|
# Some targets clear BSS before running but the test doesn't know
|
|
# that so we adjust it by the size of the test region.
|
|
if args.bss_cleared:
|
|
exp_writes += 16384
|
|
|
|
if start is None or end is None:
|
|
print("Failed to test_data boundaries from output.")
|
|
sys.exit(1)
|
|
|
|
# Parse plugin output
|
|
preads, pwrites, seen_all = parse_plugin_output(args.plugin_output,
|
|
start, end)
|
|
|
|
if not seen_all:
|
|
print("Fail: didn't instrument all accesses to test_data.")
|
|
sys.exit(1)
|
|
|
|
# Compare and report
|
|
if preads == exp_reads and pwrites == exp_writes:
|
|
sys.exit(0)
|
|
else:
|
|
print("Fail: The memory reads and writes count does not match.")
|
|
print(f"Expected Reads: {exp_reads}, Actual Reads: {preads}")
|
|
print(f"Expected Writes: {exp_writes}, Actual Writes: {pwrites}")
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|