From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:51619) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rhbvo-0006M6-VT for qemu-devel@nongnu.org; Mon, 02 Jan 2012 02:03:42 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Rhbvn-0001UF-L2 for qemu-devel@nongnu.org; Mon, 02 Jan 2012 02:03:40 -0500 Received: from e28smtp08.in.ibm.com ([122.248.162.8]:48159) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Rhbvm-0001Tt-Ls for qemu-devel@nongnu.org; Mon, 02 Jan 2012 02:03:39 -0500 Received: from /spool/local by e28smtp08.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 2 Jan 2012 12:33:35 +0530 Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay02.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id q0273SSv4153482 for ; Mon, 2 Jan 2012 12:33:29 +0530 Received: from d28av03.in.ibm.com (loopback [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id q0273Sav007201 for ; Mon, 2 Jan 2012 18:03:28 +1100 Message-ID: <4F0156C0.4030505@linux.vnet.ibm.com> Date: Mon, 02 Jan 2012 12:33:28 +0530 From: Harsh Bora MIME-Version: 1.0 References: <1325487023-10613-1-git-send-email-harsh@linux.vnet.ibm.com> <1325487023-10613-5-git-send-email-harsh@linux.vnet.ibm.com> In-Reply-To: <1325487023-10613-5-git-send-email-harsh@linux.vnet.ibm.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 4/4] simpletrace.py: Simpletrace v2 tracelog reader script List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: stefanha@linux.vnet.ibm.com, aneesh.kumar@linux.vnet.ibm.com Hi, Please ignore this duplicate patch in the series which was sent by mistake, consider the one with subject '[RFC PATCH 4/4] simpletrace.py: updated log reader script to handle new log format'. Sorry for inconvenience. - Harsh On 01/02/2012 12:20 PM, Harsh Prateek Bora wrote: > Signed-off-by: Harsh Prateek Bora > --- > scripts/simpletrace.py | 110 +++++++++++++++++++++++++++++++++++++++++++----- > 1 files changed, 99 insertions(+), 11 deletions(-) > > diff --git a/scripts/simpletrace.py b/scripts/simpletrace.py > index f55e5e6..69829dd 100755 > --- a/scripts/simpletrace.py > +++ b/scripts/simpletrace.py > @@ -12,16 +12,37 @@ > import struct > import re > import inspect > +import sys > +from tracetool import * > > header_event_id = 0xffffffffffffffff > header_magic = 0xf2b177cb0aa429b4 > header_version = 0 > +log_header_ver = 2 > dropped_event_id = 0xfffffffffffffffe > > trace_fmt = '=QQQQQQQQ' > +header_fmt = '=QQII' > +header_len = struct.calcsize(header_fmt) > trace_len = struct.calcsize(trace_fmt) > event_re = re.compile(r'(disable\s+)?([a-zA-Z0-9_]+)\(([^)]*)\).*') > > +def get_event_argtypes(fobj): > + """Parse a trace-events file into {event_num: (name, type arg, ...)}.""" > + > + events = {dropped_event_id: ('name', 'args')} > + event_num = 0 > + for line in fobj: > + m = event_re.match(line.strip()) > + if m is None: > + continue > + > + disable, name, args = m.groups() > + events[event_num] = tuple(args.split(',')) > + event_num += 1 > + return events > + > + > def parse_events(fobj): > """Parse a trace-events file into {event_num: (name, arg1, ...)}.""" > > @@ -48,15 +69,16 @@ def read_record(fobj): > return None > return struct.unpack(trace_fmt, s) > > +def read_header(fobj): > + '''Read a trace record header''' > + s = fobj.read(header_len) > + if len(s) != header_len: > + return None > + return struct.unpack(header_fmt, s) > + > + > def read_trace_file(fobj): > """Deserialize trace records from a file, yielding record tuples (event_num, timestamp, arg1, ..., arg6).""" > - header = read_record(fobj) > - if header is None or \ > - header[0] != header_event_id or \ > - header[1] != header_magic or \ > - header[2] != header_version: > - raise ValueError('not a trace file or incompatible version') > - > while True: > rec = read_record(fobj) > if rec is None: > @@ -64,6 +86,59 @@ def read_trace_file(fobj): > > yield rec > > +def process_event(event_id, fobj): > + params = etypes[event_id] > + for elem in params: > + if is_string(elem): > + l = fobj.read(4) > + (len,) = struct.unpack('=L', l) > + s = fobj.read(len) > + sfmt = `len`+'s' > + (str,) = struct.unpack_from(sfmt, s) > + type, sep, var = elem.rpartition('*') > + print '%(arg)s=%(val)s' % { 'arg': var.lstrip(), 'val': str }, > + elif '*' in elem: > + (value,) = struct.unpack('=Q', fobj.read(8)) > + type, sep, var = elem.rpartition('*') > + print '%(arg)s=0x%(val)u' % { 'arg': var.lstrip(), 'val': value }, > + else: > + (value,) = struct.unpack('=Q', fobj.read(8)) > + type, sep, var = elem.rpartition(' ') > + print '%(arg)s=%(val)u' % { 'arg': var.lstrip(), 'val': value }, > + print > + return > + > +etypes = get_event_argtypes(open(sys.argv[1], 'r')) > +def processv2(fobj): > + '''Process simpletrace v2 log trace records''' > + events = parse_events(open(sys.argv[1], 'r')) > + #print events > + max_events = len(events) - 1 > + last_timestamp = None > + while True: > + # read record header > + rechdr = read_header(fobj) > + if rechdr is None: > + print "No more records" > + break > + > + if rechdr[0]>= max_events: > + print "Invalid Event ID found, Trace Log may be corrupted !!!" > + sys.exit(1) > + > + if last_timestamp is None: > + last_timestamp = rechdr[1] > + delta_ns = rechdr[1] - last_timestamp > + last_timestamp = rechdr[1] > + > + print events[rechdr[0]][0], '%0.3f' % (delta_ns / 1000.0), > + # read data > + # process_event(rec[0], fobj) > + # rechdr[2] is record length (including header) > + #print etypes[rechdr[0]] > + #data = fobj.read(rechdr[2] - header_len) > + process_event(rechdr[0], fobj) > + > class Analyzer(object): > """A trace file analyzer which processes trace records. > > @@ -90,8 +165,6 @@ def process(events, log, analyzer): > """Invoke an analyzer on each event in a log.""" > if isinstance(events, str): > events = parse_events(open(events, 'r')) > - if isinstance(log, str): > - log = open(log, 'rb') > > def build_fn(analyzer, event): > fn = getattr(analyzer, event[0], None) > @@ -129,8 +202,10 @@ def run(analyzer): > sys.exit(1) > > events = parse_events(open(sys.argv[1], 'r')) > - process(events, sys.argv[2], analyzer) > + process(events, log, analyzer) > + > > +log = open(sys.argv[2], 'rb') > if __name__ == '__main__': > class Formatter(Analyzer): > def __init__(self): > @@ -148,4 +223,17 @@ if __name__ == '__main__': > fields.append('%s=0x%x' % (event[i], rec[i + 1])) > print ' '.join(fields) > > - run(Formatter()) > + #run(Formatter()) > + header = read_header(log) > + if header is None or \ > + header[0] != header_event_id or \ > + header[1] != header_magic: > + raise ValueError('not a valid trace file') > + if header[2] == 0: # version 1 > + # ver 1 tracelog header contains few more unused bytes > + temp = log.read(40) # read those bytes and continue > + run(Formatter()) > + elif header[2] == 2: # version 2 > + processv2(log) > + else: > + raise ValueError('trace file version not supported')