aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xemcc26
-rwxr-xr-xtests/runner.py33
-rw-r--r--tools/shared.py8
3 files changed, 58 insertions, 9 deletions
diff --git a/emcc b/emcc
index f19e614e..48631d64 100755
--- a/emcc
+++ b/emcc
@@ -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)