
For the same reason why we used to have USE_LIBBACKTRACE with the old Android makefiles, allow to build Mesa without linking to it. In recent VNDK versions, libbacktrace isn't available. When building without linking libbacktrace, for some reason some symbols related to C++ exception handling are exposed. Allow them in the symbols check script. Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com> Signed-off-by: Helen Koike <helen.koike@collabora.com> Reviewed-by: Sergi Blanch Torné <sergi.blanch.torne@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20019>
215 lines
6.6 KiB
Python
215 lines
6.6 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
|
|
# This list contains symbols that _might_ be exported for some platforms
|
|
PLATFORM_SYMBOLS = [
|
|
'__bss_end__',
|
|
'__bss_start__',
|
|
'__bss_start',
|
|
'__cxa_guard_abort',
|
|
'__cxa_guard_acquire',
|
|
'__cxa_guard_release',
|
|
'__cxa_allocate_dependent_exception',
|
|
'__cxa_allocate_exception',
|
|
'__cxa_begin_catch',
|
|
'__cxa_call_unexpected',
|
|
'__cxa_current_exception_type',
|
|
'__cxa_current_primary_exception',
|
|
'__cxa_decrement_exception_refcount',
|
|
'__cxa_deleted_virtual',
|
|
'__cxa_demangle',
|
|
'__cxa_end_catch',
|
|
'__cxa_free_dependent_exception',
|
|
'__cxa_free_exception',
|
|
'__cxa_get_exception_ptr',
|
|
'__cxa_get_globals',
|
|
'__cxa_get_globals_fast',
|
|
'__cxa_increment_exception_refcount',
|
|
'__cxa_new_handler',
|
|
'__cxa_pure_virtual',
|
|
'__cxa_rethrow',
|
|
'__cxa_rethrow_primary_exception',
|
|
'__cxa_terminate_handler',
|
|
'__cxa_throw',
|
|
'__cxa_uncaught_exception',
|
|
'__cxa_uncaught_exceptions',
|
|
'__cxa_unexpected_handler',
|
|
'__dynamic_cast',
|
|
'__emutls_get_address',
|
|
'__gxx_personality_v0',
|
|
'__end__',
|
|
'__odr_asan._glapi_Context',
|
|
'__odr_asan._glapi_Dispatch',
|
|
'_bss_end__',
|
|
'_edata',
|
|
'_end',
|
|
'_fini',
|
|
'_init',
|
|
'_fbss',
|
|
'_fdata',
|
|
'_ftext',
|
|
]
|
|
|
|
def get_symbols_nm(nm, lib):
|
|
'''
|
|
List all the (non platform-specific) symbols exported by the library
|
|
using `nm`
|
|
'''
|
|
symbols = []
|
|
platform_name = platform.system()
|
|
output = subprocess.check_output([nm, '-gP', lib],
|
|
stderr=open(os.devnull, 'w')).decode("ascii")
|
|
for line in output.splitlines():
|
|
fields = line.split()
|
|
if len(fields) == 2 or fields[1] == 'U':
|
|
continue
|
|
symbol_name = fields[0]
|
|
if platform_name == 'Linux':
|
|
if symbol_name in PLATFORM_SYMBOLS:
|
|
continue
|
|
elif platform_name == 'Darwin':
|
|
assert symbol_name[0] == '_'
|
|
symbol_name = symbol_name[1:]
|
|
symbols.append(symbol_name)
|
|
return symbols
|
|
|
|
|
|
def get_symbols_dumpbin(dumpbin, lib):
|
|
'''
|
|
List all the (non platform-specific) symbols exported by the library
|
|
using `dumpbin`
|
|
'''
|
|
symbols = []
|
|
output = subprocess.check_output([dumpbin, '/exports', lib],
|
|
stderr=open(os.devnull, 'w')).decode("ascii")
|
|
for line in output.splitlines():
|
|
fields = line.split()
|
|
# The lines with the symbols are made of at least 4 columns; see details below
|
|
if len(fields) < 4:
|
|
continue
|
|
try:
|
|
# Making sure the first 3 columns are a dec counter, a hex counter
|
|
# and a hex address
|
|
_ = int(fields[0], 10)
|
|
_ = int(fields[1], 16)
|
|
_ = int(fields[2], 16)
|
|
except ValueError:
|
|
continue
|
|
symbol_name = fields[3]
|
|
# De-mangle symbols
|
|
if symbol_name[0] == '_' and '@' in symbol_name:
|
|
symbol_name = symbol_name[1:].split('@')[0]
|
|
symbols.append(symbol_name)
|
|
return symbols
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--symbols-file',
|
|
action='store',
|
|
required=True,
|
|
help='path to file containing symbols')
|
|
parser.add_argument('--lib',
|
|
action='store',
|
|
required=True,
|
|
help='path to library')
|
|
parser.add_argument('--nm',
|
|
action='store',
|
|
help='path to binary (or name in $PATH)')
|
|
parser.add_argument('--dumpbin',
|
|
action='store',
|
|
help='path to binary (or name in $PATH)')
|
|
parser.add_argument('--ignore-symbol',
|
|
action='append',
|
|
help='do not process this symbol')
|
|
args = parser.parse_args()
|
|
|
|
try:
|
|
if platform.system() == 'Windows':
|
|
if not args.dumpbin:
|
|
parser.error('--dumpbin is mandatory')
|
|
lib_symbols = get_symbols_dumpbin(args.dumpbin, args.lib)
|
|
else:
|
|
if not args.nm:
|
|
parser.error('--nm is mandatory')
|
|
lib_symbols = get_symbols_nm(args.nm, args.lib)
|
|
except:
|
|
# We can't run this test, but we haven't technically failed it either
|
|
# Return the GNU "skip" error code
|
|
exit(77)
|
|
mandatory_symbols = []
|
|
optional_symbols = []
|
|
with open(args.symbols_file) as symbols_file:
|
|
qualifier_optional = '(optional)'
|
|
for line in symbols_file.readlines():
|
|
|
|
# Strip comments
|
|
line = line.split('#')[0]
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
|
|
# Line format:
|
|
# [qualifier] symbol
|
|
qualifier = None
|
|
symbol = None
|
|
|
|
fields = line.split()
|
|
if len(fields) == 1:
|
|
symbol = fields[0]
|
|
elif len(fields) == 2:
|
|
qualifier = fields[0]
|
|
symbol = fields[1]
|
|
else:
|
|
print(args.symbols_file + ': invalid format: ' + line)
|
|
exit(1)
|
|
|
|
# The only supported qualifier is 'optional', which means the
|
|
# symbol doesn't have to be exported by the library
|
|
if qualifier and not qualifier == qualifier_optional:
|
|
print(args.symbols_file + ': invalid qualifier: ' + qualifier)
|
|
exit(1)
|
|
|
|
if qualifier == qualifier_optional:
|
|
optional_symbols.append(symbol)
|
|
else:
|
|
mandatory_symbols.append(symbol)
|
|
|
|
unknown_symbols = []
|
|
for symbol in lib_symbols:
|
|
if symbol in mandatory_symbols:
|
|
continue
|
|
if symbol in optional_symbols:
|
|
continue
|
|
if args.ignore_symbol and symbol in args.ignore_symbol:
|
|
continue
|
|
if symbol[:2] == '_Z':
|
|
# As ajax found out, the compiler intentionally exports symbols
|
|
# that we explicitely asked it not to export, and we can't do
|
|
# anything about it:
|
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36022#c4
|
|
continue
|
|
unknown_symbols.append(symbol)
|
|
|
|
missing_symbols = [
|
|
sym for sym in mandatory_symbols if sym not in lib_symbols
|
|
]
|
|
|
|
for symbol in unknown_symbols:
|
|
print(args.lib + ': unknown symbol exported: ' + symbol)
|
|
|
|
for symbol in missing_symbols:
|
|
print(args.lib + ': missing symbol: ' + symbol)
|
|
|
|
if unknown_symbols or missing_symbols:
|
|
exit(1)
|
|
exit(0)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|