Mac: Fix undefined C++ symbols in cef_sandbox.a (see issue #2629)

This change updates make_distrib.py to link in all of libc++ and libc++abi from the Chromium build when generating cef_sandbox.a. This increases the size of the release build of cef_sandbox.a from about 0.5 MB to about 2.0 MB, but it ensures that no C++ symbols are imported by the archive.

Linking cef_sandbox.a with an incompatible C++ library prior to this change could cause undefined behavior in the resulting binary.

To make sure that we do not regress this fix, this change also updates make_distrib.py to verify that no C++ symbols are imported by cef_sandbox.a after it is generated (in a way similar to the way we verify that cef_sandbox.a exports the correct symbols).
This commit is contained in:
Chris Dziemborowicz 2019-03-16 17:12:19 +00:00 committed by Marshall Greenblatt
parent a4f0b4c5fb
commit 1b9bc33bcf
1 changed files with 33 additions and 1 deletions

View File

@ -307,7 +307,7 @@ def get_exported_symbols(file):
""" Returns the global symbols exported by |file|. """ """ Returns the global symbols exported by |file|. """
symbols = [] symbols = []
# Each symbol line has a value is like: # Each symbol line has a value like:
# 0000000000000000 T _cef_sandbox_initialize # 0000000000000000 T _cef_sandbox_initialize
cmdline = 'nm -g -U %s' % file cmdline = 'nm -g -U %s' % file
result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools')) result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
@ -322,6 +322,25 @@ def get_exported_symbols(file):
return symbols return symbols
def get_undefined_symbols(file):
""" Returns the undefined symbols imported by |file|. """
symbols = []
# Each symbol line has a value like:
# cef_sandbox.a:cef_sandbox.o: _memcpy
cmdline = 'nm -u -A %s' % file
result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
if len(result['err']) > 0:
raise Exception('ERROR: nm failed: %s' % result['err'])
for line in result['out'].split('\n'):
if line.find(': ') < 0:
continue
symbol = line[line.rfind(': ') + 2:]
symbols.append(symbol)
return symbols
def combine_libs(platform, build_dir, libs, dest_lib): def combine_libs(platform, build_dir, libs, dest_lib):
""" Combine multiple static libraries into a single static library. """ """ Combine multiple static libraries into a single static library. """
intermediate_obj = None intermediate_obj = None
@ -375,6 +394,17 @@ def combine_libs(platform, build_dir, libs, dest_lib):
print 'Got', result_symbols print 'Got', result_symbols
raise Exception('Failure verifying exported symbols') raise Exception('Failure verifying exported symbols')
# Verify that no C++ symbols are imported by the archive file. If the
# archive imports C++ symbols and the client app links an incompatible C++
# library, the result will be undefined behavior.
print 'Verifying imported (undefined) symbols...'
undefined_symbols = get_undefined_symbols(dest_lib)
cpp_symbols = list(filter(lambda symbol: symbol.startswith('__Z'),
undefined_symbols))
if cpp_symbols:
print 'Found C++ symbols:', cpp_symbols
raise Exception('Failure verifying imported (undefined) symbols')
def run(command_line, working_dir): def run(command_line, working_dir):
""" Run a command. """ """ Run a command. """
@ -913,6 +943,8 @@ elif platform == 'macosx':
'obj/sandbox/mac/libseatbelt.a', 'obj/sandbox/mac/libseatbelt.a',
'obj/sandbox/mac/libseatbelt_proto.a', 'obj/sandbox/mac/libseatbelt_proto.a',
'obj/third_party/protobuf/libprotobuf_lite.a', 'obj/third_party/protobuf/libprotobuf_lite.a',
'obj/buildtools/third_party/libc++/libc++/*.o',
'obj/buildtools/third_party/libc++abi/libc++abi/*.o',
] ]
# Generate the cef_sandbox.a merged library. A separate *_sandbox build # Generate the cef_sandbox.a merged library. A separate *_sandbox build