1#!/usr/bin/env python2 2########################################################################## 3# 4# Copyright 2008 VMware, Inc. 5# All Rights Reserved. 6# 7# Permission is hereby granted, free of charge, to any person obtaining a 8# copy of this software and associated documentation files (the 9# "Software"), to deal in the Software without restriction, including 10# without limitation the rights to use, copy, modify, merge, publish, 11# distribute, sub license, and/or sell copies of the Software, and to 12# permit persons to whom the Software is furnished to do so, subject to 13# the following conditions: 14# 15# The above copyright notice and this permission notice (including the 16# next paragraph) shall be included in all copies or substantial portions 17# of the Software. 18# 19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22# IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26# 27########################################################################## 28 29 30'''Trace data model.''' 31 32 33import sys 34import string 35import binascii 36 37try: 38 from cStringIO import StringIO 39except ImportError: 40 from StringIO import StringIO 41 42import format 43 44 45class Node: 46 47 def visit(self, visitor): 48 raise NotImplementedError 49 50 def __str__(self): 51 stream = StringIO() 52 formatter = format.DefaultFormatter(stream) 53 pretty_printer = PrettyPrinter(formatter) 54 self.visit(pretty_printer) 55 return stream.getvalue() 56 57 58class Literal(Node): 59 60 def __init__(self, value): 61 self.value = value 62 63 def visit(self, visitor): 64 visitor.visit_literal(self) 65 66 67class Blob(Node): 68 69 def __init__(self, value): 70 self._rawValue = None 71 self._hexValue = value 72 73 def getValue(self): 74 if self._rawValue is None: 75 self._rawValue = binascii.a2b_hex(self._hexValue) 76 self._hexValue = None 77 return self._rawValue 78 79 def visit(self, visitor): 80 visitor.visit_blob(self) 81 82 83class NamedConstant(Node): 84 85 def __init__(self, name): 86 self.name = name 87 88 def visit(self, visitor): 89 visitor.visit_named_constant(self) 90 91 92class Array(Node): 93 94 def __init__(self, elements): 95 self.elements = elements 96 97 def visit(self, visitor): 98 visitor.visit_array(self) 99 100 101class Struct(Node): 102 103 def __init__(self, name, members): 104 self.name = name 105 self.members = members 106 107 def visit(self, visitor): 108 visitor.visit_struct(self) 109 110 111class Pointer(Node): 112 113 def __init__(self, address): 114 self.address = address 115 116 def visit(self, visitor): 117 visitor.visit_pointer(self) 118 119 120class Call: 121 122 def __init__(self, no, klass, method, args, ret, time): 123 self.no = no 124 self.klass = klass 125 self.method = method 126 self.args = args 127 self.ret = ret 128 self.time = time 129 130 def visit(self, visitor): 131 visitor.visit_call(self) 132 133 134class Trace: 135 136 def __init__(self, calls): 137 self.calls = calls 138 139 def visit(self, visitor): 140 visitor.visit_trace(self) 141 142 143class Visitor: 144 145 def visit_literal(self, node): 146 raise NotImplementedError 147 148 def visit_blob(self, node): 149 raise NotImplementedError 150 151 def visit_named_constant(self, node): 152 raise NotImplementedError 153 154 def visit_array(self, node): 155 raise NotImplementedError 156 157 def visit_struct(self, node): 158 raise NotImplementedError 159 160 def visit_pointer(self, node): 161 raise NotImplementedError 162 163 def visit_call(self, node): 164 raise NotImplementedError 165 166 def visit_trace(self, node): 167 raise NotImplementedError 168 169 170class PrettyPrinter: 171 172 def __init__(self, formatter): 173 self.formatter = formatter 174 175 def visit_literal(self, node): 176 if node.value is None: 177 self.formatter.literal('NULL') 178 return 179 180 if isinstance(node.value, basestring): 181 self.formatter.literal('"' + node.value + '"') 182 return 183 184 self.formatter.literal(repr(node.value)) 185 186 def visit_blob(self, node): 187 self.formatter.address('blob()') 188 189 def visit_named_constant(self, node): 190 self.formatter.literal(node.name) 191 192 def visit_array(self, node): 193 self.formatter.text('{') 194 sep = '' 195 for value in node.elements: 196 self.formatter.text(sep) 197 value.visit(self) 198 sep = ', ' 199 self.formatter.text('}') 200 201 def visit_struct(self, node): 202 self.formatter.text('{') 203 sep = '' 204 for name, value in node.members: 205 self.formatter.text(sep) 206 self.formatter.variable(name) 207 self.formatter.text(' = ') 208 value.visit(self) 209 sep = ', ' 210 self.formatter.text('}') 211 212 def visit_pointer(self, node): 213 self.formatter.address(node.address) 214 215 def visit_call(self, node): 216 self.formatter.text('%s ' % node.no) 217 if node.klass is not None: 218 self.formatter.function(node.klass + '::' + node.method) 219 else: 220 self.formatter.function(node.method) 221 self.formatter.text('(') 222 sep = '' 223 for name, value in node.args: 224 self.formatter.text(sep) 225 self.formatter.variable(name) 226 self.formatter.text(' = ') 227 value.visit(self) 228 sep = ', ' 229 self.formatter.text(')') 230 if node.ret is not None: 231 self.formatter.text(' = ') 232 node.ret.visit(self) 233 if node.time is not None: 234 self.formatter.text(' // time ') 235 node.time.visit(self) 236 237 def visit_trace(self, node): 238 for call in node.calls: 239 call.visit(self) 240 self.formatter.newline() 241 242