| Index: src/vm/ffi.cc
|
| diff --git a/src/vm/ffi.cc b/src/vm/ffi.cc
|
| index a101ae2b5b89aa9611e8c1d045f5704e3ba46f3a..355e6da83b1e3df426773d6fc164250045d9329d 100644
|
| --- a/src/vm/ffi.cc
|
| +++ b/src/vm/ffi.cc
|
| @@ -6,8 +6,10 @@
|
|
|
| #include <dlfcn.h>
|
| #include <errno.h>
|
| +#include <sys/param.h>
|
|
|
| #include "src/shared/asan_helper.h"
|
| +#include "src/shared/platform.h"
|
| #include "src/vm/natives.h"
|
| #include "src/vm/object.h"
|
| #include "src/vm/port.h"
|
| @@ -74,6 +76,59 @@ void* ForeignFunctionInterface::LookupInDefaultLibraries(const char* symbol) {
|
| return NULL;
|
| }
|
|
|
| +NATIVE(ForeignLibraryLookup) {
|
| + char* library = AsForeignString(String::cast(arguments[0]));
|
| + void* result = dlopen(library, RTLD_LOCAL | RTLD_LAZY);
|
| + if (result == NULL) {
|
| + fprintf(stderr, "Failed libary lookup(%s): %s\n", library, dlerror());
|
| + }
|
| + free(library);
|
| + return result != NULL
|
| + ? process->ToInteger(reinterpret_cast<intptr_t>(result))
|
| + : Failure::index_out_of_bounds();
|
| +}
|
| +
|
| +NATIVE(ForeignLibraryGetFunction) {
|
| + word address = AsForeignWord(arguments[0]);
|
| + void* handle = reinterpret_cast<void*>(address);
|
| + char* name = AsForeignString(String::cast(arguments[1]));
|
| + if (handle == NULL) handle = dlopen(NULL, RTLD_LOCAL | RTLD_LAZY);
|
| + void* result = dlsym(handle, name);
|
| + free(name);
|
| + return result != NULL
|
| + ? process->ToInteger(reinterpret_cast<intptr_t>(result))
|
| + : Failure::index_out_of_bounds();
|
| +}
|
| +
|
| +NATIVE(ForeignLibraryBundlePath) {
|
| + char* library = AsForeignString(String::cast(arguments[0]));
|
| + char executable[MAXPATHLEN + 1];
|
| + GetPathOfExecutable(executable, sizeof(executable));
|
| + char* directory = FFIUtils::DirName(executable);
|
| + // dirname on linux may mess with the content of the buffer, so we use a fresh
|
| + // buffer for the result. If anybody cares this can be optimized by manually
|
| + // writing the strings other than dirname to the executable buffer.
|
| + char result[MAXPATHLEN + 1];
|
| + int wrote = snprintf(result, MAXPATHLEN + 1, "%s%s%s%s", directory,
|
| + FFIUtils::kLibBundlePrefix, library,
|
| + FFIUtils::kLibBundlePostfix);
|
| + if (wrote > MAXPATHLEN) {
|
| + return Failure::index_out_of_bounds();
|
| + }
|
| + free(library);
|
| + return process->NewStringFromAscii(List<const char>(result, strlen(result)));
|
| +}
|
| +
|
| +NATIVE(ForeignLibraryClose) {
|
| + word address = AsForeignWord(arguments[0]);
|
| + void* handle = reinterpret_cast<void*>(address);
|
| + if (dlclose(handle) != 0) {
|
| + fprintf(stderr, "Failed to close handle: %s\n", dlerror());
|
| + return Failure::index_out_of_bounds();
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| NATIVE(ForeignLookup) {
|
| char* library = arguments[1]->IsString()
|
| ? AsForeignString(String::cast(arguments[1]))
|
|
|