Files
acrn-hypervisor/tools/acrntrace/scripts/acrntrace_format.py
Kaige Fu 0d9b163875 tools: acrntrace: Add new tool acrntrace_format
acrntrace_format.py is used for parsing raw trace data to human-readable file on
given format. A sample format file for acrntrace predefined trace events is available
in tools/acrntrace/scripts/formats in acrn source tree.

Signed-off-by: Kaige Fu <kaige.fu@intel.com>
Reviewed-by: Yan, Like <like.yan@intel.com>
Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2018-06-29 13:05:27 +08:00

155 lines
3.8 KiB
Python
Executable File

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import os
import re
import sys
import string
import signal
import struct
import getopt
def usage():
print >> sys.stderr, \
"""
Usage:
acrntrace_format.py [options] [formats] [trace_data]
[options]
-h: print this message
Parses trace_data in binary format generated by acrntrace and
reformats it according to the rules in the [formats] file.
The rules in formats should have the format ({ and } show grouping
and are not part of the syntax):
{event_id}{whitespace}{text format string}
The textual format string may include format specifiers, such as
%(cpu)d, %(tsc)d, %(event)d, %(1)d, %(2)d, ....
The 'd' format specifier outputs in decimal, alternatively 'x' will
output in hexadecimal and 'o' will output in octal.
These respectively correspond to the CPU number (cpu), timestamp
counter (tsc), event ID (event) and the data logged in the trace file.
There can be only one such rule for each type of event.
"""
def read_format(format_file):
formats = {}
fd = open(format_file)
reg = re.compile('(\S+)\s+(\S.*)')
while True:
line = fd.readline()
if not line:
break
if line[0] == '#' or line[0] == '\n':
continue
m = reg.match(line)
if not m: print >> sys.stderr, "Wrong format file"; sys.exit(1)
formats[str(eval(m.group(1)))] = m.group(2)
return formats
exit = 0
# structure of trace data (as output by acrntrace)
# TSC(Q) HDR(Q) D1 D2 ...
# HDR consists of event:48:, n_data:8:, cpu:8:
# event means Event ID
# n_data means number of data in trace entry (like D1, D2, ...)
# cpu means cpu id this trace entry belong to
TSCREC = "Q"
HDRREC = "Q"
D2REC = "QQ"
D4REC = "IIII"
def main_loop(formats, fd):
global exit
i = 0
while not exit:
try:
i = i + 1
line = fd.read(struct.calcsize(TSCREC))
if not line:
break
tsc = struct.unpack(TSCREC, line)[0]
line = fd.read(struct.calcsize(HDRREC))
if not line:
break
event = struct.unpack(HDRREC, line)[0]
n_data = event >> 48 & 0xff
cpu = event >> 56
event = event & 0xffffffffffff
d1 = 0
d2 = 0
d3 = 0
d4 = 0
if n_data == 2:
line = fd.read(struct.calcsize(D2REC))
if not line:
break
(d1, d2) = struct.unpack(D2REC, line)
if n_data == 4:
line = fd.read(struct.calcsize(D4REC))
if not line:
break
(d1, d2, d3, d4) = struct.unpack(D4REC, line)
args = {'cpu' : cpu,
'tsc' : tsc,
'event' : event,
'1' : d1,
'2' : d2,
'3' : d3,
'4' : d4 }
try:
if str(event) in formats.keys():
print (formats[str(event)] % args)
except TypeError:
if str(event) in formats.key():
print (formats[str(event)])
print (args)
except struct.error:
sys.exit()
def main(argv):
try:
opts, arg = getopt.getopt(sys.argv[1:], "h")
for opt in opts:
if opt[0] == '-h':
usage()
sys.exit()
except getopt.GetoptError:
usage()
sys.exit(1)
try:
formats = read_format(arg[0])
fd = open(arg[1], 'rb')
except IOError:
sys.exit(1)
main_loop(formats, fd)
if __name__ == "__main__":
main(sys.argv[1:])