1bf215546Sopenharmony_ci#!/usr/bin/env python3 2bf215546Sopenharmony_ci########################################################################## 3bf215546Sopenharmony_ci# 4bf215546Sopenharmony_ci# Copyright 2008 VMware, Inc. 5bf215546Sopenharmony_ci# All Rights Reserved. 6bf215546Sopenharmony_ci# 7bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci# copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci# "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci# without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci# distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci# permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci# the following conditions: 14bf215546Sopenharmony_ci# 15bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci# next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci# of the Software. 18bf215546Sopenharmony_ci# 19bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci# 27bf215546Sopenharmony_ci########################################################################## 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci'''Trace data model.''' 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ciimport sys 34bf215546Sopenharmony_ciimport string 35bf215546Sopenharmony_ciimport binascii 36bf215546Sopenharmony_cifrom io import StringIO 37bf215546Sopenharmony_ciimport format 38bf215546Sopenharmony_ci 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ciclass ModelOptions: 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci def __init__(self, args=None): 43bf215546Sopenharmony_ci # Initialize the options we need to exist, 44bf215546Sopenharmony_ci # with some reasonable defaults 45bf215546Sopenharmony_ci self.plain = False 46bf215546Sopenharmony_ci self.suppress_variants = False 47bf215546Sopenharmony_ci self.named_ptrs = False 48bf215546Sopenharmony_ci self.method_only = False 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_ci # If args is specified, we assume it is the result object 51bf215546Sopenharmony_ci # from ArgumentParser.parse_args(). Copy the attribute values 52bf215546Sopenharmony_ci # we have from it, if they exist. 53bf215546Sopenharmony_ci if args is not None: 54bf215546Sopenharmony_ci for var in self.__dict__: 55bf215546Sopenharmony_ci if var in args.__dict__: 56bf215546Sopenharmony_ci self.__dict__[var] = args.__dict__[var] 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ciclass TraceStateData: 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci def __init__(self): 62bf215546Sopenharmony_ci self.ptr_list = {} 63bf215546Sopenharmony_ci self.ptr_type_list = {} 64bf215546Sopenharmony_ci self.ptr_types_list = {} 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ciclass Node: 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci def visit(self, visitor): 70bf215546Sopenharmony_ci raise NotImplementedError 71bf215546Sopenharmony_ci 72bf215546Sopenharmony_ci def __str__(self): 73bf215546Sopenharmony_ci stream = StringIO() 74bf215546Sopenharmony_ci formatter = format.Formatter(stream) 75bf215546Sopenharmony_ci pretty_printer = PrettyPrinter(formatter, {}) 76bf215546Sopenharmony_ci self.visit(pretty_printer) 77bf215546Sopenharmony_ci return stream.getvalue() 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci def __hash__(self): 80bf215546Sopenharmony_ci raise NotImplementedError 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci 83bf215546Sopenharmony_ciclass Literal(Node): 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci def __init__(self, value): 86bf215546Sopenharmony_ci self.value = value 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci def visit(self, visitor): 89bf215546Sopenharmony_ci visitor.visit_literal(self) 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci def __hash__(self): 92bf215546Sopenharmony_ci return hash(self.value) 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ciclass Blob(Node): 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci def __init__(self, value): 98bf215546Sopenharmony_ci self.value = binascii.a2b_hex(value) 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci def getValue(self): 101bf215546Sopenharmony_ci return self.value 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci def visit(self, visitor): 104bf215546Sopenharmony_ci visitor.visit_blob(self) 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci def __hash__(self): 107bf215546Sopenharmony_ci return hash(self.value) 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ciclass NamedConstant(Node): 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci def __init__(self, name): 113bf215546Sopenharmony_ci self.name = name 114bf215546Sopenharmony_ci 115bf215546Sopenharmony_ci def visit(self, visitor): 116bf215546Sopenharmony_ci visitor.visit_named_constant(self) 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci def __hash__(self): 119bf215546Sopenharmony_ci return hash(self.name) 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ciclass Array(Node): 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci def __init__(self, elements): 125bf215546Sopenharmony_ci self.elements = elements 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci def visit(self, visitor): 128bf215546Sopenharmony_ci visitor.visit_array(self) 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci def __hash__(self): 131bf215546Sopenharmony_ci tmp = 0 132bf215546Sopenharmony_ci for mobj in self.elements: 133bf215546Sopenharmony_ci tmp = tmp ^ hash(mobj) 134bf215546Sopenharmony_ci return tmp 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ciclass Struct(Node): 138bf215546Sopenharmony_ci 139bf215546Sopenharmony_ci def __init__(self, name, members): 140bf215546Sopenharmony_ci self.name = name 141bf215546Sopenharmony_ci self.members = members 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci def visit(self, visitor): 144bf215546Sopenharmony_ci visitor.visit_struct(self) 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci def __hash__(self): 147bf215546Sopenharmony_ci tmp = hash(self.name) 148bf215546Sopenharmony_ci for mname, mobj in self.members: 149bf215546Sopenharmony_ci tmp = tmp ^ hash(mname) ^ hash(mobj) 150bf215546Sopenharmony_ci return tmp 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ciclass Pointer(Node): 154bf215546Sopenharmony_ci 155bf215546Sopenharmony_ci ptr_ignore_list = ["ret", "elem"] 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci def __init__(self, state, address, pname): 158bf215546Sopenharmony_ci self.address = address 159bf215546Sopenharmony_ci self.state = state 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci # Check if address exists in list and if it is a return value address 162bf215546Sopenharmony_ci t1 = address in state.ptr_list 163bf215546Sopenharmony_ci if t1: 164bf215546Sopenharmony_ci rname = state.ptr_type_list[address] 165bf215546Sopenharmony_ci t2 = rname in self.ptr_ignore_list and pname not in self.ptr_ignore_list 166bf215546Sopenharmony_ci else: 167bf215546Sopenharmony_ci rname = pname 168bf215546Sopenharmony_ci t2 = False 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci # If address does NOT exist (add it), OR IS a ret value (update with new type) 171bf215546Sopenharmony_ci if not t1 or t2: 172bf215546Sopenharmony_ci # If previously set to ret value, remove one from count 173bf215546Sopenharmony_ci if t1 and t2: 174bf215546Sopenharmony_ci self.adjust_ptr_type_count(rname, -1) 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci # Add / update 177bf215546Sopenharmony_ci self.adjust_ptr_type_count(pname, 1) 178bf215546Sopenharmony_ci tmp = "{}_{}".format(pname, state.ptr_types_list[pname]) 179bf215546Sopenharmony_ci state.ptr_list[address] = tmp 180bf215546Sopenharmony_ci state.ptr_type_list[address] = pname 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci def adjust_ptr_type_count(self, pname, delta): 183bf215546Sopenharmony_ci if pname not in self.state.ptr_types_list: 184bf215546Sopenharmony_ci self.state.ptr_types_list[pname] = 0 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci self.state.ptr_types_list[pname] += delta 187bf215546Sopenharmony_ci 188bf215546Sopenharmony_ci def named_address(self): 189bf215546Sopenharmony_ci return self.state.ptr_list[self.address] 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci def visit(self, visitor): 192bf215546Sopenharmony_ci visitor.visit_pointer(self) 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci def __hash__(self): 195bf215546Sopenharmony_ci return hash(self.named_address()) 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ciclass Call: 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci def __init__(self, no, klass, method, args, ret, time): 201bf215546Sopenharmony_ci self.no = no 202bf215546Sopenharmony_ci self.klass = klass 203bf215546Sopenharmony_ci self.method = method 204bf215546Sopenharmony_ci self.args = args 205bf215546Sopenharmony_ci self.ret = ret 206bf215546Sopenharmony_ci self.time = time 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci # Calculate hashvalue "cached" into a variable 209bf215546Sopenharmony_ci self.hashvalue = hash(self.klass) ^ hash(self.method) 210bf215546Sopenharmony_ci for mname, mobj in self.args: 211bf215546Sopenharmony_ci self.hashvalue = self.hashvalue ^ hash(mname) ^ hash(mobj) 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci def visit(self, visitor): 214bf215546Sopenharmony_ci visitor.visit_call(self) 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci def __hash__(self): 217bf215546Sopenharmony_ci return self.hashvalue 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci def __eq__(self, other): 220bf215546Sopenharmony_ci return self.hashvalue == other.hashvalue 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ciclass Trace: 224bf215546Sopenharmony_ci 225bf215546Sopenharmony_ci def __init__(self, calls): 226bf215546Sopenharmony_ci self.calls = calls 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci def visit(self, visitor): 229bf215546Sopenharmony_ci visitor.visit_trace(self) 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ciclass Visitor: 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci def visit_literal(self, node): 235bf215546Sopenharmony_ci raise NotImplementedError 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci def visit_blob(self, node): 238bf215546Sopenharmony_ci raise NotImplementedError 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci def visit_named_constant(self, node): 241bf215546Sopenharmony_ci raise NotImplementedError 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci def visit_array(self, node): 244bf215546Sopenharmony_ci raise NotImplementedError 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci def visit_struct(self, node): 247bf215546Sopenharmony_ci raise NotImplementedError 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_ci def visit_pointer(self, node): 250bf215546Sopenharmony_ci raise NotImplementedError 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci def visit_call(self, node): 253bf215546Sopenharmony_ci raise NotImplementedError 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci def visit_trace(self, node): 256bf215546Sopenharmony_ci raise NotImplementedError 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ciclass PrettyPrinter: 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci def __init__(self, formatter, options): 262bf215546Sopenharmony_ci self.formatter = formatter 263bf215546Sopenharmony_ci self.options = options 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci def visit_literal(self, node): 266bf215546Sopenharmony_ci if node.value is None: 267bf215546Sopenharmony_ci self.formatter.literal('NULL') 268bf215546Sopenharmony_ci return 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci if isinstance(node.value, str): 271bf215546Sopenharmony_ci self.formatter.literal('"' + node.value + '"') 272bf215546Sopenharmony_ci return 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci self.formatter.literal(repr(node.value)) 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci def visit_blob(self, node): 277bf215546Sopenharmony_ci self.formatter.address('blob()') 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci def visit_named_constant(self, node): 280bf215546Sopenharmony_ci self.formatter.literal(node.name) 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci def visit_array(self, node): 283bf215546Sopenharmony_ci self.formatter.text('{') 284bf215546Sopenharmony_ci sep = '' 285bf215546Sopenharmony_ci for value in node.elements: 286bf215546Sopenharmony_ci self.formatter.text(sep) 287bf215546Sopenharmony_ci value.visit(self) 288bf215546Sopenharmony_ci sep = ', ' 289bf215546Sopenharmony_ci self.formatter.text('}') 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci def visit_struct(self, node): 292bf215546Sopenharmony_ci self.formatter.text('{') 293bf215546Sopenharmony_ci sep = '' 294bf215546Sopenharmony_ci for name, value in node.members: 295bf215546Sopenharmony_ci self.formatter.text(sep) 296bf215546Sopenharmony_ci self.formatter.variable(name) 297bf215546Sopenharmony_ci self.formatter.text(' = ') 298bf215546Sopenharmony_ci value.visit(self) 299bf215546Sopenharmony_ci sep = ', ' 300bf215546Sopenharmony_ci self.formatter.text('}') 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci def visit_pointer(self, node): 303bf215546Sopenharmony_ci if self.options.named_ptrs: 304bf215546Sopenharmony_ci self.formatter.address(node.named_address()) 305bf215546Sopenharmony_ci else: 306bf215546Sopenharmony_ci self.formatter.address(node.address) 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci def visit_call(self, node): 309bf215546Sopenharmony_ci if not self.options.suppress_variants: 310bf215546Sopenharmony_ci self.formatter.text(f'{node.no} ') 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci if node.klass is not None: 313bf215546Sopenharmony_ci self.formatter.function(node.klass + '::' + node.method) 314bf215546Sopenharmony_ci else: 315bf215546Sopenharmony_ci self.formatter.function(node.method) 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci if not self.options.method_only: 318bf215546Sopenharmony_ci self.formatter.text('(') 319bf215546Sopenharmony_ci sep = '' 320bf215546Sopenharmony_ci for name, value in node.args: 321bf215546Sopenharmony_ci self.formatter.text(sep) 322bf215546Sopenharmony_ci self.formatter.variable(name) 323bf215546Sopenharmony_ci self.formatter.text(' = ') 324bf215546Sopenharmony_ci value.visit(self) 325bf215546Sopenharmony_ci sep = ', ' 326bf215546Sopenharmony_ci self.formatter.text(')') 327bf215546Sopenharmony_ci if node.ret is not None: 328bf215546Sopenharmony_ci self.formatter.text(' = ') 329bf215546Sopenharmony_ci node.ret.visit(self) 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci if not self.options.suppress_variants and node.time is not None: 332bf215546Sopenharmony_ci self.formatter.text(' // time ') 333bf215546Sopenharmony_ci node.time.visit(self) 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci self.formatter.newline() 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci def visit_trace(self, node): 338bf215546Sopenharmony_ci for call in node.calls: 339bf215546Sopenharmony_ci call.visit(self) 340bf215546Sopenharmony_ci 341