Date: Sun, 05 Jun 2011 16:22:12 +0000 From: gk@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r222846 - soc2011/gk/ino64-head/tools/tools/shlib-compat Message-ID: <20110605162212.8C64E1065673@hub.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gk Date: Sun Jun 5 16:22:12 2011 New Revision: 222846 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=222846 Log: shlib-compat: add --alias-prefix option Merge rev 80347e403bf6ed616a8d Modified: soc2011/gk/ino64-head/tools/tools/shlib-compat/shlib-compat Modified: soc2011/gk/ino64-head/tools/tools/shlib-compat/shlib-compat ============================================================================== --- soc2011/gk/ino64-head/tools/tools/shlib-compat/shlib-compat Sun Jun 5 16:22:01 2011 (r222845) +++ soc2011/gk/ino64-head/tools/tools/shlib-compat/shlib-compat Sun Jun 5 16:22:12 2011 (r222846) @@ -34,8 +34,10 @@ # controlled by user verbose = 0 dump = False + no_dump = False version_filter = None symbol_filter = None + alias_prefix = None # misc opts objdump = 'objdump' dwarfdump = 'dwarfdump' @@ -58,6 +60,9 @@ cls.version_filter = StrFilter() cls.symbol_filter = StrFilter() +class App(object): + result_code = 0 + # {{{ misc class StrFilter(object): @@ -187,6 +192,17 @@ def __repr__(self): return "CommonSymbol(%s, %s)" % (self.name, self.version) +class SymbolAlias(object): + def __init__(self, alias, offset): + assert alias.startswith(Config.alias_prefix) + self.alias = alias + self.name = alias[len(Config.alias_prefix):] + self.offset = offset + + def __repr__(self): + return "SymbolAlias(%s, 0x%x)" % (self.alias, self.offset) + + class VersionMap(object): def __init__(self, name): self.name = name @@ -252,8 +268,9 @@ if ind != 0: Dwarf.cmpcache.put(ind, r) else: - raise RuntimeError('Comparing different classes: %s, %s' % - (a.__class__.__name__, b.__class__.__name__)) + r = 0 + #raise RuntimeError('Comparing different classes: %s, %s' % + # (a.__class__.__name__, b.__class__.__name__)) return r def __repr__(self): @@ -569,6 +586,7 @@ def __init__(self, libfile): self.libfile = libfile self.versions = {} + self.alias_syms = {} def parse_objdump(self): objdump = ObjdumpParser(self.libfile) @@ -585,16 +603,41 @@ if not self.versions.has_key(vername): self.versions[vername] = VersionMap(vername) self.versions[vername].append(sym) + if Config.alias_prefix: + self.local_offsetmap = objdump.local_offsetmap + for p in objdump.local_symbols: + if p['symbol'].startswith(Config.alias_prefix): + alias = SymbolAlias(p['symbol'], p['offset']) + if self.alias_syms.has_key(alias.name): + print >> sys.stderr, "WARN: Symbol alias is already defined: %s/%s" % \ + (self.name, self.alias) + self.alias_syms[alias.name] = alias def parse_dwarfdump(self): dwarfdump = DwarfdumpParser(self.libfile) + def lookup(sym): + raw = None + try: + raw = dwarfdump.offsetmap[sym.offset] + except: + try: + localnames = self.local_offsetmap[sym.offset] + localnames.sort(key=lambda x: -len(x)) + for localname in localnames: + if not self.alias_syms.has_key(localname): + continue + alias = self.alias_syms[localname] + raw = dwarfdump.offsetmap[alias.offset] + break + except: + pass + return raw dwarfdump.run() dwarf = Dwarf(dwarfdump) for ver in self.versions.values(): for sym in ver.symbols.values(): - try: - raw = dwarfdump.offsetmap[sym.offset] - except: + raw = lookup(sym); + if not raw: print >> sys.stderr, "WARN: Symbol %s (%s) not found at offset 0x%x" % \ (sym.name_ver, self.libfile, sym.offset) continue @@ -636,19 +679,25 @@ 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]*)') def __init__(self, libfile): - Parser.__init__(self, "%s -wT %s" % (Config.objdump, libfile)) + Parser.__init__(self, "%s -wtT %s" % (Config.objdump, libfile)) self.dynamic_symbols = [] self.local_symbols = [] + self.local_offsetmap = {} def parse_begin(self, line): self.parse_header(line) - def add_symbol(self, table, symbol): + def add_symbol(self, table, symbol, offsetmap = None): offset = int(symbol['offset'], 16); symbol['offset'] = offset if (offset == 0): return table.append(symbol) + if offsetmap != None: + if not offsetmap.has_key(offset): + offsetmap[offset] = [symbol['symbol']] + else: + offsetmap[offset].append(symbol['symbol']) def parse_header(self, line): m = self.re_header.match(line) @@ -670,10 +719,11 @@ return m = self.re_local_symbol.match(line) if (not m): - raise ValueError("Invalid symbol definition: %s" % line) + return + #raise ValueError("Invalid symbol definition: %s" % line) p = m.groupdict() if (p['symbol'] and p['symbol'].find('@') == -1): - self.add_symbol(self.local_symbols, p); + self.add_symbol(self.local_symbols, p, self.local_offsetmap); def parse_dynamic(self, line): if (self.parse_header(line)): @@ -843,20 +893,29 @@ print 'Removed version: ', vername print ' Removed symbols: ', \ names_ver_str(vername, origlib.versions[vername].names()) + added = [] + removed = [] for vername in verdiff.common: origver = origlib.versions[vername] newver = newlib.versions[vername] namediff = ListDiff(origver.names(), newver.names()) - if namediff.added or namediff.removed: - print 'Added symbols: ', \ - names_ver_str(vername, namediff.added) - print 'Removed symbols: ', \ - names_ver_str(vername, namediff.removed) + if namediff.added: + added.append(names_ver_str(vername, namediff.added)) + if namediff.removed: + removed.append(names_ver_str(vername, namediff.removed)) commonver = VersionMap(vername) result.append(commonver) for n in namediff.common: sym = CommonSymbol(origver.symbols[n], newver.symbols[n]) commonver.append(sym) + if added: + print 'Added symbols:' + for i in added: + print ' ', i + if removed: + print 'Removed symbols:' + for i in removed: + print ' ', i return result def cmp_symbols(commonver): @@ -866,14 +925,20 @@ for symname in names: sym = ver.symbols[symname] match = sym.origsym.definition == sym.newsym.definition + if not match: + App.result_code = 1 if Config.verbose >= 1 or not match: print '%s: definitions %smatch' % \ (sym.origsym.name_ver, "" if match else "mis") - if Config.dump and not match: + if Config.dump or (not match and not Config.no_dump): for x in [(sym.origsym, Config.origfile), (sym.newsym, Config.newfile)]: xsym = x[0] xout = x[1].out + if not xsym.definition: + print >> xout, '\n// Definition not found: %s %s' % \ + (xsym.name_ver, xsym.lib.libfile) + continue print >> xout, '\n// Definitions mismatch: %s %s' % \ (xsym.name_ver, xsym.lib.libfile) pp = PrettyPrinter() @@ -921,8 +986,12 @@ version="%prog " + Config.version) parser.add_option('-v', '--verbose', action='count', help="verbose mode, may be specified several times") + parser.add_option('--alias-prefix', action='store', + help="name prefix to try for symbol alias lookup", metavar="STR") parser.add_option('--dump', action='store_true', help="dump symbol definitions") + parser.add_option('--no-dump', action='store_true', + help="disable dump for mismatched symbols") parser.add_option('--out-orig', action='store', help="result output file for original library", metavar="ORIGFILE") parser.add_option('--out-new', action='store', @@ -940,11 +1009,17 @@ Config.origfile.init(opts.out_orig) if opts.out_new: Config.newfile.init(opts.out_new) + if opts.no_dump: + Config.dump = False + Config.no_dump = True if opts.dump: Config.dump = True + Config.no_dump = False Config.verbose = 1 if opts.verbose: Config.verbose = opts.verbose + if opts.alias_prefix: + Config.alias_prefix = opts.alias_prefix for (k, v) in ({ '_sym': Config.symbol_filter, '_ver': Config.version_filter }).items(): for a in [ 'exclude', 'include' ]: @@ -969,3 +1044,4 @@ print Dwarf.cmpcache.stats.show('Cmp') print DwarfdumpParser.tagcache_stats.show('Dwarf tag') + sys.exit(App.result_code)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110605162212.8C64E1065673>