util.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #===----------------------------------------------------------------------===##
  2. #
  3. # The LLVM Compiler Infrastructure
  4. #
  5. # This file is dual licensed under the MIT and the University of Illinois Open
  6. # Source Licenses. See LICENSE.TXT for details.
  7. #
  8. #===----------------------------------------------------------------------===##
  9. import ast
  10. import distutils.spawn
  11. import sys
  12. import re
  13. import libcxx.util
  14. def read_syms_from_list(slist):
  15. """
  16. Read a list of symbols from a list of strings.
  17. Each string is one symbol.
  18. """
  19. return [ast.literal_eval(l) for l in slist]
  20. def read_syms_from_file(filename):
  21. """
  22. Read a list of symbols in from a file.
  23. """
  24. with open(filename, 'r') as f:
  25. data = f.read()
  26. return read_syms_from_list(data.splitlines())
  27. def read_blacklist(filename):
  28. with open(filename, 'r') as f:
  29. data = f.read()
  30. lines = [l.strip() for l in data.splitlines() if l.strip()]
  31. lines = [l for l in lines if not l.startswith('#')]
  32. return lines
  33. def write_syms(sym_list, out=None, names_only=False):
  34. """
  35. Write a list of symbols to the file named by out.
  36. """
  37. out_str = ''
  38. out_list = sym_list
  39. out_list.sort(key=lambda x: x['name'])
  40. if names_only:
  41. out_list = [sym['name'] for sym in sym_list]
  42. for sym in out_list:
  43. out_str += '%s\n' % sym
  44. if out is None:
  45. sys.stdout.write(out_str)
  46. else:
  47. with open(out, 'w') as f:
  48. f.write(out_str)
  49. _cppfilt_exe = distutils.spawn.find_executable('c++filt')
  50. def demangle_symbol(symbol):
  51. if _cppfilt_exe is None:
  52. return symbol
  53. out, _, exit_code = libcxx.util.executeCommandVerbose(
  54. [_cppfilt_exe], input=symbol)
  55. if exit_code != 0:
  56. return symbol
  57. return out
  58. def is_elf(filename):
  59. with open(filename, 'rb') as f:
  60. magic_bytes = f.read(4)
  61. return magic_bytes == b'\x7fELF'
  62. def is_mach_o(filename):
  63. with open(filename, 'rb') as f:
  64. magic_bytes = f.read(4)
  65. return magic_bytes in [
  66. '\xfe\xed\xfa\xce', # MH_MAGIC
  67. '\xce\xfa\xed\xfe', # MH_CIGAM
  68. '\xfe\xed\xfa\xcf', # MH_MAGIC_64
  69. '\xcf\xfa\xed\xfe', # MH_CIGAM_64
  70. '\xca\xfe\xba\xbe', # FAT_MAGIC
  71. '\xbe\xba\xfe\xca' # FAT_CIGAM
  72. ]
  73. def is_library_file(filename):
  74. if sys.platform == 'darwin':
  75. return is_mach_o(filename)
  76. else:
  77. return is_elf(filename)
  78. def extract_or_load(filename):
  79. import libcxx.sym_check.extract
  80. if is_library_file(filename):
  81. return libcxx.sym_check.extract.extract_symbols(filename)
  82. return read_syms_from_file(filename)
  83. def adjust_mangled_name(name):
  84. if not name.startswith('__Z'):
  85. return name
  86. return name[1:]
  87. new_delete_std_symbols = [
  88. '_Znam',
  89. '_Znwm',
  90. '_ZdaPv',
  91. '_ZdaPvm',
  92. '_ZdlPv',
  93. '_ZdlPvm'
  94. ]
  95. cxxabi_symbols = [
  96. '___dynamic_cast',
  97. '___gxx_personality_v0',
  98. '_ZTIDi',
  99. '_ZTIDn',
  100. '_ZTIDs',
  101. '_ZTIPDi',
  102. '_ZTIPDn',
  103. '_ZTIPDs',
  104. '_ZTIPKDi',
  105. '_ZTIPKDn',
  106. '_ZTIPKDs',
  107. '_ZTIPKa',
  108. '_ZTIPKb',
  109. '_ZTIPKc',
  110. '_ZTIPKd',
  111. '_ZTIPKe',
  112. '_ZTIPKf',
  113. '_ZTIPKh',
  114. '_ZTIPKi',
  115. '_ZTIPKj',
  116. '_ZTIPKl',
  117. '_ZTIPKm',
  118. '_ZTIPKs',
  119. '_ZTIPKt',
  120. '_ZTIPKv',
  121. '_ZTIPKw',
  122. '_ZTIPKx',
  123. '_ZTIPKy',
  124. '_ZTIPa',
  125. '_ZTIPb',
  126. '_ZTIPc',
  127. '_ZTIPd',
  128. '_ZTIPe',
  129. '_ZTIPf',
  130. '_ZTIPh',
  131. '_ZTIPi',
  132. '_ZTIPj',
  133. '_ZTIPl',
  134. '_ZTIPm',
  135. '_ZTIPs',
  136. '_ZTIPt',
  137. '_ZTIPv',
  138. '_ZTIPw',
  139. '_ZTIPx',
  140. '_ZTIPy',
  141. '_ZTIa',
  142. '_ZTIb',
  143. '_ZTIc',
  144. '_ZTId',
  145. '_ZTIe',
  146. '_ZTIf',
  147. '_ZTIh',
  148. '_ZTIi',
  149. '_ZTIj',
  150. '_ZTIl',
  151. '_ZTIm',
  152. '_ZTIs',
  153. '_ZTIt',
  154. '_ZTIv',
  155. '_ZTIw',
  156. '_ZTIx',
  157. '_ZTIy',
  158. '_ZTSDi',
  159. '_ZTSDn',
  160. '_ZTSDs',
  161. '_ZTSPDi',
  162. '_ZTSPDn',
  163. '_ZTSPDs',
  164. '_ZTSPKDi',
  165. '_ZTSPKDn',
  166. '_ZTSPKDs',
  167. '_ZTSPKa',
  168. '_ZTSPKb',
  169. '_ZTSPKc',
  170. '_ZTSPKd',
  171. '_ZTSPKe',
  172. '_ZTSPKf',
  173. '_ZTSPKh',
  174. '_ZTSPKi',
  175. '_ZTSPKj',
  176. '_ZTSPKl',
  177. '_ZTSPKm',
  178. '_ZTSPKs',
  179. '_ZTSPKt',
  180. '_ZTSPKv',
  181. '_ZTSPKw',
  182. '_ZTSPKx',
  183. '_ZTSPKy',
  184. '_ZTSPa',
  185. '_ZTSPb',
  186. '_ZTSPc',
  187. '_ZTSPd',
  188. '_ZTSPe',
  189. '_ZTSPf',
  190. '_ZTSPh',
  191. '_ZTSPi',
  192. '_ZTSPj',
  193. '_ZTSPl',
  194. '_ZTSPm',
  195. '_ZTSPs',
  196. '_ZTSPt',
  197. '_ZTSPv',
  198. '_ZTSPw',
  199. '_ZTSPx',
  200. '_ZTSPy',
  201. '_ZTSa',
  202. '_ZTSb',
  203. '_ZTSc',
  204. '_ZTSd',
  205. '_ZTSe',
  206. '_ZTSf',
  207. '_ZTSh',
  208. '_ZTSi',
  209. '_ZTSj',
  210. '_ZTSl',
  211. '_ZTSm',
  212. '_ZTSs',
  213. '_ZTSt',
  214. '_ZTSv',
  215. '_ZTSw',
  216. '_ZTSx',
  217. '_ZTSy'
  218. ]
  219. def is_stdlib_symbol_name(name):
  220. name = adjust_mangled_name(name)
  221. if re.search("@GLIBC|@GCC", name):
  222. return False
  223. if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name):
  224. return True
  225. if name in new_delete_std_symbols:
  226. return True
  227. if name in cxxabi_symbols:
  228. return True
  229. if name.startswith('_Z'):
  230. return True
  231. return False
  232. def filter_stdlib_symbols(syms):
  233. stdlib_symbols = []
  234. other_symbols = []
  235. for s in syms:
  236. canon_name = adjust_mangled_name(s['name'])
  237. if not is_stdlib_symbol_name(canon_name):
  238. assert not s['is_defined'] and "found defined non-std symbol"
  239. other_symbols += [s]
  240. else:
  241. stdlib_symbols += [s]
  242. return stdlib_symbols, other_symbols