aboutsummaryrefslogtreecommitdiff
path: root/tools/tools/shlib-compat
diff options
context:
space:
mode:
authorGleb Kurtsou <gleb@FreeBSD.org>2014-12-01 08:14:25 +0000
committerGleb Kurtsou <gleb@FreeBSD.org>2014-12-01 08:14:25 +0000
commitc5f8185b36cac5c4a1c8e106a526a19a5829c611 (patch)
treef31c4fa314806e5fbff3635cf4e82f39a056bfcf /tools/tools/shlib-compat
parent95c4bf756a1dd903b360530f3787544417152c20 (diff)
downloadsrc-c5f8185b36cac5c4a1c8e106a526a19a5829c611.tar.gz
src-c5f8185b36cac5c4a1c8e106a526a19a5829c611.zip
Update tools/shlib-compat.
- Update dwarfdump / compiler support. Use hex instead of decimal for integers. Add boolean and restrict type definitions. Add options for specifing dwarfdump and objdump executables. - Fix reporting missing symbol definitions as matching. - Compare external variable definitions. - Exclude special symbols like _init, _end by default. - Fix test build.
Notes
Notes: svn path=/head/; revision=275354
Diffstat (limited to 'tools/tools/shlib-compat')
-rwxr-xr-xtools/tools/shlib-compat/shlib-compat.py85
-rw-r--r--tools/tools/shlib-compat/test/Makefile.inc2
-rwxr-xr-xtools/tools/shlib-compat/test/regress.sh2
3 files changed, 75 insertions, 14 deletions
diff --git a/tools/tools/shlib-compat/shlib-compat.py b/tools/tools/shlib-compat/shlib-compat.py
index 726c53ffb967..ca6f036639d1 100755
--- a/tools/tools/shlib-compat/shlib-compat.py
+++ b/tools/tools/shlib-compat/shlib-compat.py
@@ -60,6 +60,14 @@ class Config(object):
origfile = FileConfig()
newfile = FileConfig()
+ exclude_sym_default = [
+ '^__bss_start$',
+ '^_edata$',
+ '^_end$',
+ '^_fini$',
+ '^_init$',
+ ]
+
@classmethod
def init(cls):
cls.version_filter = StrFilter()
@@ -338,15 +346,17 @@ class BaseTypeDef(Def):
def _pp(self, pp):
if self.encoding in self.inttypes:
sign = '' if self.encoding == 'DW_ATE_signed' else 'u'
- bits = int(self.byte_size) * 8
+ bits = int(self.byte_size, 0) * 8
return '%sint%s_t' % (sign, bits)
- elif self.encoding == 'DW_ATE_signed_char' and int(self.byte_size) == 1:
+ elif self.encoding == 'DW_ATE_signed_char' and int(self.byte_size, 0) == 1:
return 'char';
+ elif self.encoding == 'DW_ATE_boolean' and int(self.byte_size, 0) == 1:
+ return 'bool';
elif self.encoding == 'DW_ATE_float':
- return self._mapval(self.byte_size, {
- '16': 'long double',
- '8': 'double',
- '4': 'float',
+ return self._mapval(int(self.byte_size, 0), {
+ 16: 'long double',
+ 8: 'double',
+ 4: 'float',
})
raise NotImplementedError('Invalid encoding: %s' % self)
@@ -374,6 +384,11 @@ class VolatileTypeDef(AnonymousDef):
def _pp(self, pp):
return 'volatile ' + self.type._pp(pp)
+class RestrictTypeDef(AnonymousDef):
+ _is_alias = True
+ def _pp(self, pp):
+ return 'restrict ' + self.type._pp(pp)
+
class ArrayDef(AnonymousDef):
def _pp(self, pp):
t = pp.run(self.type)
@@ -411,6 +426,11 @@ class ParameterDef(Def):
t = pp.run(self.type)
return "%s %s" % (t, self._name_opt())
+class VariableDef(Def):
+ def _pp(self, pp):
+ t = pp.run(self.type)
+ return "%s %s" % (t, self._name_opt())
+
# TODO
class StructForwardDef(Def):
pass
@@ -485,6 +505,10 @@ class Dwarf(object):
result = self._build_optarg_type(raw)
return FunctionDef(raw.id, raw.name, params=params, result=result)
+ def build_variable(self, raw):
+ type = self._build_optarg_type(raw)
+ return VariableDef(raw.id, raw.optname, type=type)
+
def build_subroutine_type(self, raw):
params = [ self.build(x) for x in raw.nested ]
result = self._build_optarg_type(raw)
@@ -547,6 +571,10 @@ class Dwarf(object):
type = self._build_optarg_type(raw)
return VolatileTypeDef(raw.id, type=type)
+ def build_restrict_type(self, raw):
+ type = self._build_optarg_type(raw)
+ return RestrictTypeDef(raw.id, type=type)
+
def build_enumeration_type(self, raw):
# TODO handle DW_TAG_enumerator ???
return EnumerationTypeDef(raw.id, name=raw.optname,
@@ -574,7 +602,7 @@ class Dwarf(object):
return int(id)
except ValueError:
if (id.startswith('<') and id.endswith('>')):
- return int(id[1:-1])
+ return int(id[1:-1], 0)
else:
raise ValueError("Invalid dwarf id: %s" % id)
@@ -782,7 +810,7 @@ class DwarfdumpParser(Parser):
class Tag(object):
def __init__(self, unit, data):
self.unit = unit
- self.id = int(data['id'])
+ self.id = int(data['id'], 0)
self.level = int(data['level'])
self.tag = data['tag']
self.args = {}
@@ -816,7 +844,7 @@ class DwarfdumpParser(Parser):
def __repr__(self):
return "Tag(%d, %d, %s)" % (self.level, self.id, self.tag)
- re_header = re.compile('<(?P<level>\d+)><(?P<id>\d+\+*\d*)><(?P<tag>\w+)>')
+ re_header = re.compile('<(?P<level>\d+)><(?P<id>[0xX0-9a-fA-F]+(?:\+(0[xX])?[0-9a-fA-F]+)?)><(?P<tag>\w+)>')
re_argname = re.compile('(?P<arg>\w+)<')
re_argunknown = re.compile('<Unknown AT value \w+><[^<>]+>')
@@ -827,6 +855,10 @@ class DwarfdumpParser(Parser):
'DW_TAG_variable',
])
+ external_tags = set([
+ 'DW_TAG_variable',
+ ])
+
def __init__(self, libfile):
Parser.__init__(self, "%s -di %s" % (Config.dwarfdump, libfile))
self.current_unit = None
@@ -888,9 +920,19 @@ class DwarfdumpParser(Parser):
while args:
args = self.parse_arg(tag, args)
tag.unit.tags[tag.id] = tag
- if tag.args.has_key('DW_AT_low_pc') and \
- tag.tag not in DwarfdumpParser.skip_tags:
- offset = int(tag.args['DW_AT_low_pc'], 16)
+ def parse_offset(tag):
+ if tag.args.has_key('DW_AT_low_pc'):
+ return int(tag.args['DW_AT_low_pc'], 16)
+ elif tag.args.has_key('DW_AT_location'):
+ location = tag.args['DW_AT_location']
+ if location.startswith('DW_OP_addr'):
+ return int(location.replace('DW_OP_addr', ''), 16)
+ return None
+ offset = parse_offset(tag)
+ if offset is not None and \
+ (tag.tag not in DwarfdumpParser.skip_tags or \
+ (tag.args.has_key('DW_AT_external') and \
+ tag.tag in DwarfdumpParser.external_tags)):
if self.offsetmap.has_key(offset):
raise ValueError("Dwarf dump parse error: " +
"symbol is aleady defined at offset 0x%x" % offset)
@@ -963,10 +1005,15 @@ def cmp_symbols(commonver):
names.sort()
for symname in names:
sym = ver.symbols[symname]
- match = sym.origsym.definition == sym.newsym.definition
+ missing = sym.origsym.definition is None or sym.newsym.definition is None
+ match = not missing and sym.origsym.definition == sym.newsym.definition
if not match:
App.result_code = 1
if Config.verbose >= 1 or not match:
+ if missing:
+ print '%s: missing definition' % \
+ (sym.origsym.name_ver,)
+ continue
print '%s: definitions %smatch' % \
(sym.origsym.name_ver, "" if match else "mis")
if Config.dump or (not match and not Config.no_dump):
@@ -1035,10 +1082,16 @@ if __name__ == '__main__':
help="result output file for original library", metavar="ORIGFILE")
parser.add_option('--out-new', action='store',
help="result output file for new library", metavar="NEWFILE")
+ parser.add_option('--dwarfdump', action='store',
+ help="path to dwarfdump executable", metavar="DWARFDUMP")
+ parser.add_option('--objdump', action='store',
+ help="path to objdump executable", metavar="OBJDUMP")
parser.add_option('--exclude-ver', action='append', metavar="RE")
parser.add_option('--include-ver', action='append', metavar="RE")
parser.add_option('--exclude-sym', action='append', metavar="RE")
parser.add_option('--include-sym', action='append', metavar="RE")
+ parser.add_option('--no-exclude-sym-default', action='store_true',
+ help="don't exclude special symbols like _init, _end, __bss_start")
for opt in ['alias', 'cached', 'symbol']:
parser.add_option("--w-" + opt,
action="store_true", dest="w_" + opt)
@@ -1049,6 +1102,10 @@ if __name__ == '__main__':
if len(args) != 2:
parser.print_help()
sys.exit(-1)
+ if opts.dwarfdump:
+ Config.dwarfdump = opts.dwarfdump
+ if opts.objdump:
+ Config.objdump = opts.objdump
if opts.out_orig:
Config.origfile.init(opts.out_orig)
if opts.out_new:
@@ -1071,6 +1128,8 @@ if __name__ == '__main__':
opt = getattr(opts, a + k)
if opt:
getattr(v, a).extend(opt)
+ if not opts.no_exclude_sym_default:
+ Config.symbol_filter.exclude.extend(Config.exclude_sym_default)
Config.version_filter.compile()
Config.symbol_filter.compile()
for w in ['w_alias', 'w_cached', 'w_symbol']:
diff --git a/tools/tools/shlib-compat/test/Makefile.inc b/tools/tools/shlib-compat/test/Makefile.inc
index 14aaef6ea956..e1a0719a89f4 100644
--- a/tools/tools/shlib-compat/test/Makefile.inc
+++ b/tools/tools/shlib-compat/test/Makefile.inc
@@ -11,3 +11,5 @@ DEBUG_FLAGS?= -g
VERSION_DEF= ${.CURDIR}/../Versions.def
SYMBOL_MAPS= ${.CURDIR}/Symbol.map
+
+MK_DEBUG_FILES= yes
diff --git a/tools/tools/shlib-compat/test/regress.sh b/tools/tools/shlib-compat/test/regress.sh
index e113cce87b63..0789fa8b3cf7 100755
--- a/tools/tools/shlib-compat/test/regress.sh
+++ b/tools/tools/shlib-compat/test/regress.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# $FreeBSD$
-run() { ../shlib-compat.py --no-dump -vv libtest$1/libtest$1.so.0.debug libtest$2/libtest$2.so.0.debug; }
+run() { ../shlib-compat.py --no-dump -vv libtest$1/libtest$1.so.0.full libtest$2/libtest$2.so.0.full; }
echo 1..9
REGRESSION_START($1)
REGRESSION_TEST(`1-1', `run 1 1')