| #!/usr/bin/env python |
| # Copyright 2018 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Find incompatible symbols in glibc and output a list of replacements. |
| """ |
| |
| from __future__ import print_function |
| |
| import re |
| import sys |
| |
| # This constant comes from https://crbug.com/580892 |
| MAX_ALLOWED_GLIBC_VERSION = [2, 17] |
| |
| |
| def get_replacements(nm_file, max_allowed_glibc_version): |
| version_format = re.compile('GLIBC_[0-9\.]+') |
| symbols = {} |
| for line in nm_file: |
| # Some versions of nm have a bug where the version gets printed twice. |
| # Since the symbol may either be formatted like "name@@VERSION" or |
| # "name@@VERSION@@VERSION", handle both cases. |
| line = line.replace('@@', '@') |
| symver = line.split('@') |
| symbol = symver[0].split(' ')[-1] |
| version = symver[-1] |
| if not re.match(version_format, version): |
| continue |
| if symbol in symbols: |
| symbols[symbol].add(version) |
| else: |
| symbols[symbol] = set([version]) |
| |
| replacements = [] |
| for symbol, versions in symbols.items(): |
| if len(versions) <= 1: |
| continue |
| versions_parsed = [[ |
| int(part) for part in version.lstrip('GLIBC_').split('.') |
| ] for version in versions] |
| if (max(versions_parsed) > max_allowed_glibc_version and |
| min(versions_parsed) <= max_allowed_glibc_version): |
| # Use the newest allowed version of the symbol. |
| replacement_version_parsed = max([ |
| version for version in versions_parsed |
| if version <= max_allowed_glibc_version |
| ]) |
| replacement_version = 'GLIBC_' + '.'.join( |
| [str(part) for part in replacement_version_parsed]) |
| replacements.append('__asm__(".symver %s, %s@%s");' % |
| (symbol, symbol, replacement_version)) |
| return sorted(replacements) |
| |
| |
| if __name__ == '__main__': |
| replacements = get_replacements(sys.stdin, MAX_ALLOWED_GLIBC_VERSION) |
| if replacements: |
| print('// Chromium-specific hack.') |
| print('// See explanation in sysroot-creator.sh.') |
| for replacement in replacements: |
| print(replacement) |