3 # by Mark Williamson, (C) 2004 Intel Research Cambridge
5 # Program for reformatting trace buffer output according to user-supplied rules
7 import re
, sys
, string
, signal
, struct
, os
, getopt
10 print >> sys
.stderr
, \
11 "Usage: " + sys
.argv
[0] + """ defs-file
12 Parses trace data in binary format, as output by kvmtrace and
13 reformats it according to the rules in a file of definitions. The
14 rules in this file should have the format ({ and } show grouping
15 and are not part of the syntax):
17 {event_id}{whitespace}{text format string}
19 The textual format string may include format specifiers, such as:
20 %(tsc)d, %(event)d, %(pid)d %(vcpu)d %(1)d, %(2)d,
22 [ the 'd' format specifier outputs in decimal, alternatively 'x'
23 will output in hexadecimal and 'o' will output in octal ]
25 Which correspond to the event ID, timestamp counter, pid
26 , vcpu and the 5 data fields from the trace record. There should be
27 one such rule for each type of event.
28 Depending on your system and the volume of trace buffer data,
29 this script may not be able to keep up with the output of kvmtrace
30 if it is piped directly. In these circumstances you should have
31 kvmtrace output to a file for processing off-line.
35 def read_defs(defs_file
):
40 reg
= re
.compile('(\S+)\s+(\S.*)')
47 if line
[0] == '#' or line
[0] == '\n':
52 if not m
: print >> sys
.stderr
, "Bad format file" ; sys
.exit(1)
54 defs
[str(eval(m
.group(1)))] = m
.group(2)
70 opts
, arg
= getopt
.getopt(sys
.argv
[1:], "c:" )
73 if opt
[0] == '-c' : mhz
= int(opt
[1])
75 except getopt
.GetoptError
:
78 signal
.signal(signal
.SIGTERM
, sighand
)
79 signal
.signal(signal
.SIGHUP
, sighand
)
80 signal
.signal(signal
.SIGINT
, sighand
)
84 defs
= read_defs(arg
[0])
86 # structure of trace record (as output by kvmtrace):
87 # HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I)
89 # HDR consists of EVENT:28:, n_data:3:, tsc_in:1:
91 # EVENT means Event ID
92 # n_data means number of data (like D1, D2, ...)
93 # tsc_in means TSC data exists(1) or not(0).
94 # if tsc_in == 0, TSC(Q) does not exists.
108 while not interrupted
:
111 line
= sys
.stdin
.read(struct
.calcsize(HDRREC
))
114 (event
, pid
, vcpu_id
) = struct
.unpack(HDRREC
, line
)
116 n_data
= event
>> 28 & 0x7
128 line
= sys
.stdin
.read(struct
.calcsize(TSCREC
))
131 tsc
= struct
.unpack(TSCREC
, line
)[0]
133 line
= sys
.stdin
.read(struct
.calcsize(D1REC
))
136 d1
= struct
.unpack(D1REC
, line
)[0]
138 line
= sys
.stdin
.read(struct
.calcsize(D2REC
))
141 (d1
, d2
) = struct
.unpack(D2REC
, line
)
143 line
= sys
.stdin
.read(struct
.calcsize(D3REC
))
146 (d1
, d2
, d3
) = struct
.unpack(D3REC
, line
)
148 line
= sys
.stdin
.read(struct
.calcsize(D4REC
))
151 (d1
, d2
, d3
, d4
) = struct
.unpack(D4REC
, line
)
153 line
= sys
.stdin
.read(struct
.calcsize(D5REC
))
156 (d1
, d2
, d3
, d4
, d5
) = struct
.unpack(D5REC
, line
)
160 # provide relative TSC
162 if last_tsc
> 0 and tsc_in
== 1:
163 reltsc
= tsc
- last_tsc
171 tsc
= tsc
/ (mhz
*1000000.0)
186 if defs
.has_key(str(event
)):
187 print defs
[str(event
)] % args
189 if defs
.has_key(str(0)): print defs
[str(0)] % args
191 if defs
.has_key(str(event
)):
192 print defs
[str(event
)]
195 if defs
.has_key(str(0)):
200 except IOError, struct
.error
: sys
.exit()