socsvn commit: r222846 - soc2011/gk/ino64-head/tools/tools/shlib-compat

gk at FreeBSD.org gk at FreeBSD.org
Sun Jun 5 16:22:14 UTC 2011


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)


More information about the svn-soc-all mailing list