aboutsummaryrefslogtreecommitdiff
path: root/utils/libcxx/sym_check/util.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils/libcxx/sym_check/util.py')
-rw-r--r--utils/libcxx/sym_check/util.py268
1 files changed, 268 insertions, 0 deletions
diff --git a/utils/libcxx/sym_check/util.py b/utils/libcxx/sym_check/util.py
new file mode 100644
index 000000000000..8a4c4ab496ff
--- /dev/null
+++ b/utils/libcxx/sym_check/util.py
@@ -0,0 +1,268 @@
+#===----------------------------------------------------------------------===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is dual licensed under the MIT and the University of Illinois Open
+# Source Licenses. See LICENSE.TXT for details.
+#
+#===----------------------------------------------------------------------===##
+
+import ast
+import distutils.spawn
+import sys
+import re
+import libcxx.util
+
+
+def read_syms_from_list(slist):
+ """
+ Read a list of symbols from a list of strings.
+ Each string is one symbol.
+ """
+ return [ast.literal_eval(l) for l in slist]
+
+
+def read_syms_from_file(filename):
+ """
+ Read a list of symbols in from a file.
+ """
+ with open(filename, 'r') as f:
+ data = f.read()
+ return read_syms_from_list(data.splitlines())
+
+
+def read_blacklist(filename):
+ with open(filename, 'r') as f:
+ data = f.read()
+ lines = [l.strip() for l in data.splitlines() if l.strip()]
+ lines = [l for l in lines if not l.startswith('#')]
+ return lines
+
+
+def write_syms(sym_list, out=None, names_only=False):
+ """
+ Write a list of symbols to the file named by out.
+ """
+ out_str = ''
+ out_list = sym_list
+ out_list.sort(key=lambda x: x['name'])
+ if names_only:
+ out_list = [sym['name'] for sym in sym_list]
+ for sym in out_list:
+ out_str += '%s\n' % sym
+ if out is None:
+ sys.stdout.write(out_str)
+ else:
+ with open(out, 'w') as f:
+ f.write(out_str)
+
+
+_cppfilt_exe = distutils.spawn.find_executable('c++filt')
+
+
+def demangle_symbol(symbol):
+ if _cppfilt_exe is None:
+ return symbol
+ out, _, exit_code = libcxx.util.executeCommandVerbose(
+ [_cppfilt_exe], input=symbol)
+ if exit_code != 0:
+ return symbol
+ return out
+
+
+def is_elf(filename):
+ with open(filename, 'rb') as f:
+ magic_bytes = f.read(4)
+ return magic_bytes == b'\x7fELF'
+
+
+def is_mach_o(filename):
+ with open(filename, 'rb') as f:
+ magic_bytes = f.read(4)
+ return magic_bytes in [
+ '\xfe\xed\xfa\xce', # MH_MAGIC
+ '\xce\xfa\xed\xfe', # MH_CIGAM
+ '\xfe\xed\xfa\xcf', # MH_MAGIC_64
+ '\xcf\xfa\xed\xfe', # MH_CIGAM_64
+ '\xca\xfe\xba\xbe', # FAT_MAGIC
+ '\xbe\xba\xfe\xca' # FAT_CIGAM
+ ]
+
+
+def is_library_file(filename):
+ if sys.platform == 'darwin':
+ return is_mach_o(filename)
+ else:
+ return is_elf(filename)
+
+
+def extract_or_load(filename):
+ import libcxx.sym_check.extract
+ if is_library_file(filename):
+ return libcxx.sym_check.extract.extract_symbols(filename)
+ return read_syms_from_file(filename)
+
+def adjust_mangled_name(name):
+ if not name.startswith('__Z'):
+ return name
+ return name[1:]
+
+new_delete_std_symbols = [
+ '_Znam',
+ '_Znwm',
+ '_ZdaPv',
+ '_ZdaPvm',
+ '_ZdlPv',
+ '_ZdlPvm'
+]
+
+cxxabi_symbols = [
+ '___dynamic_cast',
+ '___gxx_personality_v0',
+ '_ZTIDi',
+ '_ZTIDn',
+ '_ZTIDs',
+ '_ZTIPDi',
+ '_ZTIPDn',
+ '_ZTIPDs',
+ '_ZTIPKDi',
+ '_ZTIPKDn',
+ '_ZTIPKDs',
+ '_ZTIPKa',
+ '_ZTIPKb',
+ '_ZTIPKc',
+ '_ZTIPKd',
+ '_ZTIPKe',
+ '_ZTIPKf',
+ '_ZTIPKh',
+ '_ZTIPKi',
+ '_ZTIPKj',
+ '_ZTIPKl',
+ '_ZTIPKm',
+ '_ZTIPKs',
+ '_ZTIPKt',
+ '_ZTIPKv',
+ '_ZTIPKw',
+ '_ZTIPKx',
+ '_ZTIPKy',
+ '_ZTIPa',
+ '_ZTIPb',
+ '_ZTIPc',
+ '_ZTIPd',
+ '_ZTIPe',
+ '_ZTIPf',
+ '_ZTIPh',
+ '_ZTIPi',
+ '_ZTIPj',
+ '_ZTIPl',
+ '_ZTIPm',
+ '_ZTIPs',
+ '_ZTIPt',
+ '_ZTIPv',
+ '_ZTIPw',
+ '_ZTIPx',
+ '_ZTIPy',
+ '_ZTIa',
+ '_ZTIb',
+ '_ZTIc',
+ '_ZTId',
+ '_ZTIe',
+ '_ZTIf',
+ '_ZTIh',
+ '_ZTIi',
+ '_ZTIj',
+ '_ZTIl',
+ '_ZTIm',
+ '_ZTIs',
+ '_ZTIt',
+ '_ZTIv',
+ '_ZTIw',
+ '_ZTIx',
+ '_ZTIy',
+ '_ZTSDi',
+ '_ZTSDn',
+ '_ZTSDs',
+ '_ZTSPDi',
+ '_ZTSPDn',
+ '_ZTSPDs',
+ '_ZTSPKDi',
+ '_ZTSPKDn',
+ '_ZTSPKDs',
+ '_ZTSPKa',
+ '_ZTSPKb',
+ '_ZTSPKc',
+ '_ZTSPKd',
+ '_ZTSPKe',
+ '_ZTSPKf',
+ '_ZTSPKh',
+ '_ZTSPKi',
+ '_ZTSPKj',
+ '_ZTSPKl',
+ '_ZTSPKm',
+ '_ZTSPKs',
+ '_ZTSPKt',
+ '_ZTSPKv',
+ '_ZTSPKw',
+ '_ZTSPKx',
+ '_ZTSPKy',
+ '_ZTSPa',
+ '_ZTSPb',
+ '_ZTSPc',
+ '_ZTSPd',
+ '_ZTSPe',
+ '_ZTSPf',
+ '_ZTSPh',
+ '_ZTSPi',
+ '_ZTSPj',
+ '_ZTSPl',
+ '_ZTSPm',
+ '_ZTSPs',
+ '_ZTSPt',
+ '_ZTSPv',
+ '_ZTSPw',
+ '_ZTSPx',
+ '_ZTSPy',
+ '_ZTSa',
+ '_ZTSb',
+ '_ZTSc',
+ '_ZTSd',
+ '_ZTSe',
+ '_ZTSf',
+ '_ZTSh',
+ '_ZTSi',
+ '_ZTSj',
+ '_ZTSl',
+ '_ZTSm',
+ '_ZTSs',
+ '_ZTSt',
+ '_ZTSv',
+ '_ZTSw',
+ '_ZTSx',
+ '_ZTSy'
+]
+
+def is_stdlib_symbol_name(name):
+ name = adjust_mangled_name(name)
+ if re.search("@GLIBC|@GCC", name):
+ return False
+ if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name):
+ return True
+ if name in new_delete_std_symbols:
+ return True
+ if name in cxxabi_symbols:
+ return True
+ if name.startswith('_Z'):
+ return True
+ return False
+
+def filter_stdlib_symbols(syms):
+ stdlib_symbols = []
+ other_symbols = []
+ for s in syms:
+ canon_name = adjust_mangled_name(s['name'])
+ if not is_stdlib_symbol_name(canon_name):
+ assert not s['is_defined'] and "found defined non-std symbol"
+ other_symbols += [s]
+ else:
+ stdlib_symbols += [s]
+ return stdlib_symbols, other_symbols