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 Worker'''Trace data model.''' 31*61046927SAndroid Build Coastguard Worker 32*61046927SAndroid Build Coastguard Worker 33*61046927SAndroid Build Coastguard Workerimport sys 34*61046927SAndroid Build Coastguard Workerimport string 35*61046927SAndroid Build Coastguard Workerimport binascii 36*61046927SAndroid Build Coastguard Workerfrom io import StringIO 37*61046927SAndroid Build Coastguard Workerimport format 38*61046927SAndroid Build Coastguard Worker 39*61046927SAndroid Build Coastguard Worker 40*61046927SAndroid Build Coastguard Workerclass ModelOptions: 41*61046927SAndroid Build Coastguard Worker 42*61046927SAndroid Build Coastguard Worker def __init__(self, args=None): 43*61046927SAndroid Build Coastguard Worker # Initialize the options we need to exist, 44*61046927SAndroid Build Coastguard Worker # with some reasonable defaults 45*61046927SAndroid Build Coastguard Worker self.plain = False 46*61046927SAndroid Build Coastguard Worker self.suppress_variants = False 47*61046927SAndroid Build Coastguard Worker self.named_ptrs = False 48*61046927SAndroid Build Coastguard Worker self.method_only = False 49*61046927SAndroid Build Coastguard Worker 50*61046927SAndroid Build Coastguard Worker # If args is specified, we assume it is the result object 51*61046927SAndroid Build Coastguard Worker # from ArgumentParser.parse_args(). Copy the attribute values 52*61046927SAndroid Build Coastguard Worker # we have from it, if they exist. 53*61046927SAndroid Build Coastguard Worker if args is not None: 54*61046927SAndroid Build Coastguard Worker for var in self.__dict__: 55*61046927SAndroid Build Coastguard Worker if var in args.__dict__: 56*61046927SAndroid Build Coastguard Worker self.__dict__[var] = args.__dict__[var] 57*61046927SAndroid Build Coastguard Worker 58*61046927SAndroid Build Coastguard Worker 59*61046927SAndroid Build Coastguard Workerclass TraceStateData: 60*61046927SAndroid Build Coastguard Worker 61*61046927SAndroid Build Coastguard Worker def __init__(self): 62*61046927SAndroid Build Coastguard Worker self.ptr_list = {} 63*61046927SAndroid Build Coastguard Worker self.ptr_type_list = {} 64*61046927SAndroid Build Coastguard Worker self.ptr_types_list = {} 65*61046927SAndroid Build Coastguard Worker 66*61046927SAndroid Build Coastguard Worker 67*61046927SAndroid Build Coastguard Workerclass Node: 68*61046927SAndroid Build Coastguard Worker 69*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 70*61046927SAndroid Build Coastguard Worker raise NotImplementedError 71*61046927SAndroid Build Coastguard Worker 72*61046927SAndroid Build Coastguard Worker def __str__(self): 73*61046927SAndroid Build Coastguard Worker stream = StringIO() 74*61046927SAndroid Build Coastguard Worker formatter = format.Formatter(stream) 75*61046927SAndroid Build Coastguard Worker pretty_printer = PrettyPrinter(formatter, {}) 76*61046927SAndroid Build Coastguard Worker self.visit(pretty_printer) 77*61046927SAndroid Build Coastguard Worker return stream.getvalue() 78*61046927SAndroid Build Coastguard Worker 79*61046927SAndroid Build Coastguard Worker def __hash__(self): 80*61046927SAndroid Build Coastguard Worker raise NotImplementedError 81*61046927SAndroid Build Coastguard Worker 82*61046927SAndroid Build Coastguard Worker 83*61046927SAndroid Build Coastguard Workerclass Literal(Node): 84*61046927SAndroid Build Coastguard Worker 85*61046927SAndroid Build Coastguard Worker def __init__(self, value): 86*61046927SAndroid Build Coastguard Worker self.value = value 87*61046927SAndroid Build Coastguard Worker 88*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 89*61046927SAndroid Build Coastguard Worker visitor.visit_literal(self) 90*61046927SAndroid Build Coastguard Worker 91*61046927SAndroid Build Coastguard Worker def __hash__(self): 92*61046927SAndroid Build Coastguard Worker return hash(self.value) 93*61046927SAndroid Build Coastguard Worker 94*61046927SAndroid Build Coastguard Worker 95*61046927SAndroid Build Coastguard Workerclass Blob(Node): 96*61046927SAndroid Build Coastguard Worker 97*61046927SAndroid Build Coastguard Worker def __init__(self, value): 98*61046927SAndroid Build Coastguard Worker self.value = binascii.a2b_hex(value) 99*61046927SAndroid Build Coastguard Worker 100*61046927SAndroid Build Coastguard Worker def getValue(self): 101*61046927SAndroid Build Coastguard Worker return self.value 102*61046927SAndroid Build Coastguard Worker 103*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 104*61046927SAndroid Build Coastguard Worker visitor.visit_blob(self) 105*61046927SAndroid Build Coastguard Worker 106*61046927SAndroid Build Coastguard Worker def __hash__(self): 107*61046927SAndroid Build Coastguard Worker return hash(self.value) 108*61046927SAndroid Build Coastguard Worker 109*61046927SAndroid Build Coastguard Worker 110*61046927SAndroid Build Coastguard Workerclass NamedConstant(Node): 111*61046927SAndroid Build Coastguard Worker 112*61046927SAndroid Build Coastguard Worker def __init__(self, name): 113*61046927SAndroid Build Coastguard Worker self.name = name 114*61046927SAndroid Build Coastguard Worker 115*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 116*61046927SAndroid Build Coastguard Worker visitor.visit_named_constant(self) 117*61046927SAndroid Build Coastguard Worker 118*61046927SAndroid Build Coastguard Worker def __hash__(self): 119*61046927SAndroid Build Coastguard Worker return hash(self.name) 120*61046927SAndroid Build Coastguard Worker 121*61046927SAndroid Build Coastguard Worker 122*61046927SAndroid Build Coastguard Workerclass Array(Node): 123*61046927SAndroid Build Coastguard Worker 124*61046927SAndroid Build Coastguard Worker def __init__(self, elements): 125*61046927SAndroid Build Coastguard Worker self.elements = elements 126*61046927SAndroid Build Coastguard Worker 127*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 128*61046927SAndroid Build Coastguard Worker visitor.visit_array(self) 129*61046927SAndroid Build Coastguard Worker 130*61046927SAndroid Build Coastguard Worker def __hash__(self): 131*61046927SAndroid Build Coastguard Worker tmp = 0 132*61046927SAndroid Build Coastguard Worker for mobj in self.elements: 133*61046927SAndroid Build Coastguard Worker tmp = tmp ^ hash(mobj) 134*61046927SAndroid Build Coastguard Worker return tmp 135*61046927SAndroid Build Coastguard Worker 136*61046927SAndroid Build Coastguard Worker 137*61046927SAndroid Build Coastguard Workerclass Struct(Node): 138*61046927SAndroid Build Coastguard Worker 139*61046927SAndroid Build Coastguard Worker def __init__(self, name, members): 140*61046927SAndroid Build Coastguard Worker self.name = name 141*61046927SAndroid Build Coastguard Worker self.members = members 142*61046927SAndroid Build Coastguard Worker 143*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 144*61046927SAndroid Build Coastguard Worker visitor.visit_struct(self) 145*61046927SAndroid Build Coastguard Worker 146*61046927SAndroid Build Coastguard Worker def __hash__(self): 147*61046927SAndroid Build Coastguard Worker tmp = hash(self.name) 148*61046927SAndroid Build Coastguard Worker for mname, mobj in self.members: 149*61046927SAndroid Build Coastguard Worker tmp = tmp ^ hash(mname) ^ hash(mobj) 150*61046927SAndroid Build Coastguard Worker return tmp 151*61046927SAndroid Build Coastguard Worker 152*61046927SAndroid Build Coastguard Worker 153*61046927SAndroid Build Coastguard Workerclass Pointer(Node): 154*61046927SAndroid Build Coastguard Worker 155*61046927SAndroid Build Coastguard Worker ptr_ignore_list = ["ret", "elem"] 156*61046927SAndroid Build Coastguard Worker 157*61046927SAndroid Build Coastguard Worker def __init__(self, state, address, pname): 158*61046927SAndroid Build Coastguard Worker self.address = address 159*61046927SAndroid Build Coastguard Worker self.state = state 160*61046927SAndroid Build Coastguard Worker 161*61046927SAndroid Build Coastguard Worker # Check if address exists in list and if it is a return value address 162*61046927SAndroid Build Coastguard Worker t1 = address in state.ptr_list 163*61046927SAndroid Build Coastguard Worker if t1: 164*61046927SAndroid Build Coastguard Worker rname = state.ptr_type_list[address] 165*61046927SAndroid Build Coastguard Worker t2 = rname in self.ptr_ignore_list and pname not in self.ptr_ignore_list 166*61046927SAndroid Build Coastguard Worker else: 167*61046927SAndroid Build Coastguard Worker rname = pname 168*61046927SAndroid Build Coastguard Worker t2 = False 169*61046927SAndroid Build Coastguard Worker 170*61046927SAndroid Build Coastguard Worker # If address does NOT exist (add it), OR IS a ret value (update with new type) 171*61046927SAndroid Build Coastguard Worker if not t1 or t2: 172*61046927SAndroid Build Coastguard Worker # If previously set to ret value, remove one from count 173*61046927SAndroid Build Coastguard Worker if t1 and t2: 174*61046927SAndroid Build Coastguard Worker self.adjust_ptr_type_count(rname, -1) 175*61046927SAndroid Build Coastguard Worker 176*61046927SAndroid Build Coastguard Worker # Add / update 177*61046927SAndroid Build Coastguard Worker self.adjust_ptr_type_count(pname, 1) 178*61046927SAndroid Build Coastguard Worker tmp = "{}_{}".format(pname, state.ptr_types_list[pname]) 179*61046927SAndroid Build Coastguard Worker state.ptr_list[address] = tmp 180*61046927SAndroid Build Coastguard Worker state.ptr_type_list[address] = pname 181*61046927SAndroid Build Coastguard Worker 182*61046927SAndroid Build Coastguard Worker def adjust_ptr_type_count(self, pname, delta): 183*61046927SAndroid Build Coastguard Worker if pname not in self.state.ptr_types_list: 184*61046927SAndroid Build Coastguard Worker self.state.ptr_types_list[pname] = 0 185*61046927SAndroid Build Coastguard Worker 186*61046927SAndroid Build Coastguard Worker self.state.ptr_types_list[pname] += delta 187*61046927SAndroid Build Coastguard Worker 188*61046927SAndroid Build Coastguard Worker def named_address(self): 189*61046927SAndroid Build Coastguard Worker return self.state.ptr_list[self.address] 190*61046927SAndroid Build Coastguard Worker 191*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 192*61046927SAndroid Build Coastguard Worker visitor.visit_pointer(self) 193*61046927SAndroid Build Coastguard Worker 194*61046927SAndroid Build Coastguard Worker def __hash__(self): 195*61046927SAndroid Build Coastguard Worker return hash(self.named_address()) 196*61046927SAndroid Build Coastguard Worker 197*61046927SAndroid Build Coastguard Worker 198*61046927SAndroid Build Coastguard Workerclass Call: 199*61046927SAndroid Build Coastguard Worker 200*61046927SAndroid Build Coastguard Worker def __init__(self, no, klass, method, args, ret, time): 201*61046927SAndroid Build Coastguard Worker self.no = no 202*61046927SAndroid Build Coastguard Worker self.klass = klass 203*61046927SAndroid Build Coastguard Worker self.method = method 204*61046927SAndroid Build Coastguard Worker self.args = args 205*61046927SAndroid Build Coastguard Worker self.ret = ret 206*61046927SAndroid Build Coastguard Worker self.time = time 207*61046927SAndroid Build Coastguard Worker 208*61046927SAndroid Build Coastguard Worker # Calculate hashvalue "cached" into a variable 209*61046927SAndroid Build Coastguard Worker self.hashvalue = hash(self.klass) ^ hash(self.method) 210*61046927SAndroid Build Coastguard Worker for mname, mobj in self.args: 211*61046927SAndroid Build Coastguard Worker self.hashvalue = self.hashvalue ^ hash(mname) ^ hash(mobj) 212*61046927SAndroid Build Coastguard Worker 213*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 214*61046927SAndroid Build Coastguard Worker visitor.visit_call(self) 215*61046927SAndroid Build Coastguard Worker 216*61046927SAndroid Build Coastguard Worker def __hash__(self): 217*61046927SAndroid Build Coastguard Worker return self.hashvalue 218*61046927SAndroid Build Coastguard Worker 219*61046927SAndroid Build Coastguard Worker def __eq__(self, other): 220*61046927SAndroid Build Coastguard Worker return self.hashvalue == other.hashvalue 221*61046927SAndroid Build Coastguard Worker 222*61046927SAndroid Build Coastguard Worker 223*61046927SAndroid Build Coastguard Workerclass Trace: 224*61046927SAndroid Build Coastguard Worker 225*61046927SAndroid Build Coastguard Worker def __init__(self, calls): 226*61046927SAndroid Build Coastguard Worker self.calls = calls 227*61046927SAndroid Build Coastguard Worker 228*61046927SAndroid Build Coastguard Worker def visit(self, visitor): 229*61046927SAndroid Build Coastguard Worker visitor.visit_trace(self) 230*61046927SAndroid Build Coastguard Worker 231*61046927SAndroid Build Coastguard Worker 232*61046927SAndroid Build Coastguard Workerclass Visitor: 233*61046927SAndroid Build Coastguard Worker 234*61046927SAndroid Build Coastguard Worker def visit_literal(self, node): 235*61046927SAndroid Build Coastguard Worker raise NotImplementedError 236*61046927SAndroid Build Coastguard Worker 237*61046927SAndroid Build Coastguard Worker def visit_blob(self, node): 238*61046927SAndroid Build Coastguard Worker raise NotImplementedError 239*61046927SAndroid Build Coastguard Worker 240*61046927SAndroid Build Coastguard Worker def visit_named_constant(self, node): 241*61046927SAndroid Build Coastguard Worker raise NotImplementedError 242*61046927SAndroid Build Coastguard Worker 243*61046927SAndroid Build Coastguard Worker def visit_array(self, node): 244*61046927SAndroid Build Coastguard Worker raise NotImplementedError 245*61046927SAndroid Build Coastguard Worker 246*61046927SAndroid Build Coastguard Worker def visit_struct(self, node): 247*61046927SAndroid Build Coastguard Worker raise NotImplementedError 248*61046927SAndroid Build Coastguard Worker 249*61046927SAndroid Build Coastguard Worker def visit_pointer(self, node): 250*61046927SAndroid Build Coastguard Worker raise NotImplementedError 251*61046927SAndroid Build Coastguard Worker 252*61046927SAndroid Build Coastguard Worker def visit_call(self, node): 253*61046927SAndroid Build Coastguard Worker raise NotImplementedError 254*61046927SAndroid Build Coastguard Worker 255*61046927SAndroid Build Coastguard Worker def visit_trace(self, node): 256*61046927SAndroid Build Coastguard Worker raise NotImplementedError 257*61046927SAndroid Build Coastguard Worker 258*61046927SAndroid Build Coastguard Worker 259*61046927SAndroid Build Coastguard Workerclass PrettyPrinter: 260*61046927SAndroid Build Coastguard Worker 261*61046927SAndroid Build Coastguard Worker def __init__(self, formatter, options): 262*61046927SAndroid Build Coastguard Worker self.formatter = formatter 263*61046927SAndroid Build Coastguard Worker self.options = options 264*61046927SAndroid Build Coastguard Worker 265*61046927SAndroid Build Coastguard Worker def visit_literal(self, node): 266*61046927SAndroid Build Coastguard Worker if node.value is None: 267*61046927SAndroid Build Coastguard Worker self.formatter.literal('NULL') 268*61046927SAndroid Build Coastguard Worker return 269*61046927SAndroid Build Coastguard Worker 270*61046927SAndroid Build Coastguard Worker if isinstance(node.value, str): 271*61046927SAndroid Build Coastguard Worker self.formatter.literal('"' + node.value + '"') 272*61046927SAndroid Build Coastguard Worker return 273*61046927SAndroid Build Coastguard Worker 274*61046927SAndroid Build Coastguard Worker self.formatter.literal(repr(node.value)) 275*61046927SAndroid Build Coastguard Worker 276*61046927SAndroid Build Coastguard Worker def visit_blob(self, node): 277*61046927SAndroid Build Coastguard Worker self.formatter.address('blob()') 278*61046927SAndroid Build Coastguard Worker 279*61046927SAndroid Build Coastguard Worker def visit_named_constant(self, node): 280*61046927SAndroid Build Coastguard Worker self.formatter.literal(node.name) 281*61046927SAndroid Build Coastguard Worker 282*61046927SAndroid Build Coastguard Worker def visit_array(self, node): 283*61046927SAndroid Build Coastguard Worker self.formatter.text('{') 284*61046927SAndroid Build Coastguard Worker sep = '' 285*61046927SAndroid Build Coastguard Worker for value in node.elements: 286*61046927SAndroid Build Coastguard Worker self.formatter.text(sep) 287*61046927SAndroid Build Coastguard Worker value.visit(self) 288*61046927SAndroid Build Coastguard Worker sep = ', ' 289*61046927SAndroid Build Coastguard Worker self.formatter.text('}') 290*61046927SAndroid Build Coastguard Worker 291*61046927SAndroid Build Coastguard Worker def visit_struct(self, node): 292*61046927SAndroid Build Coastguard Worker self.formatter.text('{') 293*61046927SAndroid Build Coastguard Worker sep = '' 294*61046927SAndroid Build Coastguard Worker for name, value in node.members: 295*61046927SAndroid Build Coastguard Worker self.formatter.text(sep) 296*61046927SAndroid Build Coastguard Worker self.formatter.variable(name) 297*61046927SAndroid Build Coastguard Worker self.formatter.text(' = ') 298*61046927SAndroid Build Coastguard Worker value.visit(self) 299*61046927SAndroid Build Coastguard Worker sep = ', ' 300*61046927SAndroid Build Coastguard Worker self.formatter.text('}') 301*61046927SAndroid Build Coastguard Worker 302*61046927SAndroid Build Coastguard Worker def visit_pointer(self, node): 303*61046927SAndroid Build Coastguard Worker if self.options.named_ptrs: 304*61046927SAndroid Build Coastguard Worker self.formatter.address(node.named_address()) 305*61046927SAndroid Build Coastguard Worker else: 306*61046927SAndroid Build Coastguard Worker self.formatter.address(node.address) 307*61046927SAndroid Build Coastguard Worker 308*61046927SAndroid Build Coastguard Worker def visit_call(self, node): 309*61046927SAndroid Build Coastguard Worker if not self.options.suppress_variants: 310*61046927SAndroid Build Coastguard Worker self.formatter.text(f'{node.no} ') 311*61046927SAndroid Build Coastguard Worker 312*61046927SAndroid Build Coastguard Worker if node.klass is not None: 313*61046927SAndroid Build Coastguard Worker self.formatter.function(node.klass + '::' + node.method) 314*61046927SAndroid Build Coastguard Worker else: 315*61046927SAndroid Build Coastguard Worker self.formatter.function(node.method) 316*61046927SAndroid Build Coastguard Worker 317*61046927SAndroid Build Coastguard Worker if not self.options.method_only: 318*61046927SAndroid Build Coastguard Worker self.formatter.text('(') 319*61046927SAndroid Build Coastguard Worker sep = '' 320*61046927SAndroid Build Coastguard Worker for name, value in node.args: 321*61046927SAndroid Build Coastguard Worker self.formatter.text(sep) 322*61046927SAndroid Build Coastguard Worker self.formatter.variable(name) 323*61046927SAndroid Build Coastguard Worker self.formatter.text(' = ') 324*61046927SAndroid Build Coastguard Worker value.visit(self) 325*61046927SAndroid Build Coastguard Worker sep = ', ' 326*61046927SAndroid Build Coastguard Worker self.formatter.text(')') 327*61046927SAndroid Build Coastguard Worker if node.ret is not None: 328*61046927SAndroid Build Coastguard Worker self.formatter.text(' = ') 329*61046927SAndroid Build Coastguard Worker node.ret.visit(self) 330*61046927SAndroid Build Coastguard Worker 331*61046927SAndroid Build Coastguard Worker if not self.options.suppress_variants and node.time is not None: 332*61046927SAndroid Build Coastguard Worker self.formatter.text(' // time ') 333*61046927SAndroid Build Coastguard Worker node.time.visit(self) 334*61046927SAndroid Build Coastguard Worker 335*61046927SAndroid Build Coastguard Worker self.formatter.newline() 336*61046927SAndroid Build Coastguard Worker 337*61046927SAndroid Build Coastguard Worker def visit_trace(self, node): 338*61046927SAndroid Build Coastguard Worker for call in node.calls: 339*61046927SAndroid Build Coastguard Worker call.visit(self) 340*61046927SAndroid Build Coastguard Worker 341