blob: 1e0b5f614a355225e11b536d25d8ceb7d9743b88 [file] [log] [blame]
#!/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)