mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-23 18:38:30 +08:00
Change sym_check to filter non-stdlib symbols.
Currently sym_check almost all names found in the binary, including those which are defined in other libraries. This makes our ABI lists harder to maintain. This patch adds a --only-stdlib-symbols option to sym_check which removes all symbols which aren't possibly provided by libc++. It also re-generates the linux ABI list after making this change. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@287294 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -22,7 +22,7 @@ if (LIBCXX_HAS_ABILIST_CONFIGURATION)
|
|||||||
set(ABILIST_FILE "${CMAKE_CURRENT_LIST_DIR}/${TARGET_TRIPLE}.abilist")
|
set(ABILIST_FILE "${CMAKE_CURRENT_LIST_DIR}/${TARGET_TRIPLE}.abilist")
|
||||||
set(SYMDIFF_EXE "${LIBCXX_SOURCE_DIR}/utils/sym_check/sym_diff.py")
|
set(SYMDIFF_EXE "${LIBCXX_SOURCE_DIR}/utils/sym_check/sym_diff.py")
|
||||||
add_custom_target(check-cxx-abilist
|
add_custom_target(check-cxx-abilist
|
||||||
${SYMDIFF_EXE} ${ABILIST_FILE} $<TARGET_SONAME_FILE:cxx_shared>
|
${SYMDIFF_EXE} --only-stdlib-symbols ${ABILIST_FILE} $<TARGET_SONAME_FILE:cxx_shared>
|
||||||
DEPENDS cxx_shared
|
DEPENDS cxx_shared
|
||||||
COMMENT "Testing ABI compatibility...")
|
COMMENT "Testing ABI compatibility...")
|
||||||
endif()
|
endif()
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -12,9 +12,11 @@ extract - A set of function that extract symbol lists from shared libraries.
|
|||||||
"""
|
"""
|
||||||
import distutils.spawn
|
import distutils.spawn
|
||||||
import sys
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
from sym_check import util
|
from sym_check import util
|
||||||
|
|
||||||
|
extract_ignore_names = ['_init', '_fini']
|
||||||
|
|
||||||
class NMExtractor(object):
|
class NMExtractor(object):
|
||||||
"""
|
"""
|
||||||
@@ -65,7 +67,8 @@ class NMExtractor(object):
|
|||||||
return None
|
return None
|
||||||
new_sym = {
|
new_sym = {
|
||||||
'name': bits[0],
|
'name': bits[0],
|
||||||
'type': bits[1]
|
'type': bits[1],
|
||||||
|
'is_defined': (bits[1].lower() != 'u')
|
||||||
}
|
}
|
||||||
new_sym['name'] = new_sym['name'].replace('@@', '@')
|
new_sym['name'] = new_sym['name'].replace('@@', '@')
|
||||||
new_sym = self._transform_sym_type(new_sym)
|
new_sym = self._transform_sym_type(new_sym)
|
||||||
@@ -81,6 +84,8 @@ class NMExtractor(object):
|
|||||||
"""
|
"""
|
||||||
if sym is None or len(sym) < 2:
|
if sym is None or len(sym) < 2:
|
||||||
return False
|
return False
|
||||||
|
if sym['name'] in extract_ignore_names:
|
||||||
|
return False
|
||||||
bad_types = ['t', 'b', 'r', 'd', 'w']
|
bad_types = ['t', 'b', 'r', 'd', 'w']
|
||||||
return (sym['type'] not in bad_types
|
return (sym['type'] not in bad_types
|
||||||
and sym['name'] not in ['__bss_start', '_end', '_edata'])
|
and sym['name'] not in ['__bss_start', '_end', '_edata'])
|
||||||
@@ -148,8 +153,11 @@ class ReadElfExtractor(object):
|
|||||||
'name': parts[7],
|
'name': parts[7],
|
||||||
'size': int(parts[2]),
|
'size': int(parts[2]),
|
||||||
'type': parts[3],
|
'type': parts[3],
|
||||||
|
'is_defined': (parts[6] != 'UND')
|
||||||
}
|
}
|
||||||
assert new_sym['type'] in ['OBJECT', 'FUNC', 'NOTYPE']
|
assert new_sym['type'] in ['OBJECT', 'FUNC', 'NOTYPE']
|
||||||
|
if new_sym['name'] in extract_ignore_names:
|
||||||
|
continue
|
||||||
if new_sym['type'] == 'NOTYPE':
|
if new_sym['type'] == 'NOTYPE':
|
||||||
continue
|
continue
|
||||||
if new_sym['type'] == 'FUNC':
|
if new_sym['type'] == 'FUNC':
|
||||||
|
@@ -12,7 +12,7 @@ import distutils.spawn
|
|||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
def execute_command(cmd, input_str=None):
|
def execute_command(cmd, input_str=None):
|
||||||
"""
|
"""
|
||||||
@@ -135,3 +135,40 @@ def extract_or_load(filename):
|
|||||||
if is_library_file(filename):
|
if is_library_file(filename):
|
||||||
return sym_check.extract.extract_symbols(filename)
|
return sym_check.extract.extract_symbols(filename)
|
||||||
return read_syms_from_file(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'
|
||||||
|
]
|
||||||
|
|
||||||
|
def is_stdlib_symbol_name(name):
|
||||||
|
name = adjust_mangled_name(name)
|
||||||
|
if name in new_delete_std_symbols:
|
||||||
|
return True
|
||||||
|
if re.search("@GLIBC|@GCC", name):
|
||||||
|
return False
|
||||||
|
if re.search('(St[0-9])|(__cxa)|(__cxxabi)', name):
|
||||||
|
return True
|
||||||
|
return True
|
||||||
|
|
||||||
|
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 \
|
||||||
|
'have non-stdlib symbol defined in stdlib'
|
||||||
|
other_symbols += [s]
|
||||||
|
else:
|
||||||
|
stdlib_symbols += [s]
|
||||||
|
return stdlib_symbols, other_symbols
|
||||||
|
@@ -27,6 +27,9 @@ def main():
|
|||||||
'--removed-only', dest='removed_only',
|
'--removed-only', dest='removed_only',
|
||||||
help='Only print removed symbols',
|
help='Only print removed symbols',
|
||||||
action='store_true', default=False)
|
action='store_true', default=False)
|
||||||
|
parser.add_argument('--only-stdlib-symbols', dest='only_stdlib',
|
||||||
|
help="Filter all symbols not related to the stdlib",
|
||||||
|
action='store_true', default=False)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'-o', '--output', dest='output',
|
'-o', '--output', dest='output',
|
||||||
help='The output file. stdout is used if not given',
|
help='The output file. stdout is used if not given',
|
||||||
@@ -44,6 +47,10 @@ def main():
|
|||||||
old_syms_list = util.extract_or_load(args.old_syms)
|
old_syms_list = util.extract_or_load(args.old_syms)
|
||||||
new_syms_list = util.extract_or_load(args.new_syms)
|
new_syms_list = util.extract_or_load(args.new_syms)
|
||||||
|
|
||||||
|
if args.only_stdlib:
|
||||||
|
old_syms_list, _ = util.filter_stdlib_symbols(old_syms_list)
|
||||||
|
new_syms_list, _ = util.filter_stdlib_symbols(new_syms_list)
|
||||||
|
|
||||||
added, removed, changed = diff.diff(old_syms_list, new_syms_list)
|
added, removed, changed = diff.diff(old_syms_list, new_syms_list)
|
||||||
if args.removed_only:
|
if args.removed_only:
|
||||||
added = {}
|
added = {}
|
||||||
|
@@ -25,11 +25,16 @@ def main():
|
|||||||
parser.add_argument('--names-only', dest='names_only',
|
parser.add_argument('--names-only', dest='names_only',
|
||||||
help='Output only the name of the symbol',
|
help='Output only the name of the symbol',
|
||||||
action='store_true', default=False)
|
action='store_true', default=False)
|
||||||
|
parser.add_argument('--only-stdlib-symbols', dest='only_stdlib',
|
||||||
|
help="Filter all symbols not related to the stdlib",
|
||||||
|
action='store_true', default=False)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
if args.output is not None:
|
if args.output is not None:
|
||||||
print('Extracting symbols from %s to %s.'
|
print('Extracting symbols from %s to %s.'
|
||||||
% (args.library, args.output))
|
% (args.library, args.output))
|
||||||
syms = extract.extract_symbols(args.library)
|
syms = extract.extract_symbols(args.library)
|
||||||
|
if args.only_stdlib:
|
||||||
|
syms, other_syms = util.filter_stdlib_symbols(syms)
|
||||||
util.write_syms(syms, out=args.output, names_only=args.names_only)
|
util.write_syms(syms, out=args.output, names_only=args.names_only)
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user