diff options
author | Gleb Kurtsou <gleb@FreeBSD.org> | 2014-12-01 08:14:25 +0000 |
---|---|---|
committer | Gleb Kurtsou <gleb@FreeBSD.org> | 2014-12-01 08:14:25 +0000 |
commit | c5f8185b36cac5c4a1c8e106a526a19a5829c611 (patch) | |
tree | f31c4fa314806e5fbff3635cf4e82f39a056bfcf /tools/tools/shlib-compat | |
parent | 95c4bf756a1dd903b360530f3787544417152c20 (diff) | |
download | src-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-x | tools/tools/shlib-compat/shlib-compat.py | 85 | ||||
-rw-r--r-- | tools/tools/shlib-compat/test/Makefile.inc | 2 | ||||
-rwxr-xr-x | tools/tools/shlib-compat/test/regress.sh | 2 |
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') |