fix_py2_protobuf.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import subprocess
  2. import os, sys
  3. # Explicitly enable local imports
  4. # Don't forget to add imported scripts to inputs of the calling command!
  5. sys.path.append(os.path.dirname(os.path.abspath(__file__)))
  6. import process_command_files as pcf
  7. def run(*args):
  8. # print >>sys.stderr, args
  9. return subprocess.check_output(list(args), shell=False).strip()
  10. def gen_renames_1(d):
  11. for l in d.split('\n'):
  12. l = l.strip()
  13. if ' ' in l:
  14. yield l.split(' ')[-1]
  15. def gen_renames_2(p, d):
  16. for s in gen_renames_1(d):
  17. """
  18. Since clang-17, the option -fsanitize-address-globals-dead-stripping
  19. has been enabled by default. Due to this, we have broken optimization
  20. that merges calls to the `asan.module_ctor` function, as we are renaming
  21. symbols with a prefix of 'py2_'. When this flag is enabled, and
  22. the functions are not merged, false-positive ODR (One Definition Rule)
  23. violations occur on objects such as `typeinfo std::exception`, because
  24. the runtime is trying to handle global objects that have already been handled.
  25. """
  26. if 'asan_globals' in s:
  27. continue
  28. yield s + ' ' + p + s
  29. def gen_renames(p, d):
  30. return '\n'.join(gen_renames_2(p, d)).strip() + '\n'
  31. def rename_syms(where, ret, libs):
  32. p = 'py2_'
  33. # join libs
  34. run(where + 'llvm-ar', 'qcL', ret, *libs)
  35. # find symbols to rename
  36. syms = run(where + 'llvm-nm', '--extern-only', '--defined-only', '-A', ret)
  37. # prepare rename plan
  38. renames = gen_renames(p, syms)
  39. with open('syms', 'w') as f:
  40. f.write(renames)
  41. # rename symbols
  42. run(where + 'llvm-objcopy', '--redefine-syms=syms', ret)
  43. # back-rename some symbols
  44. args = [
  45. where + 'llvm-objcopy',
  46. '--redefine-sym',
  47. p + 'init_api_implementation=init6google8protobuf8internal19_api_implementation',
  48. '--redefine-sym',
  49. p + 'init_message=init6google8protobuf5pyext8_message',
  50. '--redefine-sym',
  51. p + 'init6google8protobuf8internal19_api_implementation=init6google8protobuf8internal19_api_implementation',
  52. '--redefine-sym',
  53. p + 'init6google8protobuf5pyext8_message=init6google8protobuf5pyext8_message',
  54. '--redefine-sym',
  55. p + '_init6google8protobuf8internal19_api_implementation=_init6google8protobuf8internal19_api_implementation',
  56. '--redefine-sym',
  57. p + '_init6google8protobuf5pyext8_message=_init6google8protobuf5pyext8_message',
  58. ret,
  59. ]
  60. run(*args)
  61. return ret
  62. def fix_py2(cmd, have_comand_files=False, prefix='lib', suffix='a'):
  63. args = cmd
  64. if have_comand_files:
  65. args = pcf.get_args(cmd)
  66. if 'protobuf_old' not in str(args):
  67. return cmd
  68. py2_libs = [prefix + 'contrib-libs-protobuf_old.' + suffix, prefix + 'pypython-protobuf-py2.' + suffix]
  69. def need_rename(x):
  70. for v in py2_libs:
  71. if v in x:
  72. return True
  73. return False
  74. old = []
  75. lib = []
  76. where = os.path.dirname(cmd[0]) + '/'
  77. for x in args:
  78. if need_rename(x):
  79. lib.append(x)
  80. else:
  81. old.append(x)
  82. name = rename_syms(where, 'libprotoherobora.' + suffix, lib)
  83. if not have_comand_files:
  84. return old + [name]
  85. for file in cmd:
  86. if pcf.is_cmdfile_arg(file):
  87. cmd_file_path = pcf.cmdfile_path(file)
  88. args = pcf.read_from_command_file(cmd_file_path)
  89. if not 'protobuf_old' in str(args):
  90. continue
  91. with open(cmd_file_path, 'w') as afile:
  92. for arg in args:
  93. if not need_rename(arg):
  94. afile.write(arg + '\n')
  95. afile.write(name)
  96. return cmd