1a1897c0cSGleb Kurtsou#!/usr/bin/env python 2a1897c0cSGleb Kurtsou#- 3a1897c0cSGleb Kurtsou# Copyright (c) 2010 Gleb Kurtsou 4a1897c0cSGleb Kurtsou# All rights reserved. 5a1897c0cSGleb Kurtsou# 6a1897c0cSGleb Kurtsou# Redistribution and use in source and binary forms, with or without 7a1897c0cSGleb Kurtsou# modification, are permitted provided that the following conditions 8a1897c0cSGleb Kurtsou# are met: 9a1897c0cSGleb Kurtsou# 1. Redistributions of source code must retain the above copyright 10a1897c0cSGleb Kurtsou# notice, this list of conditions and the following disclaimer. 11a1897c0cSGleb Kurtsou# 2. Redistributions in binary form must reproduce the above copyright 12a1897c0cSGleb Kurtsou# notice, this list of conditions and the following disclaimer in the 13a1897c0cSGleb Kurtsou# documentation and/or other materials provided with the distribution. 14a1897c0cSGleb Kurtsou# 15a1897c0cSGleb Kurtsou# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16a1897c0cSGleb Kurtsou# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17a1897c0cSGleb Kurtsou# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18a1897c0cSGleb Kurtsou# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19a1897c0cSGleb Kurtsou# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20a1897c0cSGleb Kurtsou# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21a1897c0cSGleb Kurtsou# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22a1897c0cSGleb Kurtsou# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23a1897c0cSGleb Kurtsou# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24a1897c0cSGleb Kurtsou# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25a1897c0cSGleb Kurtsou# SUCH DAMAGE. 26a1897c0cSGleb Kurtsou# 27a1897c0cSGleb Kurtsou 28749f65e3SCraig Rodriguesfrom __future__ import print_function 29a1897c0cSGleb Kurtsouimport os 30a1897c0cSGleb Kurtsouimport sys 31a1897c0cSGleb Kurtsouimport re 32a1897c0cSGleb Kurtsouimport optparse 33a1897c0cSGleb Kurtsou 34a1897c0cSGleb Kurtsouclass Config(object): 35a1897c0cSGleb Kurtsou version = '0.1' 36a1897c0cSGleb Kurtsou # controlled by user 37a1897c0cSGleb Kurtsou verbose = 0 38a1897c0cSGleb Kurtsou dump = False 39a1897c0cSGleb Kurtsou no_dump = False 40a1897c0cSGleb Kurtsou version_filter = None 41a1897c0cSGleb Kurtsou symbol_filter = None 42a1897c0cSGleb Kurtsou alias_prefixes = [] 43a1897c0cSGleb Kurtsou # misc opts 44a1897c0cSGleb Kurtsou objdump = 'objdump' 45a1897c0cSGleb Kurtsou dwarfdump = 'dwarfdump' 46a1897c0cSGleb Kurtsou # debug 47a1897c0cSGleb Kurtsou cmpcache_enabled = True 48a1897c0cSGleb Kurtsou dwarfcache_enabled = True 49a1897c0cSGleb Kurtsou w_alias = True 50a1897c0cSGleb Kurtsou w_cached = False 51a1897c0cSGleb Kurtsou w_symbol = True 52a1897c0cSGleb Kurtsou 53a1897c0cSGleb Kurtsou class FileConfig(object): 54a1897c0cSGleb Kurtsou filename = None 55a1897c0cSGleb Kurtsou out = sys.stdout 56a1897c0cSGleb Kurtsou def init(self, outname): 57a1897c0cSGleb Kurtsou if outname and outname != '-': 58a1897c0cSGleb Kurtsou self.out = open(outname, "w") 59a1897c0cSGleb Kurtsou 60a1897c0cSGleb Kurtsou origfile = FileConfig() 61a1897c0cSGleb Kurtsou newfile = FileConfig() 62a1897c0cSGleb Kurtsou 63c5f8185bSGleb Kurtsou exclude_sym_default = [ 64c5f8185bSGleb Kurtsou '^__bss_start$', 65c5f8185bSGleb Kurtsou '^_edata$', 66c5f8185bSGleb Kurtsou '^_end$', 67c5f8185bSGleb Kurtsou '^_fini$', 68c5f8185bSGleb Kurtsou '^_init$', 69c5f8185bSGleb Kurtsou ] 70c5f8185bSGleb Kurtsou 71a1897c0cSGleb Kurtsou @classmethod 72a1897c0cSGleb Kurtsou def init(cls): 73a1897c0cSGleb Kurtsou cls.version_filter = StrFilter() 74a1897c0cSGleb Kurtsou cls.symbol_filter = StrFilter() 75a1897c0cSGleb Kurtsou 76a1897c0cSGleb Kurtsouclass App(object): 77a1897c0cSGleb Kurtsou result_code = 0 78a1897c0cSGleb Kurtsou 79a1897c0cSGleb Kurtsoudef warn(cond, msg): 80a1897c0cSGleb Kurtsou if cond: 81749f65e3SCraig Rodrigues print("WARN: " + msg, file=sys.stderr) 82a1897c0cSGleb Kurtsou 83a1897c0cSGleb Kurtsou# {{{ misc 84a1897c0cSGleb Kurtsou 85a1897c0cSGleb Kurtsouclass StrFilter(object): 86a1897c0cSGleb Kurtsou def __init__(self): 87a1897c0cSGleb Kurtsou self.exclude = [] 88a1897c0cSGleb Kurtsou self.include = [] 89a1897c0cSGleb Kurtsou 90a1897c0cSGleb Kurtsou def compile(self): 91a1897c0cSGleb Kurtsou self.re_exclude = [ re.compile(x) for x in self.exclude ] 92a1897c0cSGleb Kurtsou self.re_include = [ re.compile(x) for x in self.include ] 93a1897c0cSGleb Kurtsou 94a1897c0cSGleb Kurtsou def match(self, s): 95a1897c0cSGleb Kurtsou if len(self.re_include): 96a1897c0cSGleb Kurtsou matched = False 97a1897c0cSGleb Kurtsou for r in self.re_include: 98a1897c0cSGleb Kurtsou if r.match(s): 99a1897c0cSGleb Kurtsou matched = True 100a1897c0cSGleb Kurtsou break 101a1897c0cSGleb Kurtsou if not matched: 102a1897c0cSGleb Kurtsou return False 103a1897c0cSGleb Kurtsou for r in self.re_exclude: 104a1897c0cSGleb Kurtsou if r.match(s): 105a1897c0cSGleb Kurtsou return False 106a1897c0cSGleb Kurtsou return True 107a1897c0cSGleb Kurtsou 108a1897c0cSGleb Kurtsouclass Cache(object): 109a1897c0cSGleb Kurtsou 110a1897c0cSGleb Kurtsou class CacheStats(object): 111a1897c0cSGleb Kurtsou def __init__(self): 112a1897c0cSGleb Kurtsou self.hit = 0 113a1897c0cSGleb Kurtsou self.miss = 0 114a1897c0cSGleb Kurtsou 115a1897c0cSGleb Kurtsou def show(self, name): 116a1897c0cSGleb Kurtsou total = self.hit + self.miss 117a1897c0cSGleb Kurtsou if total == 0: 118a1897c0cSGleb Kurtsou ratio = '(undef)' 119a1897c0cSGleb Kurtsou else: 120a1897c0cSGleb Kurtsou ratio = '%f' % (self.hit/float(total)) 121a1897c0cSGleb Kurtsou return '%s cache stats: hit: %d; miss: %d; ratio: %s' % \ 122a1897c0cSGleb Kurtsou (name, self.hit, self.miss, ratio) 123a1897c0cSGleb Kurtsou 124a1897c0cSGleb Kurtsou def __init__(self, enabled=True, stats=None): 125a1897c0cSGleb Kurtsou self.enabled = enabled 126a1897c0cSGleb Kurtsou self.items = {} 127a1897c0cSGleb Kurtsou if stats == None: 128a1897c0cSGleb Kurtsou self.stats = Cache.CacheStats() 129a1897c0cSGleb Kurtsou else: 130a1897c0cSGleb Kurtsou self.stats = stats 131a1897c0cSGleb Kurtsou 132a1897c0cSGleb Kurtsou def get(self, id): 133aef675d8SCraig Rodrigues if self.enabled and id in self.items: 134a1897c0cSGleb Kurtsou self.stats.hit += 1 135a1897c0cSGleb Kurtsou return self.items[id] 136a1897c0cSGleb Kurtsou else: 137a1897c0cSGleb Kurtsou self.stats.miss += 1 138a1897c0cSGleb Kurtsou return None 139a1897c0cSGleb Kurtsou 140a1897c0cSGleb Kurtsou def put(self, id, obj): 141a1897c0cSGleb Kurtsou if self.enabled: 142aef675d8SCraig Rodrigues if id in self.items and obj is not self.items[id]: 143a1897c0cSGleb Kurtsou #raise ValueError("Item is already cached: %d (%s, %s)" % 144a1897c0cSGleb Kurtsou # (id, self.items[id], obj)) 145a1897c0cSGleb Kurtsou warn(Config.w_cached, "Item is already cached: %d (%s, %s)" % \ 146a1897c0cSGleb Kurtsou (id, self.items[id], obj)) 147a1897c0cSGleb Kurtsou self.items[id] = obj 148a1897c0cSGleb Kurtsou 149a1897c0cSGleb Kurtsou def replace(self, id, obj): 150a1897c0cSGleb Kurtsou if self.enabled: 151aef675d8SCraig Rodrigues assert id in self.items 152a1897c0cSGleb Kurtsou self.items[id] = obj 153a1897c0cSGleb Kurtsou 154a1897c0cSGleb Kurtsouclass ListDiff(object): 155a1897c0cSGleb Kurtsou def __init__(self, orig, new): 156a1897c0cSGleb Kurtsou self.orig = set(orig) 157a1897c0cSGleb Kurtsou self.new = set(new) 158a1897c0cSGleb Kurtsou self.common = self.orig & self.new 159a1897c0cSGleb Kurtsou self.added = self.new - self.common 160a1897c0cSGleb Kurtsou self.removed = self.orig - self.common 161a1897c0cSGleb Kurtsou 162a1897c0cSGleb Kurtsouclass PrettyPrinter(object): 163a1897c0cSGleb Kurtsou def __init__(self): 164a1897c0cSGleb Kurtsou self.stack = [] 165a1897c0cSGleb Kurtsou 166a1897c0cSGleb Kurtsou def run_nested(self, obj): 167a1897c0cSGleb Kurtsou ex = obj._pp_ex(self) 168a1897c0cSGleb Kurtsou self.stack.append(ex) 169a1897c0cSGleb Kurtsou 170a1897c0cSGleb Kurtsou def run(self, obj): 171a1897c0cSGleb Kurtsou self._result = obj._pp(self) 172a1897c0cSGleb Kurtsou return self._result 173a1897c0cSGleb Kurtsou 174a1897c0cSGleb Kurtsou def nested(self): 175a1897c0cSGleb Kurtsou return sorted(set(self.stack)) 176a1897c0cSGleb Kurtsou 177a1897c0cSGleb Kurtsou def result(self): 178a1897c0cSGleb Kurtsou return self._result; 179a1897c0cSGleb Kurtsou 180a1897c0cSGleb Kurtsou# }}} 181a1897c0cSGleb Kurtsou 182a1897c0cSGleb Kurtsou#{{{ symbols and version maps 183a1897c0cSGleb Kurtsou 184a1897c0cSGleb Kurtsouclass Symbol(object): 185a1897c0cSGleb Kurtsou def __init__(self, name, offset, version, lib): 186a1897c0cSGleb Kurtsou self.name = name 187a1897c0cSGleb Kurtsou self.offset = offset 188a1897c0cSGleb Kurtsou self.version = version 189a1897c0cSGleb Kurtsou self.lib = lib 190a1897c0cSGleb Kurtsou self.definition = None 191a1897c0cSGleb Kurtsou 192a1897c0cSGleb Kurtsou @property 193a1897c0cSGleb Kurtsou def name_ver(self): 194a1897c0cSGleb Kurtsou return self.name + '@' + self.version 195a1897c0cSGleb Kurtsou 196a1897c0cSGleb Kurtsou def __repr__(self): 197a1897c0cSGleb Kurtsou return "Symbol(%s, 0x%x, %s)" % (self.name, self.offset, self.version) 198a1897c0cSGleb Kurtsou 199a1897c0cSGleb Kurtsouclass CommonSymbol(object): 200a1897c0cSGleb Kurtsou def __init__(self, origsym, newsym): 201a1897c0cSGleb Kurtsou if origsym.name != newsym.name or origsym.version != newsym.version: 202a1897c0cSGleb Kurtsou raise RuntimeError("Symbols have different names: %s", 203a1897c0cSGleb Kurtsou [origsym, newsym]) 204a1897c0cSGleb Kurtsou self.origsym = origsym 205a1897c0cSGleb Kurtsou self.newsym = newsym 206a1897c0cSGleb Kurtsou self.name = newsym.name 207a1897c0cSGleb Kurtsou self.version = newsym.version 208a1897c0cSGleb Kurtsou 209a1897c0cSGleb Kurtsou def __repr__(self): 210a1897c0cSGleb Kurtsou return "CommonSymbol(%s, %s)" % (self.name, self.version) 211a1897c0cSGleb Kurtsou 212a1897c0cSGleb Kurtsouclass SymbolAlias(object): 213a1897c0cSGleb Kurtsou def __init__(self, alias, prefix, offset): 214a1897c0cSGleb Kurtsou assert alias.startswith(prefix) 215a1897c0cSGleb Kurtsou self.alias = alias 216a1897c0cSGleb Kurtsou self.name = alias[len(prefix):] 217a1897c0cSGleb Kurtsou self.offset = offset 218a1897c0cSGleb Kurtsou 219a1897c0cSGleb Kurtsou def __repr__(self): 220a1897c0cSGleb Kurtsou return "SymbolAlias(%s, 0x%x)" % (self.alias, self.offset) 221a1897c0cSGleb Kurtsou 222a1897c0cSGleb Kurtsou 223a1897c0cSGleb Kurtsouclass VersionMap(object): 224a1897c0cSGleb Kurtsou def __init__(self, name): 225a1897c0cSGleb Kurtsou self.name = name 226a1897c0cSGleb Kurtsou self.symbols = {} 227a1897c0cSGleb Kurtsou 228a1897c0cSGleb Kurtsou def append(self, symbol): 229aef675d8SCraig Rodrigues if (symbol.name in self.symbols): 230a1897c0cSGleb Kurtsou raise ValueError("Symbol is already defined %s@%s" % 231a1897c0cSGleb Kurtsou (symbol.name, self.name)) 232a1897c0cSGleb Kurtsou self.symbols[symbol.name] = symbol 233a1897c0cSGleb Kurtsou 234a1897c0cSGleb Kurtsou def names(self): 235a1897c0cSGleb Kurtsou return self.symbols.keys() 236a1897c0cSGleb Kurtsou 237a1897c0cSGleb Kurtsou def __repr__(self): 238a1897c0cSGleb Kurtsou return repr(self.symbols.values()) 239a1897c0cSGleb Kurtsou 240a1897c0cSGleb Kurtsou# }}} 241a1897c0cSGleb Kurtsou 242a1897c0cSGleb Kurtsou# {{{ types and definitions 243a1897c0cSGleb Kurtsou 244a1897c0cSGleb Kurtsouclass Def(object): 245a1897c0cSGleb Kurtsou _is_alias = False 246a1897c0cSGleb Kurtsou 247a1897c0cSGleb Kurtsou def __init__(self, id, name, **kwargs): 248a1897c0cSGleb Kurtsou self.id = id 249a1897c0cSGleb Kurtsou self.name = name 250a1897c0cSGleb Kurtsou self.attrs = kwargs 251a1897c0cSGleb Kurtsou 252a1897c0cSGleb Kurtsou def __getattr__(self, attr): 253aef675d8SCraig Rodrigues if attr not in self.attrs: 254a1897c0cSGleb Kurtsou raise AttributeError('%s in %s' % (attr, str(self))) 255a1897c0cSGleb Kurtsou return self.attrs[attr] 256a1897c0cSGleb Kurtsou 257a1897c0cSGleb Kurtsou def _name_opt(self, default=''): 258a1897c0cSGleb Kurtsou if not self.name: 259a1897c0cSGleb Kurtsou return default 260a1897c0cSGleb Kurtsou return self.name 261a1897c0cSGleb Kurtsou 262a1897c0cSGleb Kurtsou def _alias(self): 263a1897c0cSGleb Kurtsou if self._is_alias: 264a1897c0cSGleb Kurtsou return self.type._alias() 265a1897c0cSGleb Kurtsou return self 266a1897c0cSGleb Kurtsou 267a1897c0cSGleb Kurtsou def __cmp__(self, other): 268a1897c0cSGleb Kurtsou # TODO assert 'self' and 'other' belong to different libraries 269a1897c0cSGleb Kurtsou #print 'cmp defs: %s, %s' % (self, other) 270a1897c0cSGleb Kurtsou a = self._alias() 271a1897c0cSGleb Kurtsou try: 272a1897c0cSGleb Kurtsou b = other._alias() 273a1897c0cSGleb Kurtsou except AttributeError: 274a1897c0cSGleb Kurtsou return 1 275a1897c0cSGleb Kurtsou r = cmp(a.__class__, b.__class__) 276a1897c0cSGleb Kurtsou if r == 0: 277a1897c0cSGleb Kurtsou if a.id != 0 and b.id != 0: 278a1897c0cSGleb Kurtsou ind = (long(a.id) << 32) + b.id 279a1897c0cSGleb Kurtsou r = Dwarf.cmpcache.get(ind) 280a1897c0cSGleb Kurtsou if r != None: 281a1897c0cSGleb Kurtsou return r 282a1897c0cSGleb Kurtsou else: 283a1897c0cSGleb Kurtsou ind = 0 284a1897c0cSGleb Kurtsou r = cmp(a.attrs, b.attrs) 285a1897c0cSGleb Kurtsou if ind != 0: 286a1897c0cSGleb Kurtsou Dwarf.cmpcache.put(ind, r) 287a1897c0cSGleb Kurtsou else: 288a1897c0cSGleb Kurtsou r = 0 289a1897c0cSGleb Kurtsou #raise RuntimeError('Comparing different classes: %s, %s' % 290a1897c0cSGleb Kurtsou # (a.__class__.__name__, b.__class__.__name__)) 291a1897c0cSGleb Kurtsou return r 292a1897c0cSGleb Kurtsou 293a1897c0cSGleb Kurtsou def __repr__(self): 294a1897c0cSGleb Kurtsou p = [] 295a1897c0cSGleb Kurtsou if hasattr(self, 'name'): 296a1897c0cSGleb Kurtsou p.append("name=%s" % self.name) 297a1897c0cSGleb Kurtsou for (k, v) in self.attrs.items(): 298a1897c0cSGleb Kurtsou if isinstance(v, Def): 299a1897c0cSGleb Kurtsou v = v.__class__.__name__ + '(...)' 300a1897c0cSGleb Kurtsou p.append("%s=%s" % (k, v)) 301a1897c0cSGleb Kurtsou return self.__class__.__name__ + '(' + ', '.join(p) + ')' 302a1897c0cSGleb Kurtsou 303a1897c0cSGleb Kurtsou def _mapval(self, param, vals): 304a1897c0cSGleb Kurtsou if param not in vals.keys(): 305a1897c0cSGleb Kurtsou raise NotImplementedError("Invalid value '%s': %s" % 306a1897c0cSGleb Kurtsou (param, str(self))) 307a1897c0cSGleb Kurtsou return vals[param] 308a1897c0cSGleb Kurtsou 309a1897c0cSGleb Kurtsou def _pp_ex(self, pp): 310a1897c0cSGleb Kurtsou raise NotImplementedError('Extended pretty print not implemeted: %s' % 311a1897c0cSGleb Kurtsou str(self)) 312a1897c0cSGleb Kurtsou 313a1897c0cSGleb Kurtsou def _pp(self, pp): 314a1897c0cSGleb Kurtsou raise NotImplementedError('Pretty print not implemeted: %s' % str(self)) 315a1897c0cSGleb Kurtsou 316a1897c0cSGleb Kurtsouclass AnonymousDef(Def): 317a1897c0cSGleb Kurtsou def __init__(self, id, **kwargs): 318a1897c0cSGleb Kurtsou Def.__init__(self, id, None, **kwargs) 319a1897c0cSGleb Kurtsou 320a1897c0cSGleb Kurtsouclass Void(AnonymousDef): 321a1897c0cSGleb Kurtsou _instance = None 322a1897c0cSGleb Kurtsou 323a1897c0cSGleb Kurtsou def __new__(cls, *args, **kwargs): 324a1897c0cSGleb Kurtsou if not cls._instance: 325a1897c0cSGleb Kurtsou cls._instance = super(Void, cls).__new__( 326a1897c0cSGleb Kurtsou cls, *args, **kwargs) 327a1897c0cSGleb Kurtsou return cls._instance 328a1897c0cSGleb Kurtsou 329a1897c0cSGleb Kurtsou def __init__(self): 330a1897c0cSGleb Kurtsou AnonymousDef.__init__(self, 0) 331a1897c0cSGleb Kurtsou 332a1897c0cSGleb Kurtsou def _pp(self, pp): 333a1897c0cSGleb Kurtsou return "void" 334a1897c0cSGleb Kurtsou 335a1897c0cSGleb Kurtsouclass VarArgs(AnonymousDef): 336a1897c0cSGleb Kurtsou def _pp(self, pp): 337a1897c0cSGleb Kurtsou return "..." 338a1897c0cSGleb Kurtsou 339a1897c0cSGleb Kurtsouclass PointerDef(AnonymousDef): 340a1897c0cSGleb Kurtsou def _pp(self, pp): 341a1897c0cSGleb Kurtsou t = pp.run(self.type) 342a1897c0cSGleb Kurtsou return "%s*" % (t,) 343a1897c0cSGleb Kurtsou 344a1897c0cSGleb Kurtsouclass BaseTypeDef(Def): 345a1897c0cSGleb Kurtsou inttypes = ['DW_ATE_signed', 'DW_ATE_unsigned', 'DW_ATE_unsigned_char'] 346a1897c0cSGleb Kurtsou def _pp(self, pp): 347a1897c0cSGleb Kurtsou if self.encoding in self.inttypes: 348a1897c0cSGleb Kurtsou sign = '' if self.encoding == 'DW_ATE_signed' else 'u' 349c5f8185bSGleb Kurtsou bits = int(self.byte_size, 0) * 8 350a1897c0cSGleb Kurtsou return '%sint%s_t' % (sign, bits) 351c5f8185bSGleb Kurtsou elif self.encoding == 'DW_ATE_signed_char' and int(self.byte_size, 0) == 1: 352a1897c0cSGleb Kurtsou return 'char'; 353c5f8185bSGleb Kurtsou elif self.encoding == 'DW_ATE_boolean' and int(self.byte_size, 0) == 1: 354c5f8185bSGleb Kurtsou return 'bool'; 355a1897c0cSGleb Kurtsou elif self.encoding == 'DW_ATE_float': 356c5f8185bSGleb Kurtsou return self._mapval(int(self.byte_size, 0), { 357c5f8185bSGleb Kurtsou 16: 'long double', 358c5f8185bSGleb Kurtsou 8: 'double', 359c5f8185bSGleb Kurtsou 4: 'float', 360a1897c0cSGleb Kurtsou }) 361a1897c0cSGleb Kurtsou raise NotImplementedError('Invalid encoding: %s' % self) 362a1897c0cSGleb Kurtsou 363a1897c0cSGleb Kurtsouclass TypeAliasDef(Def): 364a1897c0cSGleb Kurtsou _is_alias = True 365a1897c0cSGleb Kurtsou def _pp(self, pp): 366a1897c0cSGleb Kurtsou alias = self._alias() 367a1897c0cSGleb Kurtsou # push typedef name 368a1897c0cSGleb Kurtsou if self.name and not alias.name: 369a1897c0cSGleb Kurtsou alias.name = 'T(%s)' % self.name 370a1897c0cSGleb Kurtsou # return type with modifiers 371a1897c0cSGleb Kurtsou return self.type._pp(pp) 372a1897c0cSGleb Kurtsou 373a1897c0cSGleb Kurtsouclass EnumerationTypeDef(Def): 374a1897c0cSGleb Kurtsou def _pp(self, pp): 375a1897c0cSGleb Kurtsou return 'enum ' + self._name_opt('UNKNOWN') 376a1897c0cSGleb Kurtsou 377a1897c0cSGleb Kurtsouclass ConstTypeDef(AnonymousDef): 378a1897c0cSGleb Kurtsou _is_alias = True 379a1897c0cSGleb Kurtsou def _pp(self, pp): 380a1897c0cSGleb Kurtsou return 'const ' + self.type._pp(pp) 381a1897c0cSGleb Kurtsou 382a1897c0cSGleb Kurtsouclass VolatileTypeDef(AnonymousDef): 383a1897c0cSGleb Kurtsou _is_alias = True 384a1897c0cSGleb Kurtsou def _pp(self, pp): 385a1897c0cSGleb Kurtsou return 'volatile ' + self.type._pp(pp) 386a1897c0cSGleb Kurtsou 387c5f8185bSGleb Kurtsouclass RestrictTypeDef(AnonymousDef): 388c5f8185bSGleb Kurtsou _is_alias = True 389c5f8185bSGleb Kurtsou def _pp(self, pp): 390c5f8185bSGleb Kurtsou return 'restrict ' + self.type._pp(pp) 391c5f8185bSGleb Kurtsou 392a1897c0cSGleb Kurtsouclass ArrayDef(AnonymousDef): 393a1897c0cSGleb Kurtsou def _pp(self, pp): 394a1897c0cSGleb Kurtsou t = pp.run(self.type) 395a1897c0cSGleb Kurtsou assert len(self.subranges) == 1 396a1897c0cSGleb Kurtsou try: 397a1897c0cSGleb Kurtsou sz = int(self.subranges[0].upper_bound) + 1 398a1897c0cSGleb Kurtsou except ValueError: 399a1897c0cSGleb Kurtsou s = re.sub(r'\(.+\)', '', self.subranges[0].upper_bound) 400a1897c0cSGleb Kurtsou sz = int(s) + 1 401a1897c0cSGleb Kurtsou return '%s[%s]' % (t, sz) 402a1897c0cSGleb Kurtsou 403a1897c0cSGleb Kurtsouclass ArraySubrangeDef(AnonymousDef): 404a1897c0cSGleb Kurtsou pass 405a1897c0cSGleb Kurtsou 406a1897c0cSGleb Kurtsouclass FunctionDef(Def): 407a1897c0cSGleb Kurtsou def _pp(self, pp): 408a1897c0cSGleb Kurtsou result = pp.run(self.result) 409a1897c0cSGleb Kurtsou if not self.params: 410a1897c0cSGleb Kurtsou params = "void" 411a1897c0cSGleb Kurtsou else: 412a1897c0cSGleb Kurtsou params = ', '.join([ pp.run(x) for x in self.params ]) 413a1897c0cSGleb Kurtsou return "%s %s(%s);" % (result, self.name, params) 414a1897c0cSGleb Kurtsou 415a1897c0cSGleb Kurtsouclass FunctionTypeDef(Def): 416a1897c0cSGleb Kurtsou def _pp(self, pp): 417a1897c0cSGleb Kurtsou result = pp.run(self.result) 418a1897c0cSGleb Kurtsou if not self.params: 419a1897c0cSGleb Kurtsou params = "void" 420a1897c0cSGleb Kurtsou else: 421a1897c0cSGleb Kurtsou params = ', '.join([ pp.run(x) for x in self.params ]) 422a1897c0cSGleb Kurtsou return "F(%s, %s, (%s))" % (self._name_opt(), result, params) 423a1897c0cSGleb Kurtsou 424a1897c0cSGleb Kurtsouclass ParameterDef(Def): 425a1897c0cSGleb Kurtsou def _pp(self, pp): 426a1897c0cSGleb Kurtsou t = pp.run(self.type) 427a1897c0cSGleb Kurtsou return "%s %s" % (t, self._name_opt()) 428a1897c0cSGleb Kurtsou 429c5f8185bSGleb Kurtsouclass VariableDef(Def): 430c5f8185bSGleb Kurtsou def _pp(self, pp): 431c5f8185bSGleb Kurtsou t = pp.run(self.type) 432c5f8185bSGleb Kurtsou return "%s %s" % (t, self._name_opt()) 433c5f8185bSGleb Kurtsou 434a1897c0cSGleb Kurtsou# TODO 435a1897c0cSGleb Kurtsouclass StructForwardDef(Def): 436a1897c0cSGleb Kurtsou pass 437a1897c0cSGleb Kurtsou 438a1897c0cSGleb Kurtsouclass IncompleteDef(Def): 439a1897c0cSGleb Kurtsou def update(self, complete, cache=None): 440a1897c0cSGleb Kurtsou self.complete = complete 441a1897c0cSGleb Kurtsou complete.incomplete = self 442a1897c0cSGleb Kurtsou if cache != None: 443a1897c0cSGleb Kurtsou cached = cache.get(self.id) 444a1897c0cSGleb Kurtsou if cached != None and isinstance(cached, IncompleteDef): 445a1897c0cSGleb Kurtsou cache.replace(self.id, complete) 446a1897c0cSGleb Kurtsou 447a1897c0cSGleb Kurtsouclass StructIncompleteDef(IncompleteDef): 448a1897c0cSGleb Kurtsou def _pp(self, pp): 449a1897c0cSGleb Kurtsou return "struct %s" % (self.name,) 450a1897c0cSGleb Kurtsou 451a1897c0cSGleb Kurtsouclass UnionIncompleteDef(IncompleteDef): 452a1897c0cSGleb Kurtsou def _pp(self, pp): 453a1897c0cSGleb Kurtsou return "union %s" % (self.name,) 454a1897c0cSGleb Kurtsou 455a1897c0cSGleb Kurtsouclass StructDef(Def): 456a1897c0cSGleb Kurtsou def _pp_ex(self, pp, suffix=';'): 457a1897c0cSGleb Kurtsou members = [ pp.run(x) for x in self.members ] 458a1897c0cSGleb Kurtsou return "struct %s { %s }%s" % \ 459a1897c0cSGleb Kurtsou (self._name_opt(), ' '.join(members), suffix) 460a1897c0cSGleb Kurtsou def _pp(self, pp): 461a1897c0cSGleb Kurtsou if self.name: 462a1897c0cSGleb Kurtsou pp.run_nested(self) 463a1897c0cSGleb Kurtsou return "struct %s" % (self.name,) 464a1897c0cSGleb Kurtsou else: 465a1897c0cSGleb Kurtsou return self._pp_ex(pp, suffix='') 466a1897c0cSGleb Kurtsou 467a1897c0cSGleb Kurtsouclass UnionDef(Def): 468a1897c0cSGleb Kurtsou def _pp_ex(self, pp, suffix=';'): 469a1897c0cSGleb Kurtsou members = [ pp.run(x) for x in self.members ] 470a1897c0cSGleb Kurtsou return "union %s { %s }%s" % \ 471a1897c0cSGleb Kurtsou (self._name_opt(), ' '.join(members), suffix) 472a1897c0cSGleb Kurtsou def _pp(self, pp): 473a1897c0cSGleb Kurtsou if self.name: 474a1897c0cSGleb Kurtsou pp.run_nested(self) 475a1897c0cSGleb Kurtsou return "union %s" % (self.name,) 476a1897c0cSGleb Kurtsou else: 477a1897c0cSGleb Kurtsou return self._pp_ex(pp, suffix='') 478a1897c0cSGleb Kurtsou 479a1897c0cSGleb Kurtsouclass MemberDef(Def): 480a1897c0cSGleb Kurtsou def _pp(self, pp): 481a1897c0cSGleb Kurtsou t = pp.run(self.type) 482a1897c0cSGleb Kurtsou if self.bit_size: 483a1897c0cSGleb Kurtsou bits = ":%s" % self.bit_size 484a1897c0cSGleb Kurtsou else: 485a1897c0cSGleb Kurtsou bits = "" 486a1897c0cSGleb Kurtsou return "%s %s%s;" % (t, self._name_opt(), bits) 487a1897c0cSGleb Kurtsou 488a1897c0cSGleb Kurtsouclass Dwarf(object): 489a1897c0cSGleb Kurtsou 490a1897c0cSGleb Kurtsou cmpcache = Cache(enabled=Config.cmpcache_enabled) 491a1897c0cSGleb Kurtsou 492a1897c0cSGleb Kurtsou def __init__(self, dump): 493a1897c0cSGleb Kurtsou self.dump = dump 494a1897c0cSGleb Kurtsou 495a1897c0cSGleb Kurtsou def _build_optarg_type(self, praw): 496a1897c0cSGleb Kurtsou type = praw.optarg('type', Void()) 497a1897c0cSGleb Kurtsou if type != Void(): 498a1897c0cSGleb Kurtsou type = self.buildref(praw.unit, type) 499a1897c0cSGleb Kurtsou return type 500a1897c0cSGleb Kurtsou 501a1897c0cSGleb Kurtsou def build_subprogram(self, raw): 502a1897c0cSGleb Kurtsou if raw.optname == None: 503a1897c0cSGleb Kurtsou raw.setname('SUBPROGRAM_NONAME_' + raw.arg('low_pc')); 504a1897c0cSGleb Kurtsou params = [ self.build(x) for x in raw.nested ] 505a1897c0cSGleb Kurtsou result = self._build_optarg_type(raw) 506a1897c0cSGleb Kurtsou return FunctionDef(raw.id, raw.name, params=params, result=result) 507a1897c0cSGleb Kurtsou 508c5f8185bSGleb Kurtsou def build_variable(self, raw): 509c5f8185bSGleb Kurtsou type = self._build_optarg_type(raw) 510c5f8185bSGleb Kurtsou return VariableDef(raw.id, raw.optname, type=type) 511c5f8185bSGleb Kurtsou 512a1897c0cSGleb Kurtsou def build_subroutine_type(self, raw): 513a1897c0cSGleb Kurtsou params = [ self.build(x) for x in raw.nested ] 514a1897c0cSGleb Kurtsou result = self._build_optarg_type(raw) 515a1897c0cSGleb Kurtsou return FunctionTypeDef(raw.id, raw.optname, params=params, result=result) 516a1897c0cSGleb Kurtsou 517a1897c0cSGleb Kurtsou def build_formal_parameter(self, raw): 518a1897c0cSGleb Kurtsou type = self._build_optarg_type(raw) 519a1897c0cSGleb Kurtsou return ParameterDef(raw.id, raw.optname, type=type) 520a1897c0cSGleb Kurtsou 521a1897c0cSGleb Kurtsou def build_pointer_type(self, raw): 522a1897c0cSGleb Kurtsou type = self._build_optarg_type(raw) 523a1897c0cSGleb Kurtsou return PointerDef(raw.id, type=type) 524a1897c0cSGleb Kurtsou 525a1897c0cSGleb Kurtsou def build_member(self, raw): 526a1897c0cSGleb Kurtsou type = self.buildref(raw.unit, raw.arg('type')) 527a1897c0cSGleb Kurtsou return MemberDef(raw.id, raw.name, type=type, 528a1897c0cSGleb Kurtsou bit_size=raw.optarg('bit_size', None)) 529a1897c0cSGleb Kurtsou 530a1897c0cSGleb Kurtsou def build_structure_type(self, raw): 531a1897c0cSGleb Kurtsou incomplete = raw.unit.incomplete.get(raw.id) 532a1897c0cSGleb Kurtsou if incomplete == None: 533a1897c0cSGleb Kurtsou incomplete = StructIncompleteDef(raw.id, raw.optname) 534a1897c0cSGleb Kurtsou raw.unit.incomplete.put(raw.id, incomplete) 535a1897c0cSGleb Kurtsou else: 536a1897c0cSGleb Kurtsou return incomplete 537a1897c0cSGleb Kurtsou members = [ self.build(x) for x in raw.nested ] 538a1897c0cSGleb Kurtsou byte_size = raw.optarg('byte_size', None) 539a1897c0cSGleb Kurtsou if byte_size == None: 540a1897c0cSGleb Kurtsou obj = StructForwardDef(raw.id, raw.name, members=members, 541a1897c0cSGleb Kurtsou forcename=raw.name) 542a1897c0cSGleb Kurtsou obj = StructDef(raw.id, raw.optname, members=members, 543a1897c0cSGleb Kurtsou byte_size=byte_size) 544a1897c0cSGleb Kurtsou incomplete.update(obj, cache=raw.unit.cache) 545a1897c0cSGleb Kurtsou return obj 546a1897c0cSGleb Kurtsou 547a1897c0cSGleb Kurtsou def build_union_type(self, raw): 548a1897c0cSGleb Kurtsou incomplete = raw.unit.incomplete.get(raw.id) 549a1897c0cSGleb Kurtsou if incomplete == None: 550a1897c0cSGleb Kurtsou incomplete = UnionIncompleteDef(raw.id, raw.optname) 551a1897c0cSGleb Kurtsou raw.unit.incomplete.put(raw.id, incomplete) 552a1897c0cSGleb Kurtsou else: 553a1897c0cSGleb Kurtsou return incomplete 554a1897c0cSGleb Kurtsou members = [ self.build(x) for x in raw.nested ] 555a1897c0cSGleb Kurtsou byte_size = raw.optarg('byte_size', None) 556a1897c0cSGleb Kurtsou obj = UnionDef(raw.id, raw.optname, members=members, 557a1897c0cSGleb Kurtsou byte_size=byte_size) 558a1897c0cSGleb Kurtsou obj.incomplete = incomplete 559a1897c0cSGleb Kurtsou incomplete.complete = obj 560a1897c0cSGleb Kurtsou return obj 561a1897c0cSGleb Kurtsou 562a1897c0cSGleb Kurtsou def build_typedef(self, raw): 563a1897c0cSGleb Kurtsou type = self._build_optarg_type(raw) 564a1897c0cSGleb Kurtsou return TypeAliasDef(raw.id, raw.name, type=type) 565a1897c0cSGleb Kurtsou 566a1897c0cSGleb Kurtsou def build_const_type(self, raw): 567a1897c0cSGleb Kurtsou type = self._build_optarg_type(raw) 568a1897c0cSGleb Kurtsou return ConstTypeDef(raw.id, type=type) 569a1897c0cSGleb Kurtsou 570a1897c0cSGleb Kurtsou def build_volatile_type(self, raw): 571a1897c0cSGleb Kurtsou type = self._build_optarg_type(raw) 572a1897c0cSGleb Kurtsou return VolatileTypeDef(raw.id, type=type) 573a1897c0cSGleb Kurtsou 574c5f8185bSGleb Kurtsou def build_restrict_type(self, raw): 575c5f8185bSGleb Kurtsou type = self._build_optarg_type(raw) 576c5f8185bSGleb Kurtsou return RestrictTypeDef(raw.id, type=type) 577c5f8185bSGleb Kurtsou 578a1897c0cSGleb Kurtsou def build_enumeration_type(self, raw): 579a1897c0cSGleb Kurtsou # TODO handle DW_TAG_enumerator ??? 580a1897c0cSGleb Kurtsou return EnumerationTypeDef(raw.id, name=raw.optname, 581a1897c0cSGleb Kurtsou byte_size=raw.arg('byte_size')) 582a1897c0cSGleb Kurtsou 583a1897c0cSGleb Kurtsou def build_base_type(self, raw): 584a1897c0cSGleb Kurtsou return BaseTypeDef(raw.id, raw.optname, 585a1897c0cSGleb Kurtsou byte_size=raw.arg('byte_size'), encoding=raw.arg('encoding')) 586a1897c0cSGleb Kurtsou 587a1897c0cSGleb Kurtsou def build_array_type(self, raw): 588a1897c0cSGleb Kurtsou type = self.buildref(raw.unit, raw.arg('type')) 589a1897c0cSGleb Kurtsou subranges = [ self.build(x) for x in raw.nested ] 590a1897c0cSGleb Kurtsou return ArrayDef(raw.id, type=type, subranges=subranges) 591a1897c0cSGleb Kurtsou 592a1897c0cSGleb Kurtsou def build_subrange_type(self, raw): 593a1897c0cSGleb Kurtsou type = self.buildref(raw.unit, raw.arg('type')) 594a1897c0cSGleb Kurtsou return ArraySubrangeDef(raw.id, type=type, 595a1897c0cSGleb Kurtsou upper_bound=raw.optarg('upper_bound', 0)) 596a1897c0cSGleb Kurtsou 597a1897c0cSGleb Kurtsou def build_unspecified_parameters(self, raw): 598a1897c0cSGleb Kurtsou return VarArgs(raw.id) 599a1897c0cSGleb Kurtsou 600a1897c0cSGleb Kurtsou def _get_id(self, id): 601a1897c0cSGleb Kurtsou try: 602a1897c0cSGleb Kurtsou return int(id) 603a1897c0cSGleb Kurtsou except ValueError: 604a1897c0cSGleb Kurtsou if (id.startswith('<') and id.endswith('>')): 605c5f8185bSGleb Kurtsou return int(id[1:-1], 0) 606a1897c0cSGleb Kurtsou else: 607a1897c0cSGleb Kurtsou raise ValueError("Invalid dwarf id: %s" % id) 608a1897c0cSGleb Kurtsou 609a1897c0cSGleb Kurtsou def build(self, raw): 610a1897c0cSGleb Kurtsou obj = raw.unit.cache.get(raw.id) 611a1897c0cSGleb Kurtsou if obj != None: 612a1897c0cSGleb Kurtsou return obj 613a1897c0cSGleb Kurtsou builder_name = raw.tag.replace('DW_TAG_', 'build_') 614a1897c0cSGleb Kurtsou try: 615a1897c0cSGleb Kurtsou builder = getattr(self, builder_name) 616a1897c0cSGleb Kurtsou except AttributeError: 617a1897c0cSGleb Kurtsou raise AttributeError("Unknown dwarf tag: %s" % raw) 618a1897c0cSGleb Kurtsou obj = builder(raw) 619a1897c0cSGleb Kurtsou raw.unit.cache.put(obj.id, obj) 620a1897c0cSGleb Kurtsou return obj 621a1897c0cSGleb Kurtsou 622a1897c0cSGleb Kurtsou def buildref(self, unit, id): 623a1897c0cSGleb Kurtsou id = self._get_id(id) 624a1897c0cSGleb Kurtsou raw = unit.tags[id] 625a1897c0cSGleb Kurtsou obj = self.build(raw) 626a1897c0cSGleb Kurtsou return obj 627a1897c0cSGleb Kurtsou 628a1897c0cSGleb Kurtsou# }}} 629a1897c0cSGleb Kurtsou 630a1897c0cSGleb Kurtsouclass Shlib(object): 631a1897c0cSGleb Kurtsou def __init__(self, libfile): 632a1897c0cSGleb Kurtsou self.libfile = libfile 633a1897c0cSGleb Kurtsou self.versions = {} 634a1897c0cSGleb Kurtsou self.alias_syms = {} 635a1897c0cSGleb Kurtsou 636a1897c0cSGleb Kurtsou def parse_objdump(self): 637a1897c0cSGleb Kurtsou objdump = ObjdumpParser(self.libfile) 638a1897c0cSGleb Kurtsou objdump.run() 639a1897c0cSGleb Kurtsou for p in objdump.dynamic_symbols: 640a1897c0cSGleb Kurtsou vername = p['ver'] 641a1897c0cSGleb Kurtsou if vername.startswith('(') and vername.endswith(')'): 642a1897c0cSGleb Kurtsou vername = vername[1:-1] 643a1897c0cSGleb Kurtsou if not Config.version_filter.match(vername): 644a1897c0cSGleb Kurtsou continue 645a1897c0cSGleb Kurtsou if not Config.symbol_filter.match(p['symbol']): 646a1897c0cSGleb Kurtsou continue 647a1897c0cSGleb Kurtsou sym = Symbol(p['symbol'], p['offset'], vername, self) 648aef675d8SCraig Rodrigues if vername not in self.versions: 649a1897c0cSGleb Kurtsou self.versions[vername] = VersionMap(vername) 650a1897c0cSGleb Kurtsou self.versions[vername].append(sym) 651a1897c0cSGleb Kurtsou if Config.alias_prefixes: 652a1897c0cSGleb Kurtsou self.local_offsetmap = objdump.local_offsetmap 653a1897c0cSGleb Kurtsou for p in objdump.local_symbols: 654a1897c0cSGleb Kurtsou for prefix in Config.alias_prefixes: 655a1897c0cSGleb Kurtsou if not p['symbol'].startswith(prefix): 656a1897c0cSGleb Kurtsou continue 657a1897c0cSGleb Kurtsou alias = SymbolAlias(p['symbol'], prefix, p['offset']) 658aef675d8SCraig Rodrigues if alias.name in self.alias_syms: 659a1897c0cSGleb Kurtsou prevalias = self.alias_syms[alias.name] 660a1897c0cSGleb Kurtsou if alias.name != prevalias.name or \ 661a1897c0cSGleb Kurtsou alias.offset != prevalias.offset: 662a1897c0cSGleb Kurtsou warn(Config.w_alias, "Symbol alias is " \ 663a1897c0cSGleb Kurtsou "already defined: %s: %s at %08x -- %s at %08x" % \ 664a1897c0cSGleb Kurtsou (alias.alias, alias.name, alias.offset, 665a1897c0cSGleb Kurtsou prevalias.name, prevalias.offset)) 666a1897c0cSGleb Kurtsou self.alias_syms[alias.name] = alias 667a1897c0cSGleb Kurtsou 668a1897c0cSGleb Kurtsou def parse_dwarfdump(self): 669a1897c0cSGleb Kurtsou dwarfdump = DwarfdumpParser(self.libfile) 670a1897c0cSGleb Kurtsou def lookup(sym): 671a1897c0cSGleb Kurtsou raw = None 672a1897c0cSGleb Kurtsou try: 673a1897c0cSGleb Kurtsou raw = dwarfdump.offsetmap[sym.offset] 674a1897c0cSGleb Kurtsou except: 675a1897c0cSGleb Kurtsou try: 676a1897c0cSGleb Kurtsou localnames = self.local_offsetmap[sym.offset] 677a1897c0cSGleb Kurtsou localnames.sort(key=lambda x: -len(x)) 678a1897c0cSGleb Kurtsou for localname in localnames: 679aef675d8SCraig Rodrigues if localname not in self.alias_syms: 680a1897c0cSGleb Kurtsou continue 681a1897c0cSGleb Kurtsou alias = self.alias_syms[localname] 682a1897c0cSGleb Kurtsou raw = dwarfdump.offsetmap[alias.offset] 683a1897c0cSGleb Kurtsou break 684a1897c0cSGleb Kurtsou except: 685a1897c0cSGleb Kurtsou pass 686a1897c0cSGleb Kurtsou return raw 687a1897c0cSGleb Kurtsou dwarfdump.run() 688a1897c0cSGleb Kurtsou dwarf = Dwarf(dwarfdump) 689a1897c0cSGleb Kurtsou for ver in self.versions.values(): 690a1897c0cSGleb Kurtsou for sym in ver.symbols.values(): 691a1897c0cSGleb Kurtsou raw = lookup(sym); 692a1897c0cSGleb Kurtsou if not raw: 693a1897c0cSGleb Kurtsou warn(Config.w_symbol, "Symbol %s (%s) not found at offset 0x%x" % \ 694a1897c0cSGleb Kurtsou (sym.name_ver, self.libfile, sym.offset)) 695a1897c0cSGleb Kurtsou continue 696a1897c0cSGleb Kurtsou if Config.verbose >= 3: 697749f65e3SCraig Rodrigues print("Parsing symbol %s (%s)" % (sym.name_ver, self.libfile)) 698a1897c0cSGleb Kurtsou sym.definition = dwarf.build(raw) 699a1897c0cSGleb Kurtsou 700a1897c0cSGleb Kurtsou def parse(self): 701a1897c0cSGleb Kurtsou if not os.path.isfile(self.libfile): 702749f65e3SCraig Rodrigues print("No such file: %s" % self.libfile, file=sys.stderr) 703a1897c0cSGleb Kurtsou sys.exit(1) 704a1897c0cSGleb Kurtsou self.parse_objdump() 705a1897c0cSGleb Kurtsou self.parse_dwarfdump() 706a1897c0cSGleb Kurtsou 707a1897c0cSGleb Kurtsou# {{{ parsers 708a1897c0cSGleb Kurtsou 709a1897c0cSGleb Kurtsouclass Parser(object): 710a1897c0cSGleb Kurtsou def __init__(self, proc): 711a1897c0cSGleb Kurtsou self.proc = proc 712a1897c0cSGleb Kurtsou self.parser = self.parse_begin 713a1897c0cSGleb Kurtsou 714a1897c0cSGleb Kurtsou def run(self): 715a1897c0cSGleb Kurtsou fd = os.popen(self.proc, 'r') 716a1897c0cSGleb Kurtsou while True: 717a1897c0cSGleb Kurtsou line = fd.readline() 718a1897c0cSGleb Kurtsou if (not line): 719a1897c0cSGleb Kurtsou break 720a1897c0cSGleb Kurtsou line = line.strip() 721a1897c0cSGleb Kurtsou if (line): 722a1897c0cSGleb Kurtsou self.parser(line) 723a1897c0cSGleb Kurtsou err = fd.close() 724a1897c0cSGleb Kurtsou if err: 725749f65e3SCraig Rodrigues print("Execution failed: %s" % self.proc, file=sys.stderr) 726a1897c0cSGleb Kurtsou sys.exit(2) 727a1897c0cSGleb Kurtsou 728a1897c0cSGleb Kurtsou def parse_begin(self, line): 729a1897c0cSGleb Kurtsou print(line) 730a1897c0cSGleb Kurtsou 731a1897c0cSGleb Kurtsouclass ObjdumpParser(Parser): 732a1897c0cSGleb Kurtsou 733a1897c0cSGleb Kurtsou re_header = re.compile('(?P<table>\w*)\s*SYMBOL TABLE:') 734a1897c0cSGleb Kurtsou 735a1897c0cSGleb Kurtsou re_local_symbol = re.compile('(?P<offset>[0-9a-fA-F]+)\s+(?P<bind>\w+)\s+(?P<type>\w+)\s+(?P<section>[^\s]+)\s+(?P<foffset>[0-9a-fA-F]+)\s*(?P<symbol>[^\s]*)') 736a1897c0cSGleb Kurtsou re_lame_symbol = re.compile('(?P<offset>[0-9a-fA-F]+)\s+(?P<bind>\w+)\s+\*[A-Z]+\*') 737a1897c0cSGleb Kurtsou 738a1897c0cSGleb Kurtsou re_dynamic_symbol = re.compile('(?P<offset>[0-9a-fA-F]+)\s+(?P<bind>\w+)\s+(?P<type>\w+)\s+(?P<section>[^\s]+)\s+(?P<foffset>[0-9a-fA-F]+)\s*(?P<ver>[^\s]*)\s*(?P<symbol>[^\s]*)') 739a1897c0cSGleb Kurtsou 740a1897c0cSGleb Kurtsou def __init__(self, libfile): 741a1897c0cSGleb Kurtsou Parser.__init__(self, "%s -wtT %s" % (Config.objdump, libfile)) 742a1897c0cSGleb Kurtsou self.dynamic_symbols = [] 743a1897c0cSGleb Kurtsou self.local_symbols = [] 744a1897c0cSGleb Kurtsou self.local_offsetmap = {} 745a1897c0cSGleb Kurtsou 746a1897c0cSGleb Kurtsou def parse_begin(self, line): 747a1897c0cSGleb Kurtsou self.parse_header(line) 748a1897c0cSGleb Kurtsou 749a1897c0cSGleb Kurtsou def add_symbol(self, table, symbol, offsetmap = None): 750a1897c0cSGleb Kurtsou offset = int(symbol['offset'], 16); 751a1897c0cSGleb Kurtsou symbol['offset'] = offset 752a1897c0cSGleb Kurtsou if (offset == 0): 753a1897c0cSGleb Kurtsou return 754a1897c0cSGleb Kurtsou table.append(symbol) 755a1897c0cSGleb Kurtsou if offsetmap != None: 756aef675d8SCraig Rodrigues if offset not in offsetmap: 757a1897c0cSGleb Kurtsou offsetmap[offset] = [symbol['symbol']] 758a1897c0cSGleb Kurtsou else: 759a1897c0cSGleb Kurtsou offsetmap[offset].append(symbol['symbol']) 760a1897c0cSGleb Kurtsou 761a1897c0cSGleb Kurtsou def parse_header(self, line): 762a1897c0cSGleb Kurtsou m = self.re_header.match(line) 763a1897c0cSGleb Kurtsou if (m): 764a1897c0cSGleb Kurtsou table = m.group('table') 765a1897c0cSGleb Kurtsou if (table == "DYNAMIC"): 766a1897c0cSGleb Kurtsou self.parser = self.parse_dynamic 767a1897c0cSGleb Kurtsou elif table == '': 768a1897c0cSGleb Kurtsou self.parser = self.parse_local 769a1897c0cSGleb Kurtsou else: 770a1897c0cSGleb Kurtsou raise ValueError("Invalid symbol table: %s" % table) 771a1897c0cSGleb Kurtsou return True 772a1897c0cSGleb Kurtsou return False 773a1897c0cSGleb Kurtsou 774a1897c0cSGleb Kurtsou def parse_local(self, line): 775a1897c0cSGleb Kurtsou if (self.parse_header(line)): 776a1897c0cSGleb Kurtsou return 777a1897c0cSGleb Kurtsou if (self.re_lame_symbol.match(line)): 778a1897c0cSGleb Kurtsou return 779a1897c0cSGleb Kurtsou m = self.re_local_symbol.match(line) 780a1897c0cSGleb Kurtsou if (not m): 781a1897c0cSGleb Kurtsou return 782a1897c0cSGleb Kurtsou #raise ValueError("Invalid symbol definition: %s" % line) 783a1897c0cSGleb Kurtsou p = m.groupdict() 784a1897c0cSGleb Kurtsou if (p['symbol'] and p['symbol'].find('@') == -1): 785a1897c0cSGleb Kurtsou self.add_symbol(self.local_symbols, p, self.local_offsetmap); 786a1897c0cSGleb Kurtsou 787a1897c0cSGleb Kurtsou def parse_dynamic(self, line): 788a1897c0cSGleb Kurtsou if (self.parse_header(line)): 789a1897c0cSGleb Kurtsou return 790a1897c0cSGleb Kurtsou if (self.re_lame_symbol.match(line)): 791a1897c0cSGleb Kurtsou return 792a1897c0cSGleb Kurtsou m = self.re_dynamic_symbol.match(line) 793a1897c0cSGleb Kurtsou if (not m): 794a1897c0cSGleb Kurtsou raise ValueError("Invalid symbol definition: %s" % line) 795a1897c0cSGleb Kurtsou p = m.groupdict() 796a1897c0cSGleb Kurtsou if (p['symbol'] and p['ver']): 797a1897c0cSGleb Kurtsou self.add_symbol(self.dynamic_symbols, p); 798a1897c0cSGleb Kurtsou 799a1897c0cSGleb Kurtsouclass DwarfdumpParser(Parser): 800a1897c0cSGleb Kurtsou 801a1897c0cSGleb Kurtsou tagcache_stats = Cache.CacheStats() 802a1897c0cSGleb Kurtsou 803a1897c0cSGleb Kurtsou class Unit(object): 804a1897c0cSGleb Kurtsou def __init__(self): 805a1897c0cSGleb Kurtsou self.cache = Cache(enabled=Config.dwarfcache_enabled, 806a1897c0cSGleb Kurtsou stats=DwarfdumpParser.tagcache_stats) 807a1897c0cSGleb Kurtsou self.incomplete = Cache() 808a1897c0cSGleb Kurtsou self.tags = {} 809a1897c0cSGleb Kurtsou 810a1897c0cSGleb Kurtsou class Tag(object): 811a1897c0cSGleb Kurtsou def __init__(self, unit, data): 812a1897c0cSGleb Kurtsou self.unit = unit 813c5f8185bSGleb Kurtsou self.id = int(data['id'], 0) 814a1897c0cSGleb Kurtsou self.level = int(data['level']) 815a1897c0cSGleb Kurtsou self.tag = data['tag'] 816a1897c0cSGleb Kurtsou self.args = {} 817a1897c0cSGleb Kurtsou self.nested = [] 818a1897c0cSGleb Kurtsou 819a1897c0cSGleb Kurtsou @property 820a1897c0cSGleb Kurtsou def name(self): 821a1897c0cSGleb Kurtsou return self.arg('name') 822a1897c0cSGleb Kurtsou 823a1897c0cSGleb Kurtsou @property 824a1897c0cSGleb Kurtsou def optname(self): 825a1897c0cSGleb Kurtsou return self.optarg('name', None) 826a1897c0cSGleb Kurtsou 827a1897c0cSGleb Kurtsou def setname(self, name): 828a1897c0cSGleb Kurtsou self.args['DW_AT_name'] = name 829a1897c0cSGleb Kurtsou 830a1897c0cSGleb Kurtsou def arg(self, a): 831a1897c0cSGleb Kurtsou name = 'DW_AT_' + a 832a1897c0cSGleb Kurtsou try: 833a1897c0cSGleb Kurtsou return self.args[name] 834a1897c0cSGleb Kurtsou except KeyError: 835a1897c0cSGleb Kurtsou raise KeyError("Argument '%s' not found in %s: %s" % 836a1897c0cSGleb Kurtsou (name, self, self.args)) 837a1897c0cSGleb Kurtsou 838a1897c0cSGleb Kurtsou def optarg(self, a, default): 839a1897c0cSGleb Kurtsou try: 840a1897c0cSGleb Kurtsou return self.arg(a) 841a1897c0cSGleb Kurtsou except KeyError: 842a1897c0cSGleb Kurtsou return default 843a1897c0cSGleb Kurtsou 844a1897c0cSGleb Kurtsou def __repr__(self): 845a1897c0cSGleb Kurtsou return "Tag(%d, %d, %s)" % (self.level, self.id, self.tag) 846a1897c0cSGleb Kurtsou 847c5f8185bSGleb Kurtsou re_header = re.compile('<(?P<level>\d+)><(?P<id>[0xX0-9a-fA-F]+(?:\+(0[xX])?[0-9a-fA-F]+)?)><(?P<tag>\w+)>') 848a1897c0cSGleb Kurtsou re_argname = re.compile('(?P<arg>\w+)<') 849a1897c0cSGleb Kurtsou re_argunknown = re.compile('<Unknown AT value \w+><[^<>]+>') 850a1897c0cSGleb Kurtsou 851a1897c0cSGleb Kurtsou skip_tags = set([ 852a1897c0cSGleb Kurtsou 'DW_TAG_lexical_block', 853a1897c0cSGleb Kurtsou 'DW_TAG_inlined_subroutine', 854a1897c0cSGleb Kurtsou 'DW_TAG_label', 855a1897c0cSGleb Kurtsou 'DW_TAG_variable', 856a1897c0cSGleb Kurtsou ]) 857a1897c0cSGleb Kurtsou 858c5f8185bSGleb Kurtsou external_tags = set([ 859c5f8185bSGleb Kurtsou 'DW_TAG_variable', 860c5f8185bSGleb Kurtsou ]) 861c5f8185bSGleb Kurtsou 862a1897c0cSGleb Kurtsou def __init__(self, libfile): 863a1897c0cSGleb Kurtsou Parser.__init__(self, "%s -di %s" % (Config.dwarfdump, libfile)) 864a1897c0cSGleb Kurtsou self.current_unit = None 865a1897c0cSGleb Kurtsou self.offsetmap = {} 866a1897c0cSGleb Kurtsou self.stack = [] 867a1897c0cSGleb Kurtsou 868a1897c0cSGleb Kurtsou def parse_begin(self, line): 869a1897c0cSGleb Kurtsou if line == '.debug_info': 870a1897c0cSGleb Kurtsou self.parser = self.parse_debuginfo 871a1897c0cSGleb Kurtsou else: 872a1897c0cSGleb Kurtsou raise ValueError("Invalid dwarfdump header: %s" % line) 873a1897c0cSGleb Kurtsou 874a1897c0cSGleb Kurtsou def parse_argvalue(self, args): 875a1897c0cSGleb Kurtsou assert args.startswith('<') 876a1897c0cSGleb Kurtsou i = 1 877a1897c0cSGleb Kurtsou cnt = 1 878a1897c0cSGleb Kurtsou while i < len(args) and args[i]: 879a1897c0cSGleb Kurtsou if args[i] == '<': 880a1897c0cSGleb Kurtsou cnt += 1 881a1897c0cSGleb Kurtsou elif args[i] == '>': 882a1897c0cSGleb Kurtsou cnt -= 1 883a1897c0cSGleb Kurtsou if cnt == 0: 884a1897c0cSGleb Kurtsou break 885a1897c0cSGleb Kurtsou i = i + 1 886a1897c0cSGleb Kurtsou value = args[1:i] 887a1897c0cSGleb Kurtsou args = args[i+1:] 888a1897c0cSGleb Kurtsou return (args, value) 889a1897c0cSGleb Kurtsou 890a1897c0cSGleb Kurtsou def parse_arg(self, tag, args): 891a1897c0cSGleb Kurtsou m = self.re_argname.match(args) 892a1897c0cSGleb Kurtsou if not m: 893a1897c0cSGleb Kurtsou m = self.re_argunknown.match(args) 894a1897c0cSGleb Kurtsou if not m: 895a1897c0cSGleb Kurtsou raise ValueError("Invalid dwarfdump: couldn't parse arguments: %s" % 896a1897c0cSGleb Kurtsou args) 897a1897c0cSGleb Kurtsou args = args[len(m.group(0)):].lstrip() 898a1897c0cSGleb Kurtsou return args 899a1897c0cSGleb Kurtsou argname = m.group('arg') 900a1897c0cSGleb Kurtsou args = args[len(argname):] 901a1897c0cSGleb Kurtsou value = [] 902a1897c0cSGleb Kurtsou while len(args) > 0 and args.startswith('<'): 903a1897c0cSGleb Kurtsou (args, v) = self.parse_argvalue(args) 904a1897c0cSGleb Kurtsou value.append(v) 905a1897c0cSGleb Kurtsou args = args.lstrip() 906a1897c0cSGleb Kurtsou if len(value) == 1: 907a1897c0cSGleb Kurtsou value = value[0] 908a1897c0cSGleb Kurtsou tag.args[argname] = value 909a1897c0cSGleb Kurtsou return args 910a1897c0cSGleb Kurtsou 911a1897c0cSGleb Kurtsou def parse_debuginfo(self, line): 912a1897c0cSGleb Kurtsou m = self.re_header.match(line) 913a1897c0cSGleb Kurtsou if not m: 914a1897c0cSGleb Kurtsou raise ValueError("Invalid dwarfdump: %s" % line) 915a1897c0cSGleb Kurtsou if m.group('level') == '0': 916a1897c0cSGleb Kurtsou self.current_unit = DwarfdumpParser.Unit() 917a1897c0cSGleb Kurtsou return 918a1897c0cSGleb Kurtsou tag = DwarfdumpParser.Tag(self.current_unit, m.groupdict()) 919a1897c0cSGleb Kurtsou args = line[len(m.group(0)):].lstrip() 920a1897c0cSGleb Kurtsou while args: 921a1897c0cSGleb Kurtsou args = self.parse_arg(tag, args) 922a1897c0cSGleb Kurtsou tag.unit.tags[tag.id] = tag 923c5f8185bSGleb Kurtsou def parse_offset(tag): 924aef675d8SCraig Rodrigues if 'DW_AT_low_pc' in tag.args: 925c5f8185bSGleb Kurtsou return int(tag.args['DW_AT_low_pc'], 16) 926aef675d8SCraig Rodrigues elif 'DW_AT_location' in tag.args: 927c5f8185bSGleb Kurtsou location = tag.args['DW_AT_location'] 928c5f8185bSGleb Kurtsou if location.startswith('DW_OP_addr'): 929c5f8185bSGleb Kurtsou return int(location.replace('DW_OP_addr', ''), 16) 930c5f8185bSGleb Kurtsou return None 931c5f8185bSGleb Kurtsou offset = parse_offset(tag) 932c5f8185bSGleb Kurtsou if offset is not None and \ 933c5f8185bSGleb Kurtsou (tag.tag not in DwarfdumpParser.skip_tags or \ 934aef675d8SCraig Rodrigues ('DW_AT_external' in tag.args and \ 935c5f8185bSGleb Kurtsou tag.tag in DwarfdumpParser.external_tags)): 936aef675d8SCraig Rodrigues if offset in self.offsetmap: 937a1897c0cSGleb Kurtsou raise ValueError("Dwarf dump parse error: " + 938bd0ca238SPedro F. Giffuni "symbol is already defined at offset 0x%x" % offset) 939a1897c0cSGleb Kurtsou self.offsetmap[offset] = tag 940a1897c0cSGleb Kurtsou if len(self.stack) > 0: 941a1897c0cSGleb Kurtsou prev = self.stack.pop() 942a1897c0cSGleb Kurtsou while prev.level >= tag.level and len(self.stack) > 0: 943a1897c0cSGleb Kurtsou prev = self.stack.pop() 944a1897c0cSGleb Kurtsou if prev.level < tag.level: 945a1897c0cSGleb Kurtsou assert prev.level == tag.level - 1 946a1897c0cSGleb Kurtsou # TODO check DW_AT_sibling ??? 947a1897c0cSGleb Kurtsou if tag.tag not in DwarfdumpParser.skip_tags: 948a1897c0cSGleb Kurtsou prev.nested.append(tag) 949a1897c0cSGleb Kurtsou self.stack.append(prev) 950a1897c0cSGleb Kurtsou self.stack.append(tag) 951a1897c0cSGleb Kurtsou assert len(self.stack) == tag.level 952a1897c0cSGleb Kurtsou 953a1897c0cSGleb Kurtsou# }}} 954a1897c0cSGleb Kurtsou 955a1897c0cSGleb Kurtsoudef list_str(l): 956a1897c0cSGleb Kurtsou l = [ str(x) for x in l ] 957a1897c0cSGleb Kurtsou l.sort() 958a1897c0cSGleb Kurtsou return ', '.join(l) 959a1897c0cSGleb Kurtsou 960a1897c0cSGleb Kurtsoudef names_ver_str(vername, names): 961a1897c0cSGleb Kurtsou return list_str([ x + "@" + vername for x in names ]) 962a1897c0cSGleb Kurtsou 963a1897c0cSGleb Kurtsoudef common_symbols(origlib, newlib): 964a1897c0cSGleb Kurtsou result = [] 965a1897c0cSGleb Kurtsou verdiff = ListDiff(origlib.versions.keys(), newlib.versions.keys()) 966a1897c0cSGleb Kurtsou if Config.verbose >= 1: 967749f65e3SCraig Rodrigues print('Original versions: ', list_str(verdiff.orig)) 968749f65e3SCraig Rodrigues print('New versions: ', list_str(verdiff.new)) 969a1897c0cSGleb Kurtsou for vername in verdiff.added: 970749f65e3SCraig Rodrigues print('Added version: ', vername) 971749f65e3SCraig Rodrigues print(' Added symbols: ', \ 972749f65e3SCraig Rodrigues names_ver_str(vername, newlib.versions[vername].names())) 973a1897c0cSGleb Kurtsou for vername in verdiff.removed: 974749f65e3SCraig Rodrigues print('Removed version: ', vername) 975749f65e3SCraig Rodrigues print(' Removed symbols: ', \ 976749f65e3SCraig Rodrigues names_ver_str(vername, origlib.versions[vername].names())) 977a1897c0cSGleb Kurtsou added = [] 978a1897c0cSGleb Kurtsou removed = [] 979a1897c0cSGleb Kurtsou for vername in verdiff.common: 980a1897c0cSGleb Kurtsou origver = origlib.versions[vername] 981a1897c0cSGleb Kurtsou newver = newlib.versions[vername] 982a1897c0cSGleb Kurtsou namediff = ListDiff(origver.names(), newver.names()) 983a1897c0cSGleb Kurtsou if namediff.added: 984a1897c0cSGleb Kurtsou added.append(names_ver_str(vername, namediff.added)) 985a1897c0cSGleb Kurtsou if namediff.removed: 986a1897c0cSGleb Kurtsou removed.append(names_ver_str(vername, namediff.removed)) 987a1897c0cSGleb Kurtsou commonver = VersionMap(vername) 988a1897c0cSGleb Kurtsou result.append(commonver) 989a1897c0cSGleb Kurtsou for n in namediff.common: 990a1897c0cSGleb Kurtsou sym = CommonSymbol(origver.symbols[n], newver.symbols[n]) 991a1897c0cSGleb Kurtsou commonver.append(sym) 992a1897c0cSGleb Kurtsou if added: 993749f65e3SCraig Rodrigues print('Added symbols:') 994a1897c0cSGleb Kurtsou for i in added: 995749f65e3SCraig Rodrigues print(' ', i) 996a1897c0cSGleb Kurtsou if removed: 997749f65e3SCraig Rodrigues print('Removed symbols:') 998a1897c0cSGleb Kurtsou for i in removed: 999749f65e3SCraig Rodrigues print(' ', i) 1000a1897c0cSGleb Kurtsou return result 1001a1897c0cSGleb Kurtsou 1002a1897c0cSGleb Kurtsoudef cmp_symbols(commonver): 1003a1897c0cSGleb Kurtsou for ver in commonver: 1004a1897c0cSGleb Kurtsou names = ver.names(); 1005a1897c0cSGleb Kurtsou names.sort() 1006a1897c0cSGleb Kurtsou for symname in names: 1007a1897c0cSGleb Kurtsou sym = ver.symbols[symname] 1008c5f8185bSGleb Kurtsou missing = sym.origsym.definition is None or sym.newsym.definition is None 1009c5f8185bSGleb Kurtsou match = not missing and sym.origsym.definition == sym.newsym.definition 1010a1897c0cSGleb Kurtsou if not match: 1011a1897c0cSGleb Kurtsou App.result_code = 1 1012a1897c0cSGleb Kurtsou if Config.verbose >= 1 or not match: 1013c5f8185bSGleb Kurtsou if missing: 1014749f65e3SCraig Rodrigues print('%s: missing definition' % \ 1015749f65e3SCraig Rodrigues (sym.origsym.name_ver,)) 1016c5f8185bSGleb Kurtsou continue 1017749f65e3SCraig Rodrigues print('%s: definitions %smatch' % \ 1018749f65e3SCraig Rodrigues (sym.origsym.name_ver, "" if match else "mis")) 1019a1897c0cSGleb Kurtsou if Config.dump or (not match and not Config.no_dump): 1020a1897c0cSGleb Kurtsou for x in [(sym.origsym, Config.origfile), 1021a1897c0cSGleb Kurtsou (sym.newsym, Config.newfile)]: 1022a1897c0cSGleb Kurtsou xsym = x[0] 1023a1897c0cSGleb Kurtsou xout = x[1].out 1024a1897c0cSGleb Kurtsou if not xsym.definition: 1025749f65e3SCraig Rodrigues print('\n// Definition not found: %s %s' % \ 1026749f65e3SCraig Rodrigues (xsym.name_ver, xsym.lib.libfile), file=xout) 1027a1897c0cSGleb Kurtsou continue 1028749f65e3SCraig Rodrigues print('\n// Definitions mismatch: %s %s' % \ 1029749f65e3SCraig Rodrigues (xsym.name_ver, xsym.lib.libfile), file=xout) 1030a1897c0cSGleb Kurtsou pp = PrettyPrinter() 1031a1897c0cSGleb Kurtsou pp.run(xsym.definition) 1032a1897c0cSGleb Kurtsou for i in pp.nested(): 1033749f65e3SCraig Rodrigues print(i, file=xout) 1034749f65e3SCraig Rodrigues print(pp.result(), file=xout) 1035a1897c0cSGleb Kurtsou 1036a1897c0cSGleb Kurtsoudef dump_symbols(commonver): 1037a1897c0cSGleb Kurtsou class SymbolDump(object): 1038a1897c0cSGleb Kurtsou def __init__(self, io_conf): 1039a1897c0cSGleb Kurtsou self.io_conf = io_conf 1040a1897c0cSGleb Kurtsou self.pp = PrettyPrinter() 1041a1897c0cSGleb Kurtsou self.res = [] 1042a1897c0cSGleb Kurtsou def run(self, sym): 1043a1897c0cSGleb Kurtsou r = self.pp.run(sym.definition) 1044a1897c0cSGleb Kurtsou self.res.append('/* %s@%s */ %s' % (sym.name, sym.version, r)) 1045a1897c0cSGleb Kurtsou def finish(self): 1046749f65e3SCraig Rodrigues print('\n// Symbol dump: version %s, library %s' % \ 1047749f65e3SCraig Rodrigues (ver.name, self.io_conf.filename), file=self.io_conf.out) 1048a1897c0cSGleb Kurtsou for i in self.pp.nested(): 1049749f65e3SCraig Rodrigues print(i, file=self.io_conf.out) 1050749f65e3SCraig Rodrigues print('', file=self.io_conf.out) 1051a1897c0cSGleb Kurtsou for i in self.res: 1052749f65e3SCraig Rodrigues print(i, file=self.io_conf.out) 1053a1897c0cSGleb Kurtsou for ver in commonver: 1054a1897c0cSGleb Kurtsou names = sorted(ver.names()); 1055a1897c0cSGleb Kurtsou d_orig = SymbolDump(Config.origfile) 1056a1897c0cSGleb Kurtsou d_new = SymbolDump(Config.newfile) 1057a1897c0cSGleb Kurtsou for symname in names: 1058a1897c0cSGleb Kurtsou sym = ver.symbols[symname] 1059a1897c0cSGleb Kurtsou if not sym.origsym.definition or not sym.newsym.definition: 1060a1897c0cSGleb Kurtsou # XXX 1061a1897c0cSGleb Kurtsou warn(Config.w_symbol, 'Missing symbol definition: %s@%s' % \ 1062a1897c0cSGleb Kurtsou (symname, ver.name)) 1063a1897c0cSGleb Kurtsou continue 1064a1897c0cSGleb Kurtsou d_orig.run(sym.origsym) 1065a1897c0cSGleb Kurtsou d_new.run(sym.newsym) 1066a1897c0cSGleb Kurtsou d_orig.finish() 1067a1897c0cSGleb Kurtsou d_new.finish() 1068a1897c0cSGleb Kurtsou 1069a1897c0cSGleb Kurtsouif __name__ == '__main__': 1070a1897c0cSGleb Kurtsou Config.init() 1071a1897c0cSGleb Kurtsou parser = optparse.OptionParser(usage="usage: %prog origlib newlib", 1072a1897c0cSGleb Kurtsou version="%prog " + Config.version) 1073a1897c0cSGleb Kurtsou parser.add_option('-v', '--verbose', action='count', 1074a1897c0cSGleb Kurtsou help="verbose mode, may be specified several times") 1075a1897c0cSGleb Kurtsou parser.add_option('--alias-prefix', action='append', 1076a1897c0cSGleb Kurtsou help="name prefix to try for symbol alias lookup", metavar="STR") 1077a1897c0cSGleb Kurtsou parser.add_option('--dump', action='store_true', 1078a1897c0cSGleb Kurtsou help="dump symbol definitions") 1079a1897c0cSGleb Kurtsou parser.add_option('--no-dump', action='store_true', 1080a1897c0cSGleb Kurtsou help="disable dump for mismatched symbols") 1081a1897c0cSGleb Kurtsou parser.add_option('--out-orig', action='store', 1082a1897c0cSGleb Kurtsou help="result output file for original library", metavar="ORIGFILE") 1083a1897c0cSGleb Kurtsou parser.add_option('--out-new', action='store', 1084a1897c0cSGleb Kurtsou help="result output file for new library", metavar="NEWFILE") 1085c5f8185bSGleb Kurtsou parser.add_option('--dwarfdump', action='store', 1086c5f8185bSGleb Kurtsou help="path to dwarfdump executable", metavar="DWARFDUMP") 1087c5f8185bSGleb Kurtsou parser.add_option('--objdump', action='store', 1088c5f8185bSGleb Kurtsou help="path to objdump executable", metavar="OBJDUMP") 1089a1897c0cSGleb Kurtsou parser.add_option('--exclude-ver', action='append', metavar="RE") 1090a1897c0cSGleb Kurtsou parser.add_option('--include-ver', action='append', metavar="RE") 1091a1897c0cSGleb Kurtsou parser.add_option('--exclude-sym', action='append', metavar="RE") 1092a1897c0cSGleb Kurtsou parser.add_option('--include-sym', action='append', metavar="RE") 1093c5f8185bSGleb Kurtsou parser.add_option('--no-exclude-sym-default', action='store_true', 1094c5f8185bSGleb Kurtsou help="don't exclude special symbols like _init, _end, __bss_start") 1095a1897c0cSGleb Kurtsou for opt in ['alias', 'cached', 'symbol']: 1096a1897c0cSGleb Kurtsou parser.add_option("--w-" + opt, 1097a1897c0cSGleb Kurtsou action="store_true", dest="w_" + opt) 1098a1897c0cSGleb Kurtsou parser.add_option("--w-no-" + opt, 1099a1897c0cSGleb Kurtsou action="store_false", dest="w_" + opt) 1100a1897c0cSGleb Kurtsou (opts, args) = parser.parse_args() 1101a1897c0cSGleb Kurtsou 1102a1897c0cSGleb Kurtsou if len(args) != 2: 1103a1897c0cSGleb Kurtsou parser.print_help() 1104a1897c0cSGleb Kurtsou sys.exit(-1) 1105c5f8185bSGleb Kurtsou if opts.dwarfdump: 1106c5f8185bSGleb Kurtsou Config.dwarfdump = opts.dwarfdump 1107c5f8185bSGleb Kurtsou if opts.objdump: 1108c5f8185bSGleb Kurtsou Config.objdump = opts.objdump 1109a1897c0cSGleb Kurtsou if opts.out_orig: 1110a1897c0cSGleb Kurtsou Config.origfile.init(opts.out_orig) 1111a1897c0cSGleb Kurtsou if opts.out_new: 1112a1897c0cSGleb Kurtsou Config.newfile.init(opts.out_new) 1113a1897c0cSGleb Kurtsou if opts.no_dump: 1114a1897c0cSGleb Kurtsou Config.dump = False 1115a1897c0cSGleb Kurtsou Config.no_dump = True 1116a1897c0cSGleb Kurtsou if opts.dump: 1117a1897c0cSGleb Kurtsou Config.dump = True 1118a1897c0cSGleb Kurtsou Config.no_dump = False 1119a1897c0cSGleb Kurtsou Config.verbose = 1 1120a1897c0cSGleb Kurtsou if opts.verbose: 1121a1897c0cSGleb Kurtsou Config.verbose = opts.verbose 1122a1897c0cSGleb Kurtsou if opts.alias_prefix: 1123a1897c0cSGleb Kurtsou Config.alias_prefixes = opts.alias_prefix 1124a1897c0cSGleb Kurtsou Config.alias_prefixes.sort(key=lambda x: -len(x)) 1125a1897c0cSGleb Kurtsou for (k, v) in ({ '_sym': Config.symbol_filter, 1126a1897c0cSGleb Kurtsou '_ver': Config.version_filter }).items(): 1127a1897c0cSGleb Kurtsou for a in [ 'exclude', 'include' ]: 1128a1897c0cSGleb Kurtsou opt = getattr(opts, a + k) 1129a1897c0cSGleb Kurtsou if opt: 1130a1897c0cSGleb Kurtsou getattr(v, a).extend(opt) 1131c5f8185bSGleb Kurtsou if not opts.no_exclude_sym_default: 1132c5f8185bSGleb Kurtsou Config.symbol_filter.exclude.extend(Config.exclude_sym_default) 1133a1897c0cSGleb Kurtsou Config.version_filter.compile() 1134a1897c0cSGleb Kurtsou Config.symbol_filter.compile() 1135a1897c0cSGleb Kurtsou for w in ['w_alias', 'w_cached', 'w_symbol']: 1136a1897c0cSGleb Kurtsou if hasattr(opts, w): 1137a1897c0cSGleb Kurtsou v = getattr(opts, w) 1138a1897c0cSGleb Kurtsou if v != None: 1139a1897c0cSGleb Kurtsou setattr(Config, w, v) 1140a1897c0cSGleb Kurtsou 1141a1897c0cSGleb Kurtsou (Config.origfile.filename, Config.newfile.filename) = (args[0], args[1]) 1142a1897c0cSGleb Kurtsou 1143a1897c0cSGleb Kurtsou origlib = Shlib(Config.origfile.filename) 1144a1897c0cSGleb Kurtsou origlib.parse() 1145a1897c0cSGleb Kurtsou newlib = Shlib(Config.newfile.filename) 1146a1897c0cSGleb Kurtsou newlib.parse() 1147a1897c0cSGleb Kurtsou 1148a1897c0cSGleb Kurtsou commonver = common_symbols(origlib, newlib) 1149a1897c0cSGleb Kurtsou if Config.dump: 1150a1897c0cSGleb Kurtsou dump_symbols(commonver) 1151a1897c0cSGleb Kurtsou cmp_symbols(commonver) 1152a1897c0cSGleb Kurtsou if Config.verbose >= 4: 1153749f65e3SCraig Rodrigues print(Dwarf.cmpcache.stats.show('Cmp')) 1154749f65e3SCraig Rodrigues print(DwarfdumpParser.tagcache_stats.show('Dwarf tag')) 1155a1897c0cSGleb Kurtsou 1156a1897c0cSGleb Kurtsou sys.exit(App.result_code) 1157