From 1b9bc33bcffebbac17062a71cb1440d4cd18f03b Mon Sep 17 00:00:00 2001 From: Chris Dziemborowicz Date: Sat, 16 Mar 2019 17:12:19 +0000 Subject: [PATCH] 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). --- tools/make_distrib.py | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/tools/make_distrib.py b/tools/make_distrib.py index f835c946f..8097c3e21 100644 --- a/tools/make_distrib.py +++ b/tools/make_distrib.py @@ -307,7 +307,7 @@ def get_exported_symbols(file): """ Returns the global symbols exported by |file|. """ symbols = [] - # Each symbol line has a value is like: + # Each symbol line has a value like: # 0000000000000000 T _cef_sandbox_initialize cmdline = 'nm -g -U %s' % file result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools')) @@ -322,6 +322,25 @@ def get_exported_symbols(file): 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): """ Combine multiple static libraries into a single static library. """ intermediate_obj = None @@ -375,6 +394,17 @@ def combine_libs(platform, build_dir, libs, dest_lib): print 'Got', result_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): """ Run a command. """ @@ -913,6 +943,8 @@ elif platform == 'macosx': 'obj/sandbox/mac/libseatbelt.a', 'obj/sandbox/mac/libseatbelt_proto.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