diff options
author | Jez Ng <me@jezng.com> | 2013-07-09 07:02:47 -0700 |
---|---|---|
committer | Jez Ng <me@jezng.com> | 2013-07-11 20:37:57 -0700 |
commit | c1e1d87bc3b9e249795543e44a1224c2f03154ce (patch) | |
tree | 3f8506715b75acdf97e68dfdc3e4c1a35ffccb5a | |
parent | 9f9af4cefb142960cad37b3f43f4777e4334f2f2 (diff) |
Implement self-dlopen.
-rwxr-xr-x | emscripten.py | 10 | ||||
-rw-r--r-- | src/jsifier.js | 2 | ||||
-rw-r--r-- | src/library.js | 81 | ||||
-rw-r--r-- | src/modules.js | 3 | ||||
-rwxr-xr-x | tests/runner.py | 29 |
5 files changed, 88 insertions, 37 deletions
diff --git a/emscripten.py b/emscripten.py index d9367566..921ab879 100755 --- a/emscripten.py +++ b/emscripten.py @@ -620,6 +620,16 @@ Runtime.stackRestore = function(top) { asm['stackRestore'](top) }; // EMSCRIPTEN_END_FUNCS '''] + # Create symbol table for self-dlopen + if settings.get('LINKABLE'): + GLOBAL_BASE = forwarded_json['Runtime']['GLOBAL_BASE'] + symbol_table = {k:v+8 for k,v in forwarded_json['Variables']['indexedGlobals'].iteritems()} + for raw in last_forwarded_json['Functions']['tables'].itervalues(): + table = raw[raw.find('[')+1:raw.find(']')].split(",") + symbol_table.update(map(lambda x: (x[1], x[0]), + filter(lambda x: x[1] != '0', enumerate(table)))) + outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table)) + for funcs_js_item in funcs_js: # do this loop carefully to save memory funcs_js_item = indexize(funcs_js_item) funcs_js_item = blockaddrsize(funcs_js_item) diff --git a/src/jsifier.js b/src/jsifier.js index 82b78d0a..bc073aaa 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -602,6 +602,8 @@ function JSify(data, functionsOnly, givenFunctions) { var associatedSourceFile = "NO_SOURCE"; } + if (LINKABLE) Functions.getIndex(func.ident); + func.JS += 'function ' + func.ident + '(' + paramIdents.join(', ') + ') {\n'; if (PGO) { diff --git a/src/library.js b/src/library.js index bf969fd7..19452bb1 100644 --- a/src/library.js +++ b/src/library.js @@ -5886,7 +5886,7 @@ LibraryManager.library = { dlopen: function(filename, flag) { // void *dlopen(const char *file, int mode); // http://pubs.opengroup.org/onlinepubs/009695399/functions/dlopen.html - filename = (ENV['LD_LIBRARY_PATH'] || '/') + Pointer_stringify(filename); + filename = filename === 0 ? '__self__' : (ENV['LD_LIBRARY_PATH'] || '/') + Pointer_stringify(filename); if (DLFCN_DATA.loadedLibNames[filename]) { // Already loaded; increment ref count and return. @@ -5895,48 +5895,55 @@ LibraryManager.library = { return handle; } - var target = FS.findObject(filename); - if (!target || target.isFolder || target.isDevice) { - DLFCN_DATA.errorMsg = 'Could not find dynamic lib: ' + filename; - return 0; + if (filename === '__self__') { + var handle = -1; + var lib_module = Module; + var cached_functions = SYMBOL_TABLE; } else { - FS.forceLoadFile(target); - var lib_data = intArrayToString(target.contents); - } + var target = FS.findObject(filename); + if (!target || target.isFolder || target.isDevice) { + DLFCN_DATA.errorMsg = 'Could not find dynamic lib: ' + filename; + return 0; + } else { + FS.forceLoadFile(target); + var lib_data = intArrayToString(target.contents); + } - try { - var lib_module = eval(lib_data)({{{ Functions.getTable('x') }}}.length); - } catch (e) { + try { + var lib_module = eval(lib_data)({{{ Functions.getTable('x') }}}.length); + } catch (e) { #if ASSERTIONS - Module.printErr('Error in loading dynamic library: ' + e); + Module.printErr('Error in loading dynamic library: ' + e); #endif - DLFCN_DATA.errorMsg = 'Could not evaluate dynamic lib: ' + filename; - return 0; - } + DLFCN_DATA.errorMsg = 'Could not evaluate dynamic lib: ' + filename; + return 0; + } - // Not all browsers support Object.keys(). - var handle = 1; - for (var key in DLFCN_DATA.loadedLibs) { - if (DLFCN_DATA.loadedLibs.hasOwnProperty(key)) handle++; - } + // Not all browsers support Object.keys(). + var handle = 1; + for (var key in DLFCN_DATA.loadedLibs) { + if (DLFCN_DATA.loadedLibs.hasOwnProperty(key)) handle++; + } + // We don't care about RTLD_NOW and RTLD_LAZY. + if (flag & 256) { // RTLD_GLOBAL + for (var ident in lib_module) { + if (lib_module.hasOwnProperty(ident)) { + Module[ident] = lib_module[ident]; + } + } + } + + var cached_functions = {}; + } DLFCN_DATA.loadedLibs[handle] = { refcount: 1, name: filename, module: lib_module, - cached_functions: {} + cached_functions: cached_functions }; DLFCN_DATA.loadedLibNames[filename] = handle; - // We don't care about RTLD_NOW and RTLD_LAZY. - if (flag & 256) { // RTLD_GLOBAL - for (var ident in lib_module) { - if (lib_module.hasOwnProperty(ident)) { - Module[ident] = lib_module[ident]; - } - } - } - return handle; }, // int dlclose(void* handle); @@ -5968,13 +5975,15 @@ LibraryManager.library = { return 0; } else { var lib = DLFCN_DATA.loadedLibs[handle]; - if (!lib.module.hasOwnProperty(symbol)) { - DLFCN_DATA.errorMsg = ('Tried to lookup unknown symbol "' + symbol + - '" in dynamic lib: ' + lib.name); - return 0; + // self-dlopen means that lib.module is not a superset of + // cached_functions, so check the latter first + if (lib.cached_functions.hasOwnProperty(symbol)) { + return lib.cached_functions[symbol]; } else { - if (lib.cached_functions.hasOwnProperty(symbol)) { - return lib.cached_functions[symbol]; + if (!lib.module.hasOwnProperty(symbol)) { + DLFCN_DATA.errorMsg = ('Tried to lookup unknown symbol "' + symbol + + '" in dynamic lib: ' + lib.name); + return 0; } else { var result = lib.module[symbol]; if (typeof result == 'function') { diff --git a/src/modules.js b/src/modules.js index a6aa2644..53d97817 100644 --- a/src/modules.js +++ b/src/modules.js @@ -449,7 +449,8 @@ var PassManager = { Types: Types, Variables: Variables, Functions: Functions, - EXPORTED_FUNCTIONS: EXPORTED_FUNCTIONS // needed for asm.js global constructors (ctors) + EXPORTED_FUNCTIONS: EXPORTED_FUNCTIONS, // needed for asm.js global constructors (ctors) + Runtime: { GLOBAL_BASE: Runtime.GLOBAL_BASE } })); } else if (phase == 'funcs') { print('\n//FORWARDED_DATA:' + JSON.stringify({ diff --git a/tests/runner.py b/tests/runner.py index b21eee08..a892eb56 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -5885,6 +5885,35 @@ def process(filename): self.do_run(src, '100\n200\n13\n42\n', post_build=add_pre_run_and_checks) + def test_dlfcn_self(self): + if Settings.USE_TYPED_ARRAYS == 1: return self.skip('Does not work with USE_TYPED_ARRAYS=1') + Settings.LINKABLE = 1 + + src = r''' +#include <stdio.h> +#include <dlfcn.h> + +int global = 123; + +extern "C" __attribute__((noinline)) void foo(int x) { + printf("%d\n", x); +} + +void repeatable() { + void* self = dlopen(NULL, RTLD_LAZY); + int* global_ptr = (int*)dlsym(self, "global"); + void (*foo_ptr)(int) = (void (*)(int))dlsym(self, "foo"); + foo_ptr(*global_ptr); + dlclose(self); +} + +int main() { + repeatable(); + repeatable(); + return 0; +}''' + self.do_run(src, '123\n123') + def test_rand(self): return self.skip('rand() is now random') # FIXME |