#!/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):
  symbol_format = re.compile('\S+ \S+ ([^@]+)@@?(\S+)\n')
  version_format = re.compile('GLIBC_[0-9\.]+')
  symbols = {}
  for line in nm_file:
    m = re.match(symbol_format, line)
    symbol = m.group(1)
    version = m.group(2)
    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.iteritems():
    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)
