glibcsymbols.py 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #!/usr/bin/python3
  2. # Processing of symbols and abilist files.
  3. # Copyright (C) 2020-2026 Free Software Foundation, Inc.
  4. # This file is part of the GNU C Library.
  5. #
  6. # The GNU C Library is free software; you can redistribute it and/or
  7. # modify it under the terms of the GNU Lesser General Public
  8. # License as published by the Free Software Foundation; either
  9. # version 2.1 of the License, or (at your option) any later version.
  10. #
  11. # The GNU C Library is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. # Lesser General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU Lesser General Public
  17. # License along with the GNU C Library; if not, see
  18. # <https://www.gnu.org/licenses/>.
  19. """Symbol processing for glibc."""
  20. import os
  21. def replace_file(path, new_contents):
  22. """Atomically replace PATH with lines from NEW_CONTENTS.
  23. NEW_CONTENTS must be a sequence of strings.
  24. """
  25. temppath = path + 'T'
  26. with open(temppath, 'w') as out:
  27. for line in new_contents:
  28. out.write(line)
  29. os.rename(temppath, path)
  30. class VersionedSymbol:
  31. """A combination of a symbol and its version."""
  32. def __init__(self, symbol, version):
  33. """Construct a new versioned symbol."""
  34. assert symbol
  35. assert version
  36. self.symbol = symbol
  37. self.version = version
  38. def __str__(self):
  39. return self.symbol + '@' + self.version
  40. def __eq__(self, other):
  41. return self.symbol == other.symbol and self.version == other.version
  42. def __hash__(self):
  43. return hash(self.symbol) ^ hash(self.version)
  44. def read_abilist(path):
  45. """Read the abilist file at PATH.
  46. Return a dictionary from VersionedSymbols to their flags (as
  47. strings).
  48. """
  49. result = {}
  50. with open(path) as inp:
  51. for line in inp:
  52. version, symbol, flags = line.strip().split(' ', 2)
  53. versym = VersionedSymbol(symbol, version)
  54. if versym in result:
  55. raise IOError("{}: duplicate symbol {}".format(path, versym))
  56. result[versym] = flags
  57. return result
  58. def abilist_lines(symbols):
  59. """Build the abilist file contents (as a list of lines).
  60. SYMBOLS is a dictionary from VersionedSymbols to their flags.
  61. """
  62. result = []
  63. for versym, flags in symbols.items():
  64. result.append('{} {} {}\n'.format(
  65. versym.version, versym.symbol, flags))
  66. result.sort()
  67. return result