1248693Sgleb#!/usr/bin/env python 2248693Sgleb#- 3248693Sgleb# Copyright (c) 2010 Gleb Kurtsou 4248693Sgleb# All rights reserved. 5248693Sgleb# 6248693Sgleb# Redistribution and use in source and binary forms, with or without 7248693Sgleb# modification, are permitted provided that the following conditions 8248693Sgleb# are met: 9248693Sgleb# 1. Redistributions of source code must retain the above copyright 10248693Sgleb# notice, this list of conditions and the following disclaimer. 11248693Sgleb# 2. Redistributions in binary form must reproduce the above copyright 12248693Sgleb# notice, this list of conditions and the following disclaimer in the 13248693Sgleb# documentation and/or other materials provided with the distribution. 14248693Sgleb# 15248693Sgleb# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16248693Sgleb# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17248693Sgleb# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18248693Sgleb# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19248693Sgleb# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20248693Sgleb# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21248693Sgleb# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22248693Sgleb# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23248693Sgleb# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24248693Sgleb# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25248693Sgleb# SUCH DAMAGE. 26248693Sgleb# 27248693Sgleb# $FreeBSD$ 28248693Sgleb 29248693Sglebimport os 30248693Sglebimport sys 31248693Sglebimport re 32248693Sglebimport optparse 33248693Sgleb 34248693Sglebclass Config(object): 35248693Sgleb version = '0.1' 36248693Sgleb # controlled by user 37248693Sgleb verbose = 0 38248693Sgleb dump = False 39248693Sgleb no_dump = False 40248693Sgleb version_filter = None 41248693Sgleb symbol_filter = None 42248693Sgleb alias_prefixes = [] 43248693Sgleb # misc opts 44248693Sgleb objdump = 'objdump' 45248693Sgleb dwarfdump = 'dwarfdump' 46248693Sgleb # debug 47248693Sgleb cmpcache_enabled = True 48248693Sgleb dwarfcache_enabled = True 49248693Sgleb w_alias = True 50248693Sgleb w_cached = False 51248693Sgleb w_symbol = True 52248693Sgleb 53248693Sgleb class FileConfig(object): 54248693Sgleb filename = None 55248693Sgleb out = sys.stdout 56248693Sgleb def init(self, outname): 57248693Sgleb if outname and outname != '-': 58248693Sgleb self.out = open(outname, "w") 59248693Sgleb 60248693Sgleb origfile = FileConfig() 61248693Sgleb newfile = FileConfig() 62248693Sgleb 63248693Sgleb @classmethod 64248693Sgleb def init(cls): 65248693Sgleb cls.version_filter = StrFilter() 66248693Sgleb cls.symbol_filter = StrFilter() 67248693Sgleb 68248693Sglebclass App(object): 69248693Sgleb result_code = 0 70248693Sgleb 71248693Sglebdef warn(cond, msg): 72248693Sgleb if cond: 73248693Sgleb print >> sys.stderr, "WARN: " + msg 74248693Sgleb 75248693Sgleb# {{{ misc 76248693Sgleb 77248693Sglebclass StrFilter(object): 78248693Sgleb def __init__(self): 79248693Sgleb self.exclude = [] 80248693Sgleb self.include = [] 81248693Sgleb 82248693Sgleb def compile(self): 83248693Sgleb self.re_exclude = [ re.compile(x) for x in self.exclude ] 84248693Sgleb self.re_include = [ re.compile(x) for x in self.include ] 85248693Sgleb 86248693Sgleb def match(self, s): 87248693Sgleb if len(self.re_include): 88248693Sgleb matched = False 89248693Sgleb for r in self.re_include: 90248693Sgleb if r.match(s): 91248693Sgleb matched = True 92248693Sgleb break 93248693Sgleb if not matched: 94248693Sgleb return False 95248693Sgleb for r in self.re_exclude: 96248693Sgleb if r.match(s): 97248693Sgleb return False 98248693Sgleb return True 99248693Sgleb 100248693Sglebclass Cache(object): 101248693Sgleb 102248693Sgleb class CacheStats(object): 103248693Sgleb def __init__(self): 104248693Sgleb self.hit = 0 105248693Sgleb self.miss = 0 106248693Sgleb 107248693Sgleb def show(self, name): 108248693Sgleb total = self.hit + self.miss 109248693Sgleb if total == 0: 110248693Sgleb ratio = '(undef)' 111248693Sgleb else: 112248693Sgleb ratio = '%f' % (self.hit/float(total)) 113248693Sgleb return '%s cache stats: hit: %d; miss: %d; ratio: %s' % \ 114248693Sgleb (name, self.hit, self.miss, ratio) 115248693Sgleb 116248693Sgleb def __init__(self, enabled=True, stats=None): 117248693Sgleb self.enabled = enabled 118248693Sgleb self.items = {} 119248693Sgleb if stats == None: 120248693Sgleb self.stats = Cache.CacheStats() 121248693Sgleb else: 122248693Sgleb self.stats = stats 123248693Sgleb 124248693Sgleb def get(self, id): 125248693Sgleb if self.enabled and self.items.has_key(id): 126248693Sgleb self.stats.hit += 1 127248693Sgleb return self.items[id] 128248693Sgleb else: 129248693Sgleb self.stats.miss += 1 130248693Sgleb return None 131248693Sgleb 132248693Sgleb def put(self, id, obj): 133248693Sgleb if self.enabled: 134248693Sgleb if self.items.has_key(id) and obj is not self.items[id]: 135248693Sgleb #raise ValueError("Item is already cached: %d (%s, %s)" % 136248693Sgleb # (id, self.items[id], obj)) 137248693Sgleb warn(Config.w_cached, "Item is already cached: %d (%s, %s)" % \ 138248693Sgleb (id, self.items[id], obj)) 139248693Sgleb self.items[id] = obj 140248693Sgleb 141248693Sgleb def replace(self, id, obj): 142248693Sgleb if self.enabled: 143248693Sgleb assert self.items.has_key(id) 144248693Sgleb self.items[id] = obj 145248693Sgleb 146248693Sglebclass ListDiff(object): 147248693Sgleb def __init__(self, orig, new): 148248693Sgleb self.orig = set(orig) 149248693Sgleb self.new = set(new) 150248693Sgleb self.common = self.orig & self.new 151248693Sgleb self.added = self.new - self.common 152248693Sgleb self.removed = self.orig - self.common 153248693Sgleb 154248693Sglebclass PrettyPrinter(object): 155248693Sgleb def __init__(self): 156248693Sgleb self.stack = [] 157248693Sgleb 158248693Sgleb def run_nested(self, obj): 159248693Sgleb ex = obj._pp_ex(self) 160248693Sgleb self.stack.append(ex) 161248693Sgleb 162248693Sgleb def run(self, obj): 163248693Sgleb self._result = obj._pp(self) 164248693Sgleb return self._result 165248693Sgleb 166248693Sgleb def nested(self): 167248693Sgleb return sorted(set(self.stack)) 168248693Sgleb 169248693Sgleb def result(self): 170248693Sgleb return self._result; 171248693Sgleb 172248693Sgleb# }}} 173248693Sgleb 174248693Sgleb#{{{ symbols and version maps 175248693Sgleb 176248693Sglebclass Symbol(object): 177248693Sgleb def __init__(self, name, offset, version, lib): 178248693Sgleb self.name = name 179248693Sgleb self.offset = offset 180248693Sgleb self.version = version 181248693Sgleb self.lib = lib 182248693Sgleb self.definition = None 183248693Sgleb 184248693Sgleb @property 185248693Sgleb def name_ver(self): 186248693Sgleb return self.name + '@' + self.version 187248693Sgleb 188248693Sgleb def __repr__(self): 189248693Sgleb return "Symbol(%s, 0x%x, %s)" % (self.name, self.offset, self.version) 190248693Sgleb 191248693Sglebclass CommonSymbol(object): 192248693Sgleb def __init__(self, origsym, newsym): 193248693Sgleb if origsym.name != newsym.name or origsym.version != newsym.version: 194248693Sgleb raise RuntimeError("Symbols have different names: %s", 195248693Sgleb [origsym, newsym]) 196248693Sgleb self.origsym = origsym 197248693Sgleb self.newsym = newsym 198248693Sgleb self.name = newsym.name 199248693Sgleb self.version = newsym.version 200248693Sgleb 201248693Sgleb def __repr__(self): 202248693Sgleb return "CommonSymbol(%s, %s)" % (self.name, self.version) 203248693Sgleb 204248693Sglebclass SymbolAlias(object): 205248693Sgleb def __init__(self, alias, prefix, offset): 206248693Sgleb assert alias.startswith(prefix) 207248693Sgleb self.alias = alias 208248693Sgleb self.name = alias[len(prefix):] 209248693Sgleb self.offset = offset 210248693Sgleb 211248693Sgleb def __repr__(self): 212248693Sgleb return "SymbolAlias(%s, 0x%x)" % (self.alias, self.offset) 213248693Sgleb 214248693Sgleb 215248693Sglebclass VersionMap(object): 216248693Sgleb def __init__(self, name): 217248693Sgleb self.name = name 218248693Sgleb self.symbols = {} 219248693Sgleb 220248693Sgleb def append(self, symbol): 221248693Sgleb if (self.symbols.has_key(symbol.name)): 222248693Sgleb raise ValueError("Symbol is already defined %s@%s" % 223248693Sgleb (symbol.name, self.name)) 224248693Sgleb self.symbols[symbol.name] = symbol 225248693Sgleb 226248693Sgleb def names(self): 227248693Sgleb return self.symbols.keys() 228248693Sgleb 229248693Sgleb def __repr__(self): 230248693Sgleb return repr(self.symbols.values()) 231248693Sgleb 232248693Sgleb# }}} 233248693Sgleb 234248693Sgleb# {{{ types and definitions 235248693Sgleb 236248693Sglebclass Def(object): 237248693Sgleb _is_alias = False 238248693Sgleb 239248693Sgleb def __init__(self, id, name, **kwargs): 240248693Sgleb self.id = id 241248693Sgleb self.name = name 242248693Sgleb self.attrs = kwargs 243248693Sgleb 244248693Sgleb def __getattr__(self, attr): 245248693Sgleb if not self.attrs.has_key(attr): 246248693Sgleb raise AttributeError('%s in %s' % (attr, str(self))) 247248693Sgleb return self.attrs[attr] 248248693Sgleb 249248693Sgleb def _name_opt(self, default=''): 250248693Sgleb if not self.name: 251248693Sgleb return default 252248693Sgleb return self.name 253248693Sgleb 254248693Sgleb def _alias(self): 255248693Sgleb if self._is_alias: 256248693Sgleb return self.type._alias() 257248693Sgleb return self 258248693Sgleb 259248693Sgleb def __cmp__(self, other): 260248693Sgleb # TODO assert 'self' and 'other' belong to different libraries 261248693Sgleb #print 'cmp defs: %s, %s' % (self, other) 262248693Sgleb a = self._alias() 263248693Sgleb try: 264248693Sgleb b = other._alias() 265248693Sgleb except AttributeError: 266248693Sgleb return 1 267248693Sgleb r = cmp(a.__class__, b.__class__) 268248693Sgleb if r == 0: 269248693Sgleb if a.id != 0 and b.id != 0: 270248693Sgleb ind = (long(a.id) << 32) + b.id 271248693Sgleb r = Dwarf.cmpcache.get(ind) 272248693Sgleb if r != None: 273248693Sgleb return r 274248693Sgleb else: 275248693Sgleb ind = 0 276248693Sgleb r = cmp(a.attrs, b.attrs) 277248693Sgleb if ind != 0: 278248693Sgleb Dwarf.cmpcache.put(ind, r) 279248693Sgleb else: 280248693Sgleb r = 0 281248693Sgleb #raise RuntimeError('Comparing different classes: %s, %s' % 282248693Sgleb # (a.__class__.__name__, b.__class__.__name__)) 283248693Sgleb return r 284248693Sgleb 285248693Sgleb def __repr__(self): 286248693Sgleb p = [] 287248693Sgleb if hasattr(self, 'name'): 288248693Sgleb p.append("name=%s" % self.name) 289248693Sgleb for (k, v) in self.attrs.items(): 290248693Sgleb if isinstance(v, Def): 291248693Sgleb v = v.__class__.__name__ + '(...)' 292248693Sgleb p.append("%s=%s" % (k, v)) 293248693Sgleb return self.__class__.__name__ + '(' + ', '.join(p) + ')' 294248693Sgleb 295248693Sgleb def _mapval(self, param, vals): 296248693Sgleb if param not in vals.keys(): 297248693Sgleb raise NotImplementedError("Invalid value '%s': %s" % 298248693Sgleb (param, str(self))) 299248693Sgleb return vals[param] 300248693Sgleb 301248693Sgleb def _pp_ex(self, pp): 302248693Sgleb raise NotImplementedError('Extended pretty print not implemeted: %s' % 303248693Sgleb str(self)) 304248693Sgleb 305248693Sgleb def _pp(self, pp): 306248693Sgleb raise NotImplementedError('Pretty print not implemeted: %s' % str(self)) 307248693Sgleb 308248693Sglebclass AnonymousDef(Def): 309248693Sgleb def __init__(self, id, **kwargs): 310248693Sgleb Def.__init__(self, id, None, **kwargs) 311248693Sgleb 312248693Sglebclass Void(AnonymousDef): 313248693Sgleb _instance = None 314248693Sgleb 315248693Sgleb def __new__(cls, *args, **kwargs): 316248693Sgleb if not cls._instance: 317248693Sgleb cls._instance = super(Void, cls).__new__( 318248693Sgleb cls, *args, **kwargs) 319248693Sgleb return cls._instance 320248693Sgleb 321248693Sgleb def __init__(self): 322248693Sgleb AnonymousDef.__init__(self, 0) 323248693Sgleb 324248693Sgleb def _pp(self, pp): 325248693Sgleb return "void" 326248693Sgleb 327248693Sglebclass VarArgs(AnonymousDef): 328248693Sgleb def _pp(self, pp): 329248693Sgleb return "..." 330248693Sgleb 331248693Sglebclass PointerDef(AnonymousDef): 332248693Sgleb def _pp(self, pp): 333248693Sgleb t = pp.run(self.type) 334248693Sgleb return "%s*" % (t,) 335248693Sgleb 336248693Sglebclass BaseTypeDef(Def): 337248693Sgleb inttypes = ['DW_ATE_signed', 'DW_ATE_unsigned', 'DW_ATE_unsigned_char'] 338248693Sgleb def _pp(self, pp): 339248693Sgleb if self.encoding in self.inttypes: 340248693Sgleb sign = '' if self.encoding == 'DW_ATE_signed' else 'u' 341248693Sgleb bits = int(self.byte_size) * 8 342248693Sgleb return '%sint%s_t' % (sign, bits) 343248693Sgleb elif self.encoding == 'DW_ATE_signed_char' and int(self.byte_size) == 1: 344248693Sgleb return 'char'; 345248693Sgleb elif self.encoding == 'DW_ATE_float': 346248693Sgleb return self._mapval(self.byte_size, { 347248693Sgleb '16': 'long double', 348248693Sgleb '8': 'double', 349248693Sgleb '4': 'float', 350248693Sgleb }) 351248693Sgleb raise NotImplementedError('Invalid encoding: %s' % self) 352248693Sgleb 353248693Sglebclass TypeAliasDef(Def): 354248693Sgleb _is_alias = True 355248693Sgleb def _pp(self, pp): 356248693Sgleb alias = self._alias() 357248693Sgleb # push typedef name 358248693Sgleb if self.name and not alias.name: 359248693Sgleb alias.name = 'T(%s)' % self.name 360248693Sgleb # return type with modifiers 361248693Sgleb return self.type._pp(pp) 362248693Sgleb 363248693Sglebclass EnumerationTypeDef(Def): 364248693Sgleb def _pp(self, pp): 365248693Sgleb return 'enum ' + self._name_opt('UNKNOWN') 366248693Sgleb 367248693Sglebclass ConstTypeDef(AnonymousDef): 368248693Sgleb _is_alias = True 369248693Sgleb def _pp(self, pp): 370248693Sgleb return 'const ' + self.type._pp(pp) 371248693Sgleb 372248693Sglebclass VolatileTypeDef(AnonymousDef): 373248693Sgleb _is_alias = True 374248693Sgleb def _pp(self, pp): 375248693Sgleb return 'volatile ' + self.type._pp(pp) 376248693Sgleb 377248693Sglebclass ArrayDef(AnonymousDef): 378248693Sgleb def _pp(self, pp): 379248693Sgleb t = pp.run(self.type) 380248693Sgleb assert len(self.subranges) == 1 381248693Sgleb try: 382248693Sgleb sz = int(self.subranges[0].upper_bound) + 1 383248693Sgleb except ValueError: 384248693Sgleb s = re.sub(r'\(.+\)', '', self.subranges[0].upper_bound) 385248693Sgleb sz = int(s) + 1 386248693Sgleb return '%s[%s]' % (t, sz) 387248693Sgleb 388248693Sglebclass ArraySubrangeDef(AnonymousDef): 389248693Sgleb pass 390248693Sgleb 391248693Sglebclass FunctionDef(Def): 392248693Sgleb def _pp(self, pp): 393248693Sgleb result = pp.run(self.result) 394248693Sgleb if not self.params: 395248693Sgleb params = "void" 396248693Sgleb else: 397248693Sgleb params = ', '.join([ pp.run(x) for x in self.params ]) 398248693Sgleb return "%s %s(%s);" % (result, self.name, params) 399248693Sgleb 400248693Sglebclass FunctionTypeDef(Def): 401248693Sgleb def _pp(self, pp): 402248693Sgleb result = pp.run(self.result) 403248693Sgleb if not self.params: 404248693Sgleb params = "void" 405248693Sgleb else: 406248693Sgleb params = ', '.join([ pp.run(x) for x in self.params ]) 407248693Sgleb return "F(%s, %s, (%s))" % (self._name_opt(), result, params) 408248693Sgleb 409248693Sglebclass ParameterDef(Def): 410248693Sgleb def _pp(self, pp): 411248693Sgleb t = pp.run(self.type) 412248693Sgleb return "%s %s" % (t, self._name_opt()) 413248693Sgleb 414248693Sgleb# TODO 415248693Sglebclass StructForwardDef(Def): 416248693Sgleb pass 417248693Sgleb 418248693Sglebclass IncompleteDef(Def): 419248693Sgleb def update(self, complete, cache=None): 420248693Sgleb self.complete = complete 421248693Sgleb complete.incomplete = self 422248693Sgleb if cache != None: 423248693Sgleb cached = cache.get(self.id) 424248693Sgleb if cached != None and isinstance(cached, IncompleteDef): 425248693Sgleb cache.replace(self.id, complete) 426248693Sgleb 427248693Sglebclass StructIncompleteDef(IncompleteDef): 428248693Sgleb def _pp(self, pp): 429248693Sgleb return "struct %s" % (self.name,) 430248693Sgleb 431248693Sglebclass UnionIncompleteDef(IncompleteDef): 432248693Sgleb def _pp(self, pp): 433248693Sgleb return "union %s" % (self.name,) 434248693Sgleb 435248693Sglebclass StructDef(Def): 436248693Sgleb def _pp_ex(self, pp, suffix=';'): 437248693Sgleb members = [ pp.run(x) for x in self.members ] 438248693Sgleb return "struct %s { %s }%s" % \ 439248693Sgleb (self._name_opt(), ' '.join(members), suffix) 440248693Sgleb def _pp(self, pp): 441248693Sgleb if self.name: 442248693Sgleb pp.run_nested(self) 443248693Sgleb return "struct %s" % (self.name,) 444248693Sgleb else: 445248693Sgleb return self._pp_ex(pp, suffix='') 446248693Sgleb 447248693Sglebclass UnionDef(Def): 448248693Sgleb def _pp_ex(self, pp, suffix=';'): 449248693Sgleb members = [ pp.run(x) for x in self.members ] 450248693Sgleb return "union %s { %s }%s" % \ 451248693Sgleb (self._name_opt(), ' '.join(members), suffix) 452248693Sgleb def _pp(self, pp): 453248693Sgleb if self.name: 454248693Sgleb pp.run_nested(self) 455248693Sgleb return "union %s" % (self.name,) 456248693Sgleb else: 457248693Sgleb return self._pp_ex(pp, suffix='') 458248693Sgleb 459248693Sglebclass MemberDef(Def): 460248693Sgleb def _pp(self, pp): 461248693Sgleb t = pp.run(self.type) 462248693Sgleb if self.bit_size: 463248693Sgleb bits = ":%s" % self.bit_size 464248693Sgleb else: 465248693Sgleb bits = "" 466248693Sgleb return "%s %s%s;" % (t, self._name_opt(), bits) 467248693Sgleb 468248693Sglebclass Dwarf(object): 469248693Sgleb 470248693Sgleb cmpcache = Cache(enabled=Config.cmpcache_enabled) 471248693Sgleb 472248693Sgleb def __init__(self, dump): 473248693Sgleb self.dump = dump 474248693Sgleb 475248693Sgleb def _build_optarg_type(self, praw): 476248693Sgleb type = praw.optarg('type', Void()) 477248693Sgleb if type != Void(): 478248693Sgleb type = self.buildref(praw.unit, type) 479248693Sgleb return type 480248693Sgleb 481248693Sgleb def build_subprogram(self, raw): 482248693Sgleb if raw.optname == None: 483248693Sgleb raw.setname('SUBPROGRAM_NONAME_' + raw.arg('low_pc')); 484248693Sgleb params = [ self.build(x) for x in raw.nested ] 485248693Sgleb result = self._build_optarg_type(raw) 486248693Sgleb return FunctionDef(raw.id, raw.name, params=params, result=result) 487248693Sgleb 488248693Sgleb def build_subroutine_type(self, raw): 489248693Sgleb params = [ self.build(x) for x in raw.nested ] 490248693Sgleb result = self._build_optarg_type(raw) 491248693Sgleb return FunctionTypeDef(raw.id, raw.optname, params=params, result=result) 492248693Sgleb 493248693Sgleb def build_formal_parameter(self, raw): 494248693Sgleb type = self._build_optarg_type(raw) 495248693Sgleb return ParameterDef(raw.id, raw.optname, type=type) 496248693Sgleb 497248693Sgleb def build_pointer_type(self, raw): 498248693Sgleb type = self._build_optarg_type(raw) 499248693Sgleb return PointerDef(raw.id, type=type) 500248693Sgleb 501248693Sgleb def build_member(self, raw): 502248693Sgleb type = self.buildref(raw.unit, raw.arg('type')) 503248693Sgleb return MemberDef(raw.id, raw.name, type=type, 504248693Sgleb bit_size=raw.optarg('bit_size', None)) 505248693Sgleb 506248693Sgleb def build_structure_type(self, raw): 507248693Sgleb incomplete = raw.unit.incomplete.get(raw.id) 508248693Sgleb if incomplete == None: 509248693Sgleb incomplete = StructIncompleteDef(raw.id, raw.optname) 510248693Sgleb raw.unit.incomplete.put(raw.id, incomplete) 511248693Sgleb else: 512248693Sgleb return incomplete 513248693Sgleb members = [ self.build(x) for x in raw.nested ] 514248693Sgleb byte_size = raw.optarg('byte_size', None) 515248693Sgleb if byte_size == None: 516248693Sgleb obj = StructForwardDef(raw.id, raw.name, members=members, 517248693Sgleb forcename=raw.name) 518248693Sgleb obj = StructDef(raw.id, raw.optname, members=members, 519248693Sgleb byte_size=byte_size) 520248693Sgleb incomplete.update(obj, cache=raw.unit.cache) 521248693Sgleb return obj 522248693Sgleb 523248693Sgleb def build_union_type(self, raw): 524248693Sgleb incomplete = raw.unit.incomplete.get(raw.id) 525248693Sgleb if incomplete == None: 526248693Sgleb incomplete = UnionIncompleteDef(raw.id, raw.optname) 527248693Sgleb raw.unit.incomplete.put(raw.id, incomplete) 528248693Sgleb else: 529248693Sgleb return incomplete 530248693Sgleb members = [ self.build(x) for x in raw.nested ] 531248693Sgleb byte_size = raw.optarg('byte_size', None) 532248693Sgleb obj = UnionDef(raw.id, raw.optname, members=members, 533248693Sgleb byte_size=byte_size) 534248693Sgleb obj.incomplete = incomplete 535248693Sgleb incomplete.complete = obj 536248693Sgleb return obj 537248693Sgleb 538248693Sgleb def build_typedef(self, raw): 539248693Sgleb type = self._build_optarg_type(raw) 540248693Sgleb return TypeAliasDef(raw.id, raw.name, type=type) 541248693Sgleb 542248693Sgleb def build_const_type(self, raw): 543248693Sgleb type = self._build_optarg_type(raw) 544248693Sgleb return ConstTypeDef(raw.id, type=type) 545248693Sgleb 546248693Sgleb def build_volatile_type(self, raw): 547248693Sgleb type = self._build_optarg_type(raw) 548248693Sgleb return VolatileTypeDef(raw.id, type=type) 549248693Sgleb 550248693Sgleb def build_enumeration_type(self, raw): 551248693Sgleb # TODO handle DW_TAG_enumerator ??? 552248693Sgleb return EnumerationTypeDef(raw.id, name=raw.optname, 553248693Sgleb byte_size=raw.arg('byte_size')) 554248693Sgleb 555248693Sgleb def build_base_type(self, raw): 556248693Sgleb return BaseTypeDef(raw.id, raw.optname, 557248693Sgleb byte_size=raw.arg('byte_size'), encoding=raw.arg('encoding')) 558248693Sgleb 559248693Sgleb def build_array_type(self, raw): 560248693Sgleb type = self.buildref(raw.unit, raw.arg('type')) 561248693Sgleb subranges = [ self.build(x) for x in raw.nested ] 562248693Sgleb return ArrayDef(raw.id, type=type, subranges=subranges) 563248693Sgleb 564248693Sgleb def build_subrange_type(self, raw): 565248693Sgleb type = self.buildref(raw.unit, raw.arg('type')) 566248693Sgleb return ArraySubrangeDef(raw.id, type=type, 567248693Sgleb upper_bound=raw.optarg('upper_bound', 0)) 568248693Sgleb 569248693Sgleb def build_unspecified_parameters(self, raw): 570248693Sgleb return VarArgs(raw.id) 571248693Sgleb 572248693Sgleb def _get_id(self, id): 573248693Sgleb try: 574248693Sgleb return int(id) 575248693Sgleb except ValueError: 576248693Sgleb if (id.startswith('<') and id.endswith('>')): 577248693Sgleb return int(id[1:-1]) 578248693Sgleb else: 579248693Sgleb raise ValueError("Invalid dwarf id: %s" % id) 580248693Sgleb 581248693Sgleb def build(self, raw): 582248693Sgleb obj = raw.unit.cache.get(raw.id) 583248693Sgleb if obj != None: 584248693Sgleb return obj 585248693Sgleb builder_name = raw.tag.replace('DW_TAG_', 'build_') 586248693Sgleb try: 587248693Sgleb builder = getattr(self, builder_name) 588248693Sgleb except AttributeError: 589248693Sgleb raise AttributeError("Unknown dwarf tag: %s" % raw) 590248693Sgleb obj = builder(raw) 591248693Sgleb raw.unit.cache.put(obj.id, obj) 592248693Sgleb return obj 593248693Sgleb 594248693Sgleb def buildref(self, unit, id): 595248693Sgleb id = self._get_id(id) 596248693Sgleb raw = unit.tags[id] 597248693Sgleb obj = self.build(raw) 598248693Sgleb return obj 599248693Sgleb 600248693Sgleb# }}} 601248693Sgleb 602248693Sglebclass Shlib(object): 603248693Sgleb def __init__(self, libfile): 604248693Sgleb self.libfile = libfile 605248693Sgleb self.versions = {} 606248693Sgleb self.alias_syms = {} 607248693Sgleb 608248693Sgleb def parse_objdump(self): 609248693Sgleb objdump = ObjdumpParser(self.libfile) 610248693Sgleb objdump.run() 611248693Sgleb for p in objdump.dynamic_symbols: 612248693Sgleb vername = p['ver'] 613248693Sgleb if vername.startswith('(') and vername.endswith(')'): 614248693Sgleb vername = vername[1:-1] 615248693Sgleb if not Config.version_filter.match(vername): 616248693Sgleb continue 617248693Sgleb if not Config.symbol_filter.match(p['symbol']): 618248693Sgleb continue 619248693Sgleb sym = Symbol(p['symbol'], p['offset'], vername, self) 620248693Sgleb if not self.versions.has_key(vername): 621248693Sgleb self.versions[vername] = VersionMap(vername) 622248693Sgleb self.versions[vername].append(sym) 623248693Sgleb if Config.alias_prefixes: 624248693Sgleb self.local_offsetmap = objdump.local_offsetmap 625248693Sgleb for p in objdump.local_symbols: 626248693Sgleb for prefix in Config.alias_prefixes: 627248693Sgleb if not p['symbol'].startswith(prefix): 628248693Sgleb continue 629248693Sgleb alias = SymbolAlias(p['symbol'], prefix, p['offset']) 630248693Sgleb if self.alias_syms.has_key(alias.name): 631248693Sgleb prevalias = self.alias_syms[alias.name] 632248693Sgleb if alias.name != prevalias.name or \ 633248693Sgleb alias.offset != prevalias.offset: 634248693Sgleb warn(Config.w_alias, "Symbol alias is " \ 635248693Sgleb "already defined: %s: %s at %08x -- %s at %08x" % \ 636248693Sgleb (alias.alias, alias.name, alias.offset, 637248693Sgleb prevalias.name, prevalias.offset)) 638248693Sgleb self.alias_syms[alias.name] = alias 639248693Sgleb 640248693Sgleb def parse_dwarfdump(self): 641248693Sgleb dwarfdump = DwarfdumpParser(self.libfile) 642248693Sgleb def lookup(sym): 643248693Sgleb raw = None 644248693Sgleb try: 645248693Sgleb raw = dwarfdump.offsetmap[sym.offset] 646248693Sgleb except: 647248693Sgleb try: 648248693Sgleb localnames = self.local_offsetmap[sym.offset] 649248693Sgleb localnames.sort(key=lambda x: -len(x)) 650248693Sgleb for localname in localnames: 651248693Sgleb if not self.alias_syms.has_key(localname): 652248693Sgleb continue 653248693Sgleb alias = self.alias_syms[localname] 654248693Sgleb raw = dwarfdump.offsetmap[alias.offset] 655248693Sgleb break 656248693Sgleb except: 657248693Sgleb pass 658248693Sgleb return raw 659248693Sgleb dwarfdump.run() 660248693Sgleb dwarf = Dwarf(dwarfdump) 661248693Sgleb for ver in self.versions.values(): 662248693Sgleb for sym in ver.symbols.values(): 663248693Sgleb raw = lookup(sym); 664248693Sgleb if not raw: 665248693Sgleb warn(Config.w_symbol, "Symbol %s (%s) not found at offset 0x%x" % \ 666248693Sgleb (sym.name_ver, self.libfile, sym.offset)) 667248693Sgleb continue 668248693Sgleb if Config.verbose >= 3: 669248693Sgleb print "Parsing symbol %s (%s)" % (sym.name_ver, self.libfile) 670248693Sgleb sym.definition = dwarf.build(raw) 671248693Sgleb 672248693Sgleb def parse(self): 673248693Sgleb if not os.path.isfile(self.libfile): 674248693Sgleb print >> sys.stderr, ("No such file: %s" % self.libfile) 675248693Sgleb sys.exit(1) 676248693Sgleb self.parse_objdump() 677248693Sgleb self.parse_dwarfdump() 678248693Sgleb 679248693Sgleb# {{{ parsers 680248693Sgleb 681248693Sglebclass Parser(object): 682248693Sgleb def __init__(self, proc): 683248693Sgleb self.proc = proc 684248693Sgleb self.parser = self.parse_begin 685248693Sgleb 686248693Sgleb def run(self): 687248693Sgleb fd = os.popen(self.proc, 'r') 688248693Sgleb while True: 689248693Sgleb line = fd.readline() 690248693Sgleb if (not line): 691248693Sgleb break 692248693Sgleb line = line.strip() 693248693Sgleb if (line): 694248693Sgleb self.parser(line) 695248693Sgleb err = fd.close() 696248693Sgleb if err: 697248693Sgleb print >> sys.stderr, ("Execution failed: %s" % self.proc) 698248693Sgleb sys.exit(2) 699248693Sgleb 700248693Sgleb def parse_begin(self, line): 701248693Sgleb print(line) 702248693Sgleb 703248693Sglebclass ObjdumpParser(Parser): 704248693Sgleb 705248693Sgleb re_header = re.compile('(?P<table>\w*)\s*SYMBOL TABLE:') 706248693Sgleb 707248693Sgleb 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]*)') 708248693Sgleb re_lame_symbol = re.compile('(?P<offset>[0-9a-fA-F]+)\s+(?P<bind>\w+)\s+\*[A-Z]+\*') 709248693Sgleb 710248693Sgleb 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]*)') 711248693Sgleb 712248693Sgleb def __init__(self, libfile): 713248693Sgleb Parser.__init__(self, "%s -wtT %s" % (Config.objdump, libfile)) 714248693Sgleb self.dynamic_symbols = [] 715248693Sgleb self.local_symbols = [] 716248693Sgleb self.local_offsetmap = {} 717248693Sgleb 718248693Sgleb def parse_begin(self, line): 719248693Sgleb self.parse_header(line) 720248693Sgleb 721248693Sgleb def add_symbol(self, table, symbol, offsetmap = None): 722248693Sgleb offset = int(symbol['offset'], 16); 723248693Sgleb symbol['offset'] = offset 724248693Sgleb if (offset == 0): 725248693Sgleb return 726248693Sgleb table.append(symbol) 727248693Sgleb if offsetmap != None: 728248693Sgleb if not offsetmap.has_key(offset): 729248693Sgleb offsetmap[offset] = [symbol['symbol']] 730248693Sgleb else: 731248693Sgleb offsetmap[offset].append(symbol['symbol']) 732248693Sgleb 733248693Sgleb def parse_header(self, line): 734248693Sgleb m = self.re_header.match(line) 735248693Sgleb if (m): 736248693Sgleb table = m.group('table') 737248693Sgleb if (table == "DYNAMIC"): 738248693Sgleb self.parser = self.parse_dynamic 739248693Sgleb elif table == '': 740248693Sgleb self.parser = self.parse_local 741248693Sgleb else: 742248693Sgleb raise ValueError("Invalid symbol table: %s" % table) 743248693Sgleb return True 744248693Sgleb return False 745248693Sgleb 746248693Sgleb def parse_local(self, line): 747248693Sgleb if (self.parse_header(line)): 748248693Sgleb return 749248693Sgleb if (self.re_lame_symbol.match(line)): 750248693Sgleb return 751248693Sgleb m = self.re_local_symbol.match(line) 752248693Sgleb if (not m): 753248693Sgleb return 754248693Sgleb #raise ValueError("Invalid symbol definition: %s" % line) 755248693Sgleb p = m.groupdict() 756248693Sgleb if (p['symbol'] and p['symbol'].find('@') == -1): 757248693Sgleb self.add_symbol(self.local_symbols, p, self.local_offsetmap); 758248693Sgleb 759248693Sgleb def parse_dynamic(self, line): 760248693Sgleb if (self.parse_header(line)): 761248693Sgleb return 762248693Sgleb if (self.re_lame_symbol.match(line)): 763248693Sgleb return 764248693Sgleb m = self.re_dynamic_symbol.match(line) 765248693Sgleb if (not m): 766248693Sgleb raise ValueError("Invalid symbol definition: %s" % line) 767248693Sgleb p = m.groupdict() 768248693Sgleb if (p['symbol'] and p['ver']): 769248693Sgleb self.add_symbol(self.dynamic_symbols, p); 770248693Sgleb 771248693Sglebclass DwarfdumpParser(Parser): 772248693Sgleb 773248693Sgleb tagcache_stats = Cache.CacheStats() 774248693Sgleb 775248693Sgleb class Unit(object): 776248693Sgleb def __init__(self): 777248693Sgleb self.cache = Cache(enabled=Config.dwarfcache_enabled, 778248693Sgleb stats=DwarfdumpParser.tagcache_stats) 779248693Sgleb self.incomplete = Cache() 780248693Sgleb self.tags = {} 781248693Sgleb 782248693Sgleb class Tag(object): 783248693Sgleb def __init__(self, unit, data): 784248693Sgleb self.unit = unit 785248693Sgleb self.id = int(data['id']) 786248693Sgleb self.level = int(data['level']) 787248693Sgleb self.tag = data['tag'] 788248693Sgleb self.args = {} 789248693Sgleb self.nested = [] 790248693Sgleb 791248693Sgleb @property 792248693Sgleb def name(self): 793248693Sgleb return self.arg('name') 794248693Sgleb 795248693Sgleb @property 796248693Sgleb def optname(self): 797248693Sgleb return self.optarg('name', None) 798248693Sgleb 799248693Sgleb def setname(self, name): 800248693Sgleb self.args['DW_AT_name'] = name 801248693Sgleb 802248693Sgleb def arg(self, a): 803248693Sgleb name = 'DW_AT_' + a 804248693Sgleb try: 805248693Sgleb return self.args[name] 806248693Sgleb except KeyError: 807248693Sgleb raise KeyError("Argument '%s' not found in %s: %s" % 808248693Sgleb (name, self, self.args)) 809248693Sgleb 810248693Sgleb def optarg(self, a, default): 811248693Sgleb try: 812248693Sgleb return self.arg(a) 813248693Sgleb except KeyError: 814248693Sgleb return default 815248693Sgleb 816248693Sgleb def __repr__(self): 817248693Sgleb return "Tag(%d, %d, %s)" % (self.level, self.id, self.tag) 818248693Sgleb 819248693Sgleb re_header = re.compile('<(?P<level>\d+)><(?P<id>\d+\+*\d*)><(?P<tag>\w+)>') 820248693Sgleb re_argname = re.compile('(?P<arg>\w+)<') 821248693Sgleb re_argunknown = re.compile('<Unknown AT value \w+><[^<>]+>') 822248693Sgleb 823248693Sgleb skip_tags = set([ 824248693Sgleb 'DW_TAG_lexical_block', 825248693Sgleb 'DW_TAG_inlined_subroutine', 826248693Sgleb 'DW_TAG_label', 827248693Sgleb 'DW_TAG_variable', 828248693Sgleb ]) 829248693Sgleb 830248693Sgleb def __init__(self, libfile): 831248693Sgleb Parser.__init__(self, "%s -di %s" % (Config.dwarfdump, libfile)) 832248693Sgleb self.current_unit = None 833248693Sgleb self.offsetmap = {} 834248693Sgleb self.stack = [] 835248693Sgleb 836248693Sgleb def parse_begin(self, line): 837248693Sgleb if line == '.debug_info': 838248693Sgleb self.parser = self.parse_debuginfo 839248693Sgleb else: 840248693Sgleb raise ValueError("Invalid dwarfdump header: %s" % line) 841248693Sgleb 842248693Sgleb def parse_argvalue(self, args): 843248693Sgleb assert args.startswith('<') 844248693Sgleb i = 1 845248693Sgleb cnt = 1 846248693Sgleb while i < len(args) and args[i]: 847248693Sgleb if args[i] == '<': 848248693Sgleb cnt += 1 849248693Sgleb elif args[i] == '>': 850248693Sgleb cnt -= 1 851248693Sgleb if cnt == 0: 852248693Sgleb break 853248693Sgleb i = i + 1 854248693Sgleb value = args[1:i] 855248693Sgleb args = args[i+1:] 856248693Sgleb return (args, value) 857248693Sgleb 858248693Sgleb def parse_arg(self, tag, args): 859248693Sgleb m = self.re_argname.match(args) 860248693Sgleb if not m: 861248693Sgleb m = self.re_argunknown.match(args) 862248693Sgleb if not m: 863248693Sgleb raise ValueError("Invalid dwarfdump: couldn't parse arguments: %s" % 864248693Sgleb args) 865248693Sgleb args = args[len(m.group(0)):].lstrip() 866248693Sgleb return args 867248693Sgleb argname = m.group('arg') 868248693Sgleb args = args[len(argname):] 869248693Sgleb value = [] 870248693Sgleb while len(args) > 0 and args.startswith('<'): 871248693Sgleb (args, v) = self.parse_argvalue(args) 872248693Sgleb value.append(v) 873248693Sgleb args = args.lstrip() 874248693Sgleb if len(value) == 1: 875248693Sgleb value = value[0] 876248693Sgleb tag.args[argname] = value 877248693Sgleb return args 878248693Sgleb 879248693Sgleb def parse_debuginfo(self, line): 880248693Sgleb m = self.re_header.match(line) 881248693Sgleb if not m: 882248693Sgleb raise ValueError("Invalid dwarfdump: %s" % line) 883248693Sgleb if m.group('level') == '0': 884248693Sgleb self.current_unit = DwarfdumpParser.Unit() 885248693Sgleb return 886248693Sgleb tag = DwarfdumpParser.Tag(self.current_unit, m.groupdict()) 887248693Sgleb args = line[len(m.group(0)):].lstrip() 888248693Sgleb while args: 889248693Sgleb args = self.parse_arg(tag, args) 890248693Sgleb tag.unit.tags[tag.id] = tag 891248693Sgleb if tag.args.has_key('DW_AT_low_pc') and \ 892248693Sgleb tag.tag not in DwarfdumpParser.skip_tags: 893248693Sgleb offset = int(tag.args['DW_AT_low_pc'], 16) 894248693Sgleb if self.offsetmap.has_key(offset): 895248693Sgleb raise ValueError("Dwarf dump parse error: " + 896248693Sgleb "symbol is aleady defined at offset 0x%x" % offset) 897248693Sgleb self.offsetmap[offset] = tag 898248693Sgleb if len(self.stack) > 0: 899248693Sgleb prev = self.stack.pop() 900248693Sgleb while prev.level >= tag.level and len(self.stack) > 0: 901248693Sgleb prev = self.stack.pop() 902248693Sgleb if prev.level < tag.level: 903248693Sgleb assert prev.level == tag.level - 1 904248693Sgleb # TODO check DW_AT_sibling ??? 905248693Sgleb if tag.tag not in DwarfdumpParser.skip_tags: 906248693Sgleb prev.nested.append(tag) 907248693Sgleb self.stack.append(prev) 908248693Sgleb self.stack.append(tag) 909248693Sgleb assert len(self.stack) == tag.level 910248693Sgleb 911248693Sgleb# }}} 912248693Sgleb 913248693Sglebdef list_str(l): 914248693Sgleb l = [ str(x) for x in l ] 915248693Sgleb l.sort() 916248693Sgleb return ', '.join(l) 917248693Sgleb 918248693Sglebdef names_ver_str(vername, names): 919248693Sgleb return list_str([ x + "@" + vername for x in names ]) 920248693Sgleb 921248693Sglebdef common_symbols(origlib, newlib): 922248693Sgleb result = [] 923248693Sgleb verdiff = ListDiff(origlib.versions.keys(), newlib.versions.keys()) 924248693Sgleb if Config.verbose >= 1: 925248693Sgleb print 'Original versions: ', list_str(verdiff.orig) 926248693Sgleb print 'New versions: ', list_str(verdiff.new) 927248693Sgleb for vername in verdiff.added: 928248693Sgleb print 'Added version: ', vername 929248693Sgleb print ' Added symbols: ', \ 930248693Sgleb names_ver_str(vername, newlib.versions[vername].names()) 931248693Sgleb for vername in verdiff.removed: 932248693Sgleb print 'Removed version: ', vername 933248693Sgleb print ' Removed symbols: ', \ 934248693Sgleb names_ver_str(vername, origlib.versions[vername].names()) 935248693Sgleb added = [] 936248693Sgleb removed = [] 937248693Sgleb for vername in verdiff.common: 938248693Sgleb origver = origlib.versions[vername] 939248693Sgleb newver = newlib.versions[vername] 940248693Sgleb namediff = ListDiff(origver.names(), newver.names()) 941248693Sgleb if namediff.added: 942248693Sgleb added.append(names_ver_str(vername, namediff.added)) 943248693Sgleb if namediff.removed: 944248693Sgleb removed.append(names_ver_str(vername, namediff.removed)) 945248693Sgleb commonver = VersionMap(vername) 946248693Sgleb result.append(commonver) 947248693Sgleb for n in namediff.common: 948248693Sgleb sym = CommonSymbol(origver.symbols[n], newver.symbols[n]) 949248693Sgleb commonver.append(sym) 950248693Sgleb if added: 951248693Sgleb print 'Added symbols:' 952248693Sgleb for i in added: 953248693Sgleb print ' ', i 954248693Sgleb if removed: 955248693Sgleb print 'Removed symbols:' 956248693Sgleb for i in removed: 957248693Sgleb print ' ', i 958248693Sgleb return result 959248693Sgleb 960248693Sglebdef cmp_symbols(commonver): 961248693Sgleb for ver in commonver: 962248693Sgleb names = ver.names(); 963248693Sgleb names.sort() 964248693Sgleb for symname in names: 965248693Sgleb sym = ver.symbols[symname] 966248693Sgleb match = sym.origsym.definition == sym.newsym.definition 967248693Sgleb if not match: 968248693Sgleb App.result_code = 1 969248693Sgleb if Config.verbose >= 1 or not match: 970248693Sgleb print '%s: definitions %smatch' % \ 971248693Sgleb (sym.origsym.name_ver, "" if match else "mis") 972248693Sgleb if Config.dump or (not match and not Config.no_dump): 973248693Sgleb for x in [(sym.origsym, Config.origfile), 974248693Sgleb (sym.newsym, Config.newfile)]: 975248693Sgleb xsym = x[0] 976248693Sgleb xout = x[1].out 977248693Sgleb if not xsym.definition: 978248693Sgleb print >> xout, '\n// Definition not found: %s %s' % \ 979248693Sgleb (xsym.name_ver, xsym.lib.libfile) 980248693Sgleb continue 981248693Sgleb print >> xout, '\n// Definitions mismatch: %s %s' % \ 982248693Sgleb (xsym.name_ver, xsym.lib.libfile) 983248693Sgleb pp = PrettyPrinter() 984248693Sgleb pp.run(xsym.definition) 985248693Sgleb for i in pp.nested(): 986248693Sgleb print >> xout, i 987248693Sgleb print >> xout, pp.result() 988248693Sgleb 989248693Sglebdef dump_symbols(commonver): 990248693Sgleb class SymbolDump(object): 991248693Sgleb def __init__(self, io_conf): 992248693Sgleb self.io_conf = io_conf 993248693Sgleb self.pp = PrettyPrinter() 994248693Sgleb self.res = [] 995248693Sgleb def run(self, sym): 996248693Sgleb r = self.pp.run(sym.definition) 997248693Sgleb self.res.append('/* %s@%s */ %s' % (sym.name, sym.version, r)) 998248693Sgleb def finish(self): 999248693Sgleb print >> self.io_conf.out, '\n// Symbol dump: version %s, library %s' % \ 1000248693Sgleb (ver.name, self.io_conf.filename) 1001248693Sgleb for i in self.pp.nested(): 1002248693Sgleb print >> self.io_conf.out, i 1003248693Sgleb print >> self.io_conf.out, '' 1004248693Sgleb for i in self.res: 1005248693Sgleb print >> self.io_conf.out, i 1006248693Sgleb for ver in commonver: 1007248693Sgleb names = sorted(ver.names()); 1008248693Sgleb d_orig = SymbolDump(Config.origfile) 1009248693Sgleb d_new = SymbolDump(Config.newfile) 1010248693Sgleb for symname in names: 1011248693Sgleb sym = ver.symbols[symname] 1012248693Sgleb if not sym.origsym.definition or not sym.newsym.definition: 1013248693Sgleb # XXX 1014248693Sgleb warn(Config.w_symbol, 'Missing symbol definition: %s@%s' % \ 1015248693Sgleb (symname, ver.name)) 1016248693Sgleb continue 1017248693Sgleb d_orig.run(sym.origsym) 1018248693Sgleb d_new.run(sym.newsym) 1019248693Sgleb d_orig.finish() 1020248693Sgleb d_new.finish() 1021248693Sgleb 1022248693Sglebif __name__ == '__main__': 1023248693Sgleb Config.init() 1024248693Sgleb parser = optparse.OptionParser(usage="usage: %prog origlib newlib", 1025248693Sgleb version="%prog " + Config.version) 1026248693Sgleb parser.add_option('-v', '--verbose', action='count', 1027248693Sgleb help="verbose mode, may be specified several times") 1028248693Sgleb parser.add_option('--alias-prefix', action='append', 1029248693Sgleb help="name prefix to try for symbol alias lookup", metavar="STR") 1030248693Sgleb parser.add_option('--dump', action='store_true', 1031248693Sgleb help="dump symbol definitions") 1032248693Sgleb parser.add_option('--no-dump', action='store_true', 1033248693Sgleb help="disable dump for mismatched symbols") 1034248693Sgleb parser.add_option('--out-orig', action='store', 1035248693Sgleb help="result output file for original library", metavar="ORIGFILE") 1036248693Sgleb parser.add_option('--out-new', action='store', 1037248693Sgleb help="result output file for new library", metavar="NEWFILE") 1038248693Sgleb parser.add_option('--exclude-ver', action='append', metavar="RE") 1039248693Sgleb parser.add_option('--include-ver', action='append', metavar="RE") 1040248693Sgleb parser.add_option('--exclude-sym', action='append', metavar="RE") 1041248693Sgleb parser.add_option('--include-sym', action='append', metavar="RE") 1042248693Sgleb for opt in ['alias', 'cached', 'symbol']: 1043248693Sgleb parser.add_option("--w-" + opt, 1044248693Sgleb action="store_true", dest="w_" + opt) 1045248693Sgleb parser.add_option("--w-no-" + opt, 1046248693Sgleb action="store_false", dest="w_" + opt) 1047248693Sgleb (opts, args) = parser.parse_args() 1048248693Sgleb 1049248693Sgleb if len(args) != 2: 1050248693Sgleb parser.print_help() 1051248693Sgleb sys.exit(-1) 1052248693Sgleb if opts.out_orig: 1053248693Sgleb Config.origfile.init(opts.out_orig) 1054248693Sgleb if opts.out_new: 1055248693Sgleb Config.newfile.init(opts.out_new) 1056248693Sgleb if opts.no_dump: 1057248693Sgleb Config.dump = False 1058248693Sgleb Config.no_dump = True 1059248693Sgleb if opts.dump: 1060248693Sgleb Config.dump = True 1061248693Sgleb Config.no_dump = False 1062248693Sgleb Config.verbose = 1 1063248693Sgleb if opts.verbose: 1064248693Sgleb Config.verbose = opts.verbose 1065248693Sgleb if opts.alias_prefix: 1066248693Sgleb Config.alias_prefixes = opts.alias_prefix 1067248693Sgleb Config.alias_prefixes.sort(key=lambda x: -len(x)) 1068248693Sgleb for (k, v) in ({ '_sym': Config.symbol_filter, 1069248693Sgleb '_ver': Config.version_filter }).items(): 1070248693Sgleb for a in [ 'exclude', 'include' ]: 1071248693Sgleb opt = getattr(opts, a + k) 1072248693Sgleb if opt: 1073248693Sgleb getattr(v, a).extend(opt) 1074248693Sgleb Config.version_filter.compile() 1075248693Sgleb Config.symbol_filter.compile() 1076248693Sgleb for w in ['w_alias', 'w_cached', 'w_symbol']: 1077248693Sgleb if hasattr(opts, w): 1078248693Sgleb v = getattr(opts, w) 1079248693Sgleb if v != None: 1080248693Sgleb setattr(Config, w, v) 1081248693Sgleb 1082248693Sgleb (Config.origfile.filename, Config.newfile.filename) = (args[0], args[1]) 1083248693Sgleb 1084248693Sgleb origlib = Shlib(Config.origfile.filename) 1085248693Sgleb origlib.parse() 1086248693Sgleb newlib = Shlib(Config.newfile.filename) 1087248693Sgleb newlib.parse() 1088248693Sgleb 1089248693Sgleb commonver = common_symbols(origlib, newlib) 1090248693Sgleb if Config.dump: 1091248693Sgleb dump_symbols(commonver) 1092248693Sgleb cmp_symbols(commonver) 1093248693Sgleb if Config.verbose >= 4: 1094248693Sgleb print Dwarf.cmpcache.stats.show('Cmp') 1095248693Sgleb print DwarfdumpParser.tagcache_stats.show('Dwarf tag') 1096248693Sgleb 1097248693Sgleb sys.exit(App.result_code) 1098