1*61046927SAndroid Build Coastguard Worker#!/usr/bin/env python3 2*61046927SAndroid Build Coastguard Worker########################################################################## 3*61046927SAndroid Build Coastguard Worker# 4*61046927SAndroid Build Coastguard Worker# Copyright 2008 VMware, Inc. 5*61046927SAndroid Build Coastguard Worker# All Rights Reserved. 6*61046927SAndroid Build Coastguard Worker# 7*61046927SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 8*61046927SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the 9*61046927SAndroid Build Coastguard Worker# "Software"), to deal in the Software without restriction, including 10*61046927SAndroid Build Coastguard Worker# without limitation the rights to use, copy, modify, merge, publish, 11*61046927SAndroid Build Coastguard Worker# distribute, sub license, and/or sell copies of the Software, and to 12*61046927SAndroid Build Coastguard Worker# permit persons to whom the Software is furnished to do so, subject to 13*61046927SAndroid Build Coastguard Worker# the following conditions: 14*61046927SAndroid Build Coastguard Worker# 15*61046927SAndroid Build Coastguard Worker# The above copyright notice and this permission notice (including the 16*61046927SAndroid Build Coastguard Worker# next paragraph) shall be included in all copies or substantial portions 17*61046927SAndroid Build Coastguard Worker# of the Software. 18*61046927SAndroid Build Coastguard Worker# 19*61046927SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20*61046927SAndroid Build Coastguard Worker# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21*61046927SAndroid Build Coastguard Worker# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22*61046927SAndroid Build Coastguard Worker# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23*61046927SAndroid Build Coastguard Worker# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24*61046927SAndroid Build Coastguard Worker# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25*61046927SAndroid Build Coastguard Worker# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26*61046927SAndroid Build Coastguard Worker# 27*61046927SAndroid Build Coastguard Worker########################################################################## 28*61046927SAndroid Build Coastguard Worker 29*61046927SAndroid Build Coastguard Worker 30*61046927SAndroid Build Coastguard Workerimport io 31*61046927SAndroid Build Coastguard Workerimport sys 32*61046927SAndroid Build Coastguard Workerimport xml.parsers.expat as xpat 33*61046927SAndroid Build Coastguard Workerimport argparse 34*61046927SAndroid Build Coastguard Worker 35*61046927SAndroid Build Coastguard Workerimport format 36*61046927SAndroid Build Coastguard Workerfrom model import * 37*61046927SAndroid Build Coastguard Worker 38*61046927SAndroid Build Coastguard Worker 39*61046927SAndroid Build Coastguard Workertrace_ignore_calls = set(( 40*61046927SAndroid Build Coastguard Worker ("pipe_screen", "is_format_supported"), 41*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_name"), 42*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_vendor"), 43*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_param"), 44*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_paramf"), 45*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_shader_param"), 46*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_compute_param"), 47*61046927SAndroid Build Coastguard Worker ("pipe_screen", "get_disk_shader_cache"), 48*61046927SAndroid Build Coastguard Worker)) 49*61046927SAndroid Build Coastguard Worker 50*61046927SAndroid Build Coastguard Worker 51*61046927SAndroid Build Coastguard Workerdef trace_call_ignore(call): 52*61046927SAndroid Build Coastguard Worker return (call.klass, call.method) in trace_ignore_calls 53*61046927SAndroid Build Coastguard Worker 54*61046927SAndroid Build Coastguard Worker 55*61046927SAndroid Build Coastguard WorkerELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) 56*61046927SAndroid Build Coastguard Worker 57*61046927SAndroid Build Coastguard Worker 58*61046927SAndroid Build Coastguard Workerclass XmlToken: 59*61046927SAndroid Build Coastguard Worker 60*61046927SAndroid Build Coastguard Worker def __init__(self, type, name_or_data, attrs = None, line = None, column = None): 61*61046927SAndroid Build Coastguard Worker assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) 62*61046927SAndroid Build Coastguard Worker self.type = type 63*61046927SAndroid Build Coastguard Worker self.name_or_data = name_or_data 64*61046927SAndroid Build Coastguard Worker self.attrs = attrs 65*61046927SAndroid Build Coastguard Worker self.line = line 66*61046927SAndroid Build Coastguard Worker self.column = column 67*61046927SAndroid Build Coastguard Worker 68*61046927SAndroid Build Coastguard Worker def __str__(self): 69*61046927SAndroid Build Coastguard Worker if self.type == ELEMENT_START: 70*61046927SAndroid Build Coastguard Worker return '<' + self.name_or_data + ' ...>' 71*61046927SAndroid Build Coastguard Worker if self.type == ELEMENT_END: 72*61046927SAndroid Build Coastguard Worker return '</' + self.name_or_data + '>' 73*61046927SAndroid Build Coastguard Worker if self.type == CHARACTER_DATA: 74*61046927SAndroid Build Coastguard Worker return self.name_or_data 75*61046927SAndroid Build Coastguard Worker if self.type == EOF: 76*61046927SAndroid Build Coastguard Worker return 'end of file' 77*61046927SAndroid Build Coastguard Worker assert 0 78*61046927SAndroid Build Coastguard Worker 79*61046927SAndroid Build Coastguard Worker 80*61046927SAndroid Build Coastguard Workerclass XmlTokenizer: 81*61046927SAndroid Build Coastguard Worker """Expat based XML tokenizer.""" 82*61046927SAndroid Build Coastguard Worker 83*61046927SAndroid Build Coastguard Worker def __init__(self, fp, skip_ws = True): 84*61046927SAndroid Build Coastguard Worker self.fp = fp 85*61046927SAndroid Build Coastguard Worker self.tokens = [] 86*61046927SAndroid Build Coastguard Worker self.index = 0 87*61046927SAndroid Build Coastguard Worker self.final = False 88*61046927SAndroid Build Coastguard Worker self.skip_ws = skip_ws 89*61046927SAndroid Build Coastguard Worker 90*61046927SAndroid Build Coastguard Worker self.character_pos = 0, 0 91*61046927SAndroid Build Coastguard Worker self.character_data = [] 92*61046927SAndroid Build Coastguard Worker 93*61046927SAndroid Build Coastguard Worker self.parser = xpat.ParserCreate() 94*61046927SAndroid Build Coastguard Worker self.parser.StartElementHandler = self.handle_element_start 95*61046927SAndroid Build Coastguard Worker self.parser.EndElementHandler = self.handle_element_end 96*61046927SAndroid Build Coastguard Worker self.parser.CharacterDataHandler = self.handle_character_data 97*61046927SAndroid Build Coastguard Worker 98*61046927SAndroid Build Coastguard Worker def handle_element_start(self, name, attributes): 99*61046927SAndroid Build Coastguard Worker self.finish_character_data() 100*61046927SAndroid Build Coastguard Worker line, column = self.pos() 101*61046927SAndroid Build Coastguard Worker token = XmlToken(ELEMENT_START, name, attributes, line, column) 102*61046927SAndroid Build Coastguard Worker self.tokens.append(token) 103*61046927SAndroid Build Coastguard Worker 104*61046927SAndroid Build Coastguard Worker def handle_element_end(self, name): 105*61046927SAndroid Build Coastguard Worker self.finish_character_data() 106*61046927SAndroid Build Coastguard Worker line, column = self.pos() 107*61046927SAndroid Build Coastguard Worker token = XmlToken(ELEMENT_END, name, None, line, column) 108*61046927SAndroid Build Coastguard Worker self.tokens.append(token) 109*61046927SAndroid Build Coastguard Worker 110*61046927SAndroid Build Coastguard Worker def handle_character_data(self, data): 111*61046927SAndroid Build Coastguard Worker if not self.character_data: 112*61046927SAndroid Build Coastguard Worker self.character_pos = self.pos() 113*61046927SAndroid Build Coastguard Worker self.character_data.append(data) 114*61046927SAndroid Build Coastguard Worker 115*61046927SAndroid Build Coastguard Worker def finish_character_data(self): 116*61046927SAndroid Build Coastguard Worker if self.character_data: 117*61046927SAndroid Build Coastguard Worker character_data = ''.join(self.character_data) 118*61046927SAndroid Build Coastguard Worker if not self.skip_ws or not character_data.isspace(): 119*61046927SAndroid Build Coastguard Worker line, column = self.character_pos 120*61046927SAndroid Build Coastguard Worker token = XmlToken(CHARACTER_DATA, character_data, None, line, column) 121*61046927SAndroid Build Coastguard Worker self.tokens.append(token) 122*61046927SAndroid Build Coastguard Worker self.character_data = [] 123*61046927SAndroid Build Coastguard Worker 124*61046927SAndroid Build Coastguard Worker def next(self): 125*61046927SAndroid Build Coastguard Worker size = 16*1024 126*61046927SAndroid Build Coastguard Worker while self.index >= len(self.tokens) and not self.final: 127*61046927SAndroid Build Coastguard Worker self.tokens = [] 128*61046927SAndroid Build Coastguard Worker self.index = 0 129*61046927SAndroid Build Coastguard Worker data = self.fp.read(size) 130*61046927SAndroid Build Coastguard Worker self.final = len(data) < size 131*61046927SAndroid Build Coastguard Worker data = data.rstrip('\0') 132*61046927SAndroid Build Coastguard Worker try: 133*61046927SAndroid Build Coastguard Worker self.parser.Parse(data, self.final) 134*61046927SAndroid Build Coastguard Worker except xpat.ExpatError as e: 135*61046927SAndroid Build Coastguard Worker #if e.code == xpat.errors.XML_ERROR_NO_ELEMENTS: 136*61046927SAndroid Build Coastguard Worker if e.code == 3: 137*61046927SAndroid Build Coastguard Worker pass 138*61046927SAndroid Build Coastguard Worker else: 139*61046927SAndroid Build Coastguard Worker raise e 140*61046927SAndroid Build Coastguard Worker if self.index >= len(self.tokens): 141*61046927SAndroid Build Coastguard Worker line, column = self.pos() 142*61046927SAndroid Build Coastguard Worker token = XmlToken(EOF, None, None, line, column) 143*61046927SAndroid Build Coastguard Worker else: 144*61046927SAndroid Build Coastguard Worker token = self.tokens[self.index] 145*61046927SAndroid Build Coastguard Worker self.index += 1 146*61046927SAndroid Build Coastguard Worker return token 147*61046927SAndroid Build Coastguard Worker 148*61046927SAndroid Build Coastguard Worker def pos(self): 149*61046927SAndroid Build Coastguard Worker return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber 150*61046927SAndroid Build Coastguard Worker 151*61046927SAndroid Build Coastguard Worker 152*61046927SAndroid Build Coastguard Workerclass TokenMismatch(Exception): 153*61046927SAndroid Build Coastguard Worker 154*61046927SAndroid Build Coastguard Worker def __init__(self, expected, found): 155*61046927SAndroid Build Coastguard Worker self.expected = expected 156*61046927SAndroid Build Coastguard Worker self.found = found 157*61046927SAndroid Build Coastguard Worker 158*61046927SAndroid Build Coastguard Worker def __str__(self): 159*61046927SAndroid Build Coastguard Worker return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) 160*61046927SAndroid Build Coastguard Worker 161*61046927SAndroid Build Coastguard Worker 162*61046927SAndroid Build Coastguard Worker 163*61046927SAndroid Build Coastguard Workerclass XmlParser: 164*61046927SAndroid Build Coastguard Worker """Base XML document parser.""" 165*61046927SAndroid Build Coastguard Worker 166*61046927SAndroid Build Coastguard Worker def __init__(self, fp): 167*61046927SAndroid Build Coastguard Worker self.tokenizer = XmlTokenizer(fp) 168*61046927SAndroid Build Coastguard Worker self.consume() 169*61046927SAndroid Build Coastguard Worker 170*61046927SAndroid Build Coastguard Worker def consume(self): 171*61046927SAndroid Build Coastguard Worker self.token = self.tokenizer.next() 172*61046927SAndroid Build Coastguard Worker 173*61046927SAndroid Build Coastguard Worker def match_element_start(self, name): 174*61046927SAndroid Build Coastguard Worker return self.token.type == ELEMENT_START and self.token.name_or_data == name 175*61046927SAndroid Build Coastguard Worker 176*61046927SAndroid Build Coastguard Worker def match_element_end(self, name): 177*61046927SAndroid Build Coastguard Worker return self.token.type == ELEMENT_END and self.token.name_or_data == name 178*61046927SAndroid Build Coastguard Worker 179*61046927SAndroid Build Coastguard Worker def element_start(self, name): 180*61046927SAndroid Build Coastguard Worker while self.token.type == CHARACTER_DATA: 181*61046927SAndroid Build Coastguard Worker self.consume() 182*61046927SAndroid Build Coastguard Worker if self.token.type != ELEMENT_START: 183*61046927SAndroid Build Coastguard Worker raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) 184*61046927SAndroid Build Coastguard Worker if self.token.name_or_data != name: 185*61046927SAndroid Build Coastguard Worker raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) 186*61046927SAndroid Build Coastguard Worker attrs = self.token.attrs 187*61046927SAndroid Build Coastguard Worker self.consume() 188*61046927SAndroid Build Coastguard Worker return attrs 189*61046927SAndroid Build Coastguard Worker 190*61046927SAndroid Build Coastguard Worker def element_end(self, name): 191*61046927SAndroid Build Coastguard Worker while self.token.type == CHARACTER_DATA: 192*61046927SAndroid Build Coastguard Worker self.consume() 193*61046927SAndroid Build Coastguard Worker if self.token.type != ELEMENT_END: 194*61046927SAndroid Build Coastguard Worker raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) 195*61046927SAndroid Build Coastguard Worker if self.token.name_or_data != name: 196*61046927SAndroid Build Coastguard Worker raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) 197*61046927SAndroid Build Coastguard Worker self.consume() 198*61046927SAndroid Build Coastguard Worker 199*61046927SAndroid Build Coastguard Worker def character_data(self, strip = True): 200*61046927SAndroid Build Coastguard Worker data = '' 201*61046927SAndroid Build Coastguard Worker while self.token.type == CHARACTER_DATA: 202*61046927SAndroid Build Coastguard Worker data += self.token.name_or_data 203*61046927SAndroid Build Coastguard Worker self.consume() 204*61046927SAndroid Build Coastguard Worker if strip: 205*61046927SAndroid Build Coastguard Worker data = data.strip() 206*61046927SAndroid Build Coastguard Worker return data 207*61046927SAndroid Build Coastguard Worker 208*61046927SAndroid Build Coastguard Worker 209*61046927SAndroid Build Coastguard Workerclass TraceParser(XmlParser): 210*61046927SAndroid Build Coastguard Worker 211*61046927SAndroid Build Coastguard Worker def __init__(self, fp, options, state): 212*61046927SAndroid Build Coastguard Worker XmlParser.__init__(self, fp) 213*61046927SAndroid Build Coastguard Worker self.last_call_no = 0 214*61046927SAndroid Build Coastguard Worker self.state = state 215*61046927SAndroid Build Coastguard Worker self.options = options 216*61046927SAndroid Build Coastguard Worker 217*61046927SAndroid Build Coastguard Worker def parse(self): 218*61046927SAndroid Build Coastguard Worker self.element_start('trace') 219*61046927SAndroid Build Coastguard Worker while self.token.type not in (ELEMENT_END, EOF): 220*61046927SAndroid Build Coastguard Worker call = self.parse_call() 221*61046927SAndroid Build Coastguard Worker call.is_junk = trace_call_ignore(call) 222*61046927SAndroid Build Coastguard Worker self.handle_call(call) 223*61046927SAndroid Build Coastguard Worker if self.token.type != EOF: 224*61046927SAndroid Build Coastguard Worker self.element_end('trace') 225*61046927SAndroid Build Coastguard Worker 226*61046927SAndroid Build Coastguard Worker def parse_call(self): 227*61046927SAndroid Build Coastguard Worker attrs = self.element_start('call') 228*61046927SAndroid Build Coastguard Worker try: 229*61046927SAndroid Build Coastguard Worker no = int(attrs['no']) 230*61046927SAndroid Build Coastguard Worker except KeyError as e: 231*61046927SAndroid Build Coastguard Worker self.last_call_no += 1 232*61046927SAndroid Build Coastguard Worker no = self.last_call_no 233*61046927SAndroid Build Coastguard Worker else: 234*61046927SAndroid Build Coastguard Worker self.last_call_no = no 235*61046927SAndroid Build Coastguard Worker klass = attrs['class'] 236*61046927SAndroid Build Coastguard Worker method = attrs['method'] 237*61046927SAndroid Build Coastguard Worker args = [] 238*61046927SAndroid Build Coastguard Worker ret = None 239*61046927SAndroid Build Coastguard Worker time = None 240*61046927SAndroid Build Coastguard Worker while self.token.type == ELEMENT_START: 241*61046927SAndroid Build Coastguard Worker if self.token.name_or_data == 'arg': 242*61046927SAndroid Build Coastguard Worker arg = self.parse_arg() 243*61046927SAndroid Build Coastguard Worker args.append(arg) 244*61046927SAndroid Build Coastguard Worker elif self.token.name_or_data == 'ret': 245*61046927SAndroid Build Coastguard Worker ret = self.parse_ret() 246*61046927SAndroid Build Coastguard Worker elif self.token.name_or_data == 'call': 247*61046927SAndroid Build Coastguard Worker # ignore nested function calls 248*61046927SAndroid Build Coastguard Worker self.parse_call() 249*61046927SAndroid Build Coastguard Worker elif self.token.name_or_data == 'time': 250*61046927SAndroid Build Coastguard Worker time = self.parse_time() 251*61046927SAndroid Build Coastguard Worker else: 252*61046927SAndroid Build Coastguard Worker raise TokenMismatch("<arg ...> or <ret ...>", self.token) 253*61046927SAndroid Build Coastguard Worker self.element_end('call') 254*61046927SAndroid Build Coastguard Worker 255*61046927SAndroid Build Coastguard Worker return Call(no, klass, method, args, ret, time) 256*61046927SAndroid Build Coastguard Worker 257*61046927SAndroid Build Coastguard Worker def parse_arg(self): 258*61046927SAndroid Build Coastguard Worker attrs = self.element_start('arg') 259*61046927SAndroid Build Coastguard Worker name = attrs['name'] 260*61046927SAndroid Build Coastguard Worker value = self.parse_value(name) 261*61046927SAndroid Build Coastguard Worker self.element_end('arg') 262*61046927SAndroid Build Coastguard Worker 263*61046927SAndroid Build Coastguard Worker return name, value 264*61046927SAndroid Build Coastguard Worker 265*61046927SAndroid Build Coastguard Worker def parse_ret(self): 266*61046927SAndroid Build Coastguard Worker attrs = self.element_start('ret') 267*61046927SAndroid Build Coastguard Worker value = self.parse_value('ret') 268*61046927SAndroid Build Coastguard Worker self.element_end('ret') 269*61046927SAndroid Build Coastguard Worker 270*61046927SAndroid Build Coastguard Worker return value 271*61046927SAndroid Build Coastguard Worker 272*61046927SAndroid Build Coastguard Worker def parse_time(self): 273*61046927SAndroid Build Coastguard Worker attrs = self.element_start('time') 274*61046927SAndroid Build Coastguard Worker time = self.parse_value('time'); 275*61046927SAndroid Build Coastguard Worker self.element_end('time') 276*61046927SAndroid Build Coastguard Worker return time 277*61046927SAndroid Build Coastguard Worker 278*61046927SAndroid Build Coastguard Worker def parse_value(self, name): 279*61046927SAndroid Build Coastguard Worker expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') 280*61046927SAndroid Build Coastguard Worker if self.token.type == ELEMENT_START: 281*61046927SAndroid Build Coastguard Worker if self.token.name_or_data in expected_tokens: 282*61046927SAndroid Build Coastguard Worker method = getattr(self, 'parse_' + self.token.name_or_data) 283*61046927SAndroid Build Coastguard Worker return method(name) 284*61046927SAndroid Build Coastguard Worker raise TokenMismatch(" or " .join(expected_tokens), self.token) 285*61046927SAndroid Build Coastguard Worker 286*61046927SAndroid Build Coastguard Worker def parse_null(self, pname): 287*61046927SAndroid Build Coastguard Worker self.element_start('null') 288*61046927SAndroid Build Coastguard Worker self.element_end('null') 289*61046927SAndroid Build Coastguard Worker return Literal(None) 290*61046927SAndroid Build Coastguard Worker 291*61046927SAndroid Build Coastguard Worker def parse_bool(self, pname): 292*61046927SAndroid Build Coastguard Worker self.element_start('bool') 293*61046927SAndroid Build Coastguard Worker value = int(self.character_data()) 294*61046927SAndroid Build Coastguard Worker self.element_end('bool') 295*61046927SAndroid Build Coastguard Worker return Literal(value) 296*61046927SAndroid Build Coastguard Worker 297*61046927SAndroid Build Coastguard Worker def parse_int(self, pname): 298*61046927SAndroid Build Coastguard Worker self.element_start('int') 299*61046927SAndroid Build Coastguard Worker value = int(self.character_data()) 300*61046927SAndroid Build Coastguard Worker self.element_end('int') 301*61046927SAndroid Build Coastguard Worker return Literal(value) 302*61046927SAndroid Build Coastguard Worker 303*61046927SAndroid Build Coastguard Worker def parse_uint(self, pname): 304*61046927SAndroid Build Coastguard Worker self.element_start('uint') 305*61046927SAndroid Build Coastguard Worker value = int(self.character_data()) 306*61046927SAndroid Build Coastguard Worker self.element_end('uint') 307*61046927SAndroid Build Coastguard Worker return Literal(value) 308*61046927SAndroid Build Coastguard Worker 309*61046927SAndroid Build Coastguard Worker def parse_float(self, pname): 310*61046927SAndroid Build Coastguard Worker self.element_start('float') 311*61046927SAndroid Build Coastguard Worker value = float(self.character_data()) 312*61046927SAndroid Build Coastguard Worker self.element_end('float') 313*61046927SAndroid Build Coastguard Worker return Literal(value) 314*61046927SAndroid Build Coastguard Worker 315*61046927SAndroid Build Coastguard Worker def parse_enum(self, pname): 316*61046927SAndroid Build Coastguard Worker self.element_start('enum') 317*61046927SAndroid Build Coastguard Worker name = self.character_data() 318*61046927SAndroid Build Coastguard Worker self.element_end('enum') 319*61046927SAndroid Build Coastguard Worker return NamedConstant(name) 320*61046927SAndroid Build Coastguard Worker 321*61046927SAndroid Build Coastguard Worker def parse_string(self, pname): 322*61046927SAndroid Build Coastguard Worker self.element_start('string') 323*61046927SAndroid Build Coastguard Worker value = self.character_data() 324*61046927SAndroid Build Coastguard Worker self.element_end('string') 325*61046927SAndroid Build Coastguard Worker return Literal(value) 326*61046927SAndroid Build Coastguard Worker 327*61046927SAndroid Build Coastguard Worker def parse_bytes(self, pname): 328*61046927SAndroid Build Coastguard Worker self.element_start('bytes') 329*61046927SAndroid Build Coastguard Worker value = self.character_data() 330*61046927SAndroid Build Coastguard Worker self.element_end('bytes') 331*61046927SAndroid Build Coastguard Worker return Blob(value) 332*61046927SAndroid Build Coastguard Worker 333*61046927SAndroid Build Coastguard Worker def parse_array(self, pname): 334*61046927SAndroid Build Coastguard Worker self.element_start('array') 335*61046927SAndroid Build Coastguard Worker elems = [] 336*61046927SAndroid Build Coastguard Worker while self.token.type != ELEMENT_END: 337*61046927SAndroid Build Coastguard Worker elems.append(self.parse_elem('array')) 338*61046927SAndroid Build Coastguard Worker self.element_end('array') 339*61046927SAndroid Build Coastguard Worker return Array(elems) 340*61046927SAndroid Build Coastguard Worker 341*61046927SAndroid Build Coastguard Worker def parse_elem(self, pname): 342*61046927SAndroid Build Coastguard Worker self.element_start('elem') 343*61046927SAndroid Build Coastguard Worker value = self.parse_value('elem') 344*61046927SAndroid Build Coastguard Worker self.element_end('elem') 345*61046927SAndroid Build Coastguard Worker return value 346*61046927SAndroid Build Coastguard Worker 347*61046927SAndroid Build Coastguard Worker def parse_struct(self, pname): 348*61046927SAndroid Build Coastguard Worker attrs = self.element_start('struct') 349*61046927SAndroid Build Coastguard Worker name = attrs['name'] 350*61046927SAndroid Build Coastguard Worker members = [] 351*61046927SAndroid Build Coastguard Worker while self.token.type != ELEMENT_END: 352*61046927SAndroid Build Coastguard Worker members.append(self.parse_member(name)) 353*61046927SAndroid Build Coastguard Worker self.element_end('struct') 354*61046927SAndroid Build Coastguard Worker return Struct(name, members) 355*61046927SAndroid Build Coastguard Worker 356*61046927SAndroid Build Coastguard Worker def parse_member(self, pname): 357*61046927SAndroid Build Coastguard Worker attrs = self.element_start('member') 358*61046927SAndroid Build Coastguard Worker name = attrs['name'] 359*61046927SAndroid Build Coastguard Worker value = self.parse_value(name) 360*61046927SAndroid Build Coastguard Worker self.element_end('member') 361*61046927SAndroid Build Coastguard Worker 362*61046927SAndroid Build Coastguard Worker return name, value 363*61046927SAndroid Build Coastguard Worker 364*61046927SAndroid Build Coastguard Worker def parse_ptr(self, pname): 365*61046927SAndroid Build Coastguard Worker self.element_start('ptr') 366*61046927SAndroid Build Coastguard Worker address = self.character_data() 367*61046927SAndroid Build Coastguard Worker self.element_end('ptr') 368*61046927SAndroid Build Coastguard Worker 369*61046927SAndroid Build Coastguard Worker return Pointer(self.state, address, pname) 370*61046927SAndroid Build Coastguard Worker 371*61046927SAndroid Build Coastguard Worker def handle_call(self, call): 372*61046927SAndroid Build Coastguard Worker pass 373*61046927SAndroid Build Coastguard Worker 374*61046927SAndroid Build Coastguard Worker 375*61046927SAndroid Build Coastguard Workerclass SimpleTraceDumper(TraceParser): 376*61046927SAndroid Build Coastguard Worker 377*61046927SAndroid Build Coastguard Worker def __init__(self, fp, options, formatter, state): 378*61046927SAndroid Build Coastguard Worker TraceParser.__init__(self, fp, options, state) 379*61046927SAndroid Build Coastguard Worker self.options = options 380*61046927SAndroid Build Coastguard Worker self.formatter = formatter 381*61046927SAndroid Build Coastguard Worker self.pretty_printer = PrettyPrinter(self.formatter, options) 382*61046927SAndroid Build Coastguard Worker 383*61046927SAndroid Build Coastguard Worker def handle_call(self, call): 384*61046927SAndroid Build Coastguard Worker if self.options.ignore_junk and call.is_junk: 385*61046927SAndroid Build Coastguard Worker return 386*61046927SAndroid Build Coastguard Worker 387*61046927SAndroid Build Coastguard Worker call.visit(self.pretty_printer) 388*61046927SAndroid Build Coastguard Worker 389*61046927SAndroid Build Coastguard Worker 390*61046927SAndroid Build Coastguard Workerclass TraceDumper(SimpleTraceDumper): 391*61046927SAndroid Build Coastguard Worker 392*61046927SAndroid Build Coastguard Worker def __init__(self, fp, options, formatter, state): 393*61046927SAndroid Build Coastguard Worker SimpleTraceDumper.__init__(self, fp, options, formatter, state) 394*61046927SAndroid Build Coastguard Worker self.call_stack = [] 395*61046927SAndroid Build Coastguard Worker 396*61046927SAndroid Build Coastguard Worker def handle_call(self, call): 397*61046927SAndroid Build Coastguard Worker if self.options.ignore_junk and call.is_junk: 398*61046927SAndroid Build Coastguard Worker return 399*61046927SAndroid Build Coastguard Worker 400*61046927SAndroid Build Coastguard Worker if self.options.named_ptrs: 401*61046927SAndroid Build Coastguard Worker self.call_stack.append(call) 402*61046927SAndroid Build Coastguard Worker else: 403*61046927SAndroid Build Coastguard Worker call.visit(self.pretty_printer) 404*61046927SAndroid Build Coastguard Worker 405*61046927SAndroid Build Coastguard Worker 406*61046927SAndroid Build Coastguard Workerclass ParseOptions(ModelOptions): 407*61046927SAndroid Build Coastguard Worker 408*61046927SAndroid Build Coastguard Worker def __init__(self, args=None): 409*61046927SAndroid Build Coastguard Worker # Initialize options local to this module 410*61046927SAndroid Build Coastguard Worker self.plain = False 411*61046927SAndroid Build Coastguard Worker self.ignore_junk = False 412*61046927SAndroid Build Coastguard Worker 413*61046927SAndroid Build Coastguard Worker ModelOptions.__init__(self, args) 414*61046927SAndroid Build Coastguard Worker 415*61046927SAndroid Build Coastguard Worker 416*61046927SAndroid Build Coastguard Workerclass Main: 417*61046927SAndroid Build Coastguard Worker '''Common main class for all retrace command line utilities.''' 418*61046927SAndroid Build Coastguard Worker 419*61046927SAndroid Build Coastguard Worker def __init__(self): 420*61046927SAndroid Build Coastguard Worker pass 421*61046927SAndroid Build Coastguard Worker 422*61046927SAndroid Build Coastguard Worker def main(self): 423*61046927SAndroid Build Coastguard Worker optparser = self.get_optparser() 424*61046927SAndroid Build Coastguard Worker args = optparser.parse_args() 425*61046927SAndroid Build Coastguard Worker options = self.make_options(args) 426*61046927SAndroid Build Coastguard Worker 427*61046927SAndroid Build Coastguard Worker for fname in args.filename: 428*61046927SAndroid Build Coastguard Worker try: 429*61046927SAndroid Build Coastguard Worker if fname.endswith('.gz'): 430*61046927SAndroid Build Coastguard Worker from gzip import GzipFile 431*61046927SAndroid Build Coastguard Worker stream = io.TextIOWrapper(GzipFile(fname, 'rb')) 432*61046927SAndroid Build Coastguard Worker elif fname.endswith('.bz2'): 433*61046927SAndroid Build Coastguard Worker from bz2 import BZ2File 434*61046927SAndroid Build Coastguard Worker stream = io.TextIOWrapper(BZ2File(fname, 'rb')) 435*61046927SAndroid Build Coastguard Worker else: 436*61046927SAndroid Build Coastguard Worker stream = open(fname, 'rt') 437*61046927SAndroid Build Coastguard Worker except Exception as e: 438*61046927SAndroid Build Coastguard Worker print("ERROR: {}".format(str(e))) 439*61046927SAndroid Build Coastguard Worker sys.exit(1) 440*61046927SAndroid Build Coastguard Worker 441*61046927SAndroid Build Coastguard Worker self.process_arg(stream, options) 442*61046927SAndroid Build Coastguard Worker 443*61046927SAndroid Build Coastguard Worker def make_options(self, args): 444*61046927SAndroid Build Coastguard Worker return ParseOptions(args) 445*61046927SAndroid Build Coastguard Worker 446*61046927SAndroid Build Coastguard Worker def get_optparser(self): 447*61046927SAndroid Build Coastguard Worker estr = "\nList of junk calls:\n" 448*61046927SAndroid Build Coastguard Worker for klass, call in sorted(trace_ignore_calls): 449*61046927SAndroid Build Coastguard Worker estr += f" {klass}::{call}\n" 450*61046927SAndroid Build Coastguard Worker 451*61046927SAndroid Build Coastguard Worker optparser = argparse.ArgumentParser( 452*61046927SAndroid Build Coastguard Worker description="Parse and dump Gallium trace(s)", 453*61046927SAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 454*61046927SAndroid Build Coastguard Worker epilog=estr) 455*61046927SAndroid Build Coastguard Worker 456*61046927SAndroid Build Coastguard Worker optparser.add_argument("filename", action="extend", nargs="+", 457*61046927SAndroid Build Coastguard Worker type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)") 458*61046927SAndroid Build Coastguard Worker 459*61046927SAndroid Build Coastguard Worker optparser.add_argument("-p", "--plain", 460*61046927SAndroid Build Coastguard Worker action="store_const", const=True, default=False, 461*61046927SAndroid Build Coastguard Worker dest="plain", help="disable ANSI color etc. formatting") 462*61046927SAndroid Build Coastguard Worker 463*61046927SAndroid Build Coastguard Worker optparser.add_argument("-S", "--suppress", 464*61046927SAndroid Build Coastguard Worker action="store_const", const=True, default=False, 465*61046927SAndroid Build Coastguard Worker dest="suppress_variants", help="suppress some variants in output for better diffability") 466*61046927SAndroid Build Coastguard Worker 467*61046927SAndroid Build Coastguard Worker optparser.add_argument("-N", "--named", 468*61046927SAndroid Build Coastguard Worker action="store_const", const=True, default=False, 469*61046927SAndroid Build Coastguard Worker dest="named_ptrs", help="generate symbolic names for raw pointer values") 470*61046927SAndroid Build Coastguard Worker 471*61046927SAndroid Build Coastguard Worker optparser.add_argument("-M", "--method-only", 472*61046927SAndroid Build Coastguard Worker action="store_const", const=True, default=False, 473*61046927SAndroid Build Coastguard Worker dest="method_only", help="output only call names without arguments") 474*61046927SAndroid Build Coastguard Worker 475*61046927SAndroid Build Coastguard Worker optparser.add_argument("-I", "--ignore-junk", 476*61046927SAndroid Build Coastguard Worker action="store_const", const=True, default=False, 477*61046927SAndroid Build Coastguard Worker dest="ignore_junk", help="filter out/ignore junk calls (see below)") 478*61046927SAndroid Build Coastguard Worker 479*61046927SAndroid Build Coastguard Worker return optparser 480*61046927SAndroid Build Coastguard Worker 481*61046927SAndroid Build Coastguard Worker def process_arg(self, stream, options): 482*61046927SAndroid Build Coastguard Worker if options.plain: 483*61046927SAndroid Build Coastguard Worker formatter = format.Formatter(sys.stdout) 484*61046927SAndroid Build Coastguard Worker else: 485*61046927SAndroid Build Coastguard Worker formatter = format.DefaultFormatter(sys.stdout) 486*61046927SAndroid Build Coastguard Worker 487*61046927SAndroid Build Coastguard Worker dump = TraceDumper(stream, options, formatter, TraceStateData()) 488*61046927SAndroid Build Coastguard Worker dump.parse() 489*61046927SAndroid Build Coastguard Worker 490*61046927SAndroid Build Coastguard Worker if options.named_ptrs: 491*61046927SAndroid Build Coastguard Worker for call in dump.call_stack: 492*61046927SAndroid Build Coastguard Worker call.visit(dump.pretty_printer) 493*61046927SAndroid Build Coastguard Worker 494*61046927SAndroid Build Coastguard Worker 495*61046927SAndroid Build Coastguard Workerif __name__ == '__main__': 496*61046927SAndroid Build Coastguard Worker Main().main() 497