#!/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)