blob: 0ebde9034cab60169a5541a652777214d2cfb199 [file] [log] [blame]
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
import ast
import distutils.spawn
import sys
import re
import libcxx.util
from pprint import pformat
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 =
return read_syms_from_list(data.splitlines())
def read_blacklist(filename):
with open(filename, 'r') as f:
data =
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, filter=None):
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 filter is not None:
out_list = filter(out_list)
if names_only:
out_list = [sym['name'] for sym in out_list]
for sym in out_list:
# Use pformat for consistent ordering of keys.
out_str += pformat(sym, width=100000) + '\n'
if out is None:
with open(out, 'w') as f:
_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 =
return magic_bytes == b'\x7fELF'
def is_mach_o(filename):
with open(filename, 'rb') as f:
magic_bytes =
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)
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 = [
cxxabi_symbols = [
def is_stdlib_symbol_name(name, sym):
name = adjust_mangled_name(name)
if"@GLIBC|@GCC", name):
# Only when symbol is defined do we consider it ours
return sym['is_defined']
if'(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, s):
other_symbols += [s]
stdlib_symbols += [s]
return stdlib_symbols, other_symbols