diff options
-rwxr-xr-x | emcc | 26 | ||||
-rwxr-xr-x | tests/runner.py | 33 | ||||
-rw-r--r-- | tools/shared.py | 8 |
3 files changed, 58 insertions, 9 deletions
@@ -991,20 +991,32 @@ try: for name, create, fix, library_symbols in [('libcxx', create_libcxx, fix_libcxx, libcxx_symbols), ('libcxxabi', create_libcxxabi, fix_libcxxabi, libcxxabi_symbols), ('dlmalloc', create_dlmalloc, fix_dlmalloc, dlmalloc_symbols)]: - need = [] - has = [] + need = set() + has = set() for temp_file in temp_files: symbols = shared.Building.llvm_nm(temp_file) for library_symbol in library_symbols: if library_symbol in symbols.undefs: - need.append(library_symbol) + need.add(library_symbol) if library_symbol in symbols.defs: - has.append(library_symbol) - if DEBUG: print >> sys.stderr, 'emcc: considering including %s: we need |%s| and have |%s|' % (name, str(need), str(has)) - if force or (need and not has): + has.add(library_symbol) + for haz in has: # remove symbols that are supplied by another of the inputs + if haz in need: + need.remove(haz) + if DEBUG: print >> sys.stderr, 'emcc: considering including %s: we need %s and have %s' % (name, str(need), str(has)) + if force or len(need) > 0: # We need to build and link the library in if DEBUG: print >> sys.stderr, 'emcc: including %s' % name - extra_files_to_link.append(shared.Cache.get(name, create)) + libfile = shared.Cache.get(name, create) + if len(has) > 0: + # remove the symbols we do not need + fixed = in_temp(uniquename(libfile)) + '.bc' + shutil.copyfile(libfile, fixed) + for haz in has: + if DEBUG: print >> sys.stderr, 'emcc: including: removing symbol "%s" that we have' % haz + shared.Building.remove_symbol(fixed, haz) + libfile = fixed + extra_files_to_link.append(libfile) force = True if fix: fix() diff --git a/tests/runner.py b/tests/runner.py index 3dfef3e9..08dec7b3 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5779,6 +5779,39 @@ int main(int argc, char **argv) { ]: self.do_run(src.replace('{{{ NEW }}}', new).replace('{{{ DELETE }}}', delete), '*1,0*') + def test_dlmalloc_partial(self): + if self.emcc_args is None: return self.skip('only emcc will link in dlmalloc') + # present part of the symbols of dlmalloc, not all + src = open(path_from_root('tests', 'new.cpp')).read().replace('{{{ NEW }}}', 'new int').replace('{{{ DELETE }}}', 'delete') + ''' +void * +operator new(size_t size) +{ + printf("new %d!\\n", size); + return malloc(size); +} +''' + self.do_run(src, 'new 4!\n*1,0*') + + def test_dlmalloc_partial_2(self): + if self.emcc_args is None or 'SAFE_HEAP' in str(self.emcc_args): return self.skip('only emcc will link in dlmalloc, and we do unsafe stuff') + # present part of the symbols of dlmalloc, not all. malloc is harder to link than new which is weak. + src = r''' + #include <stdio.h> + #include <stdlib.h> + void *malloc(size_t size) + { + return (void*)123; + } + int main() { + void *x = malloc(10); + printf("got %p\n", x); + free(x); + printf("freed the faker\n"); + return 1; + } +''' + self.do_run(src, 'got 0x7b\nfreed') + def test_libcxx(self): self.do_run(open(path_from_root('tests', 'hashtest.cpp')).read(), 'june -> 30\nPrevious (in alphabetical order) is july\nNext (in alphabetical order) is march') diff --git a/tools/shared.py b/tools/shared.py index 1f9c8fe5..86a5ba77 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -707,6 +707,11 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e return generated_libs @staticmethod + def remove_symbol(filename, symbol): + Popen([LLVM_EXTRACT, filename, '-delete', '-glob=' + symbol, '-o', filename], stderr=PIPE).communicate() + Popen([LLVM_EXTRACT, filename, '-delete', '-func=' + symbol, '-o', filename], stderr=PIPE).communicate() + + @staticmethod def link(files, target, remove_duplicates=False): actual_files = [] unresolved_symbols = set(['main']) # tracking unresolveds is necessary for .a linking, see below. (and main is always a necessary symbol) @@ -775,8 +780,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e print >> sys.stderr, 'emcc: warning: removing duplicates in', actual for dupe in dupes: print >> sys.stderr, 'emcc: warning: removing duplicate', dupe - Popen([LLVM_EXTRACT, actual, '-delete', '-glob=' + dupe, '-o', actual], stderr=PIPE).communicate() - Popen([LLVM_EXTRACT, actual, '-delete', '-func=' + dupe, '-o', actual], stderr=PIPE).communicate() + Building.remove_symbol(actual, dupe) Popen([LLVM_EXTRACT, actual, '-delete', '-glob=.str', '-o', actual], stderr=PIPE).communicate() # garbage that appears here seen_symbols = seen_symbols.union(symbols.defs) |