| Index: src/vm/ffi.cc
|
| diff --git a/src/vm/ffi.cc b/src/vm/ffi.cc
|
| index a101ae2b5b89aa9611e8c1d045f5704e3ba46f3a..7ee6823330898ef69cb2870198ebf3f6fdfcf513 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,61 @@ void* ForeignFunctionInterface::LookupInDefaultLibraries(const char* symbol) {
|
| return NULL;
|
| }
|
|
|
| +NATIVE(ForeignLibraryLookup) {
|
| + char* library = arguments[0]->IsString()
|
| + ? AsForeignString(String::cast(arguments[0]))
|
| + : NULL;
|
| + 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 = ForeignUtils::DirectoryName(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,
|
| + ForeignUtils::kLibBundlePrefix, library,
|
| + ForeignUtils::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]))
|
| @@ -402,7 +459,11 @@ NATIVE(ForeignSet##suffix) { \
|
| return Failure::wrong_argument_type(); \
|
| } \
|
| type* address = reinterpret_cast<type*>(AsForeignWord(arguments[0])); \
|
| - *address = AsForeignWord(value); \
|
| + if (value->IsSmi()) { \
|
| + *address = Smi::cast(value)->value(); \
|
| + } else { \
|
| + *address = LargeInteger::cast(value)->value(); \
|
| + } \
|
| return value; \
|
| }
|
|
|
|
|