mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:59:47 +00:00
e64738ffbc
Change-Id: I6be84f24f0ac245ba176748e4a3ec1ba782798ce Cq-Include-Trybots: luci.dart.try:vm-kernel-win-debug-x64-try,vm-kernel-mac-debug-x64-try,vm-ffi-android-debug-arm-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/113687 Commit-Queue: Samir Jindel <sjindel@google.com> Reviewed-by: Daco Harkes <dacoharkes@google.com>
147 lines
4.7 KiB
C++
147 lines
4.7 KiB
C++
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
#include "include/dart_api.h"
|
|
#include "vm/bootstrap_natives.h"
|
|
#include "vm/exceptions.h"
|
|
#include "vm/globals.h"
|
|
#include "vm/native_entry.h"
|
|
|
|
#if !defined(HOST_OS_LINUX) && !defined(HOST_OS_MACOS) && \
|
|
!defined(HOST_OS_ANDROID)
|
|
// TODO(dacoharkes): Implement dynamic libraries for other targets & merge the
|
|
// implementation with:
|
|
// - runtime/bin/extensions.h
|
|
// - runtime/bin/extensions_linux.cc
|
|
// TODO(dacoharkes): Make the code from bin available in a manner similar to
|
|
// runtime/vm/dart.h Dart_FileReadCallback.
|
|
#else
|
|
#include <dlfcn.h>
|
|
#endif
|
|
|
|
namespace dart {
|
|
|
|
static void* LoadExtensionLibrary(const char* library_file) {
|
|
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
|
void* handle = dlopen(library_file, RTLD_LAZY);
|
|
if (handle == nullptr) {
|
|
char* error = dlerror();
|
|
const String& msg = String::Handle(
|
|
String::NewFormatted("Failed to load dynamic library (%s)", error));
|
|
Exceptions::ThrowArgumentError(msg);
|
|
}
|
|
|
|
return handle;
|
|
#elif defined(HOST_OS_WINDOWS)
|
|
SetLastError(0); // Clear any errors.
|
|
|
|
void* ext;
|
|
|
|
if (library_file == nullptr) {
|
|
ext = GetModuleHandle(nullptr);
|
|
} else {
|
|
// Convert to wchar_t string.
|
|
const int name_len =
|
|
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, NULL, 0);
|
|
wchar_t* name = new wchar_t[name_len];
|
|
MultiByteToWideChar(CP_UTF8, 0, library_file, -1, name, name_len);
|
|
|
|
ext = LoadLibraryW(name);
|
|
delete[] name;
|
|
}
|
|
|
|
if (ext == nullptr) {
|
|
const int error = GetLastError();
|
|
const String& msg = String::Handle(
|
|
String::NewFormatted("Failed to load dynamic library (%i)", error));
|
|
Exceptions::ThrowArgumentError(msg);
|
|
}
|
|
|
|
return ext;
|
|
#else
|
|
const Array& args = Array::Handle(Array::New(1));
|
|
args.SetAt(0,
|
|
String::Handle(String::New(
|
|
"The dart:ffi library is not available on this platform.")));
|
|
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
|
|
#endif
|
|
}
|
|
|
|
DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));
|
|
|
|
void* handle = LoadExtensionLibrary(lib_path.ToCString());
|
|
|
|
return DynamicLibrary::New(handle);
|
|
}
|
|
|
|
DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
|
|
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
|
return DynamicLibrary::New(RTLD_DEFAULT);
|
|
#else
|
|
const Array& args = Array::Handle(Array::New(1));
|
|
args.SetAt(0,
|
|
String::Handle(String::New(
|
|
"DynamicLibrary.process is not available on this platform.")));
|
|
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
|
|
#endif
|
|
}
|
|
|
|
DEFINE_NATIVE_ENTRY(Ffi_dl_executableLibrary, 0, 0) {
|
|
return DynamicLibrary::New(LoadExtensionLibrary(nullptr));
|
|
}
|
|
|
|
static void* ResolveSymbol(void* handle, const char* symbol) {
|
|
#if defined(HOST_OS_LINUX) || defined(HOST_OS_MACOS) || defined(HOST_OS_ANDROID)
|
|
dlerror(); // Clear any errors.
|
|
void* pointer = dlsym(handle, symbol);
|
|
if (pointer == nullptr) {
|
|
char* error = dlerror();
|
|
const String& msg = String::Handle(
|
|
String::NewFormatted("Failed to lookup symbol (%s)", error));
|
|
Exceptions::ThrowArgumentError(msg);
|
|
}
|
|
return pointer;
|
|
#elif defined(HOST_OS_WINDOWS)
|
|
SetLastError(0);
|
|
void* pointer = GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol);
|
|
if (pointer == nullptr) {
|
|
const int error = GetLastError();
|
|
const String& msg = String::Handle(
|
|
String::NewFormatted("Failed to lookup symbol (%i)", error));
|
|
Exceptions::ThrowArgumentError(msg);
|
|
}
|
|
return pointer;
|
|
#else
|
|
const Array& args = Array::Handle(Array::New(1));
|
|
args.SetAt(0,
|
|
String::Handle(String::New(
|
|
"The dart:ffi library is not available on this platform.")));
|
|
Exceptions::ThrowByType(Exceptions::kUnsupported, args);
|
|
#endif
|
|
}
|
|
|
|
DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
|
|
GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
|
|
|
|
GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
|
|
GET_NON_NULL_NATIVE_ARGUMENT(String, argSymbolName,
|
|
arguments->NativeArgAt(1));
|
|
|
|
void* handle = dlib.GetHandle();
|
|
|
|
const uword pointer =
|
|
reinterpret_cast<uword>(ResolveSymbol(handle, argSymbolName.ToCString()));
|
|
return Pointer::New(type_arg, pointer);
|
|
}
|
|
|
|
DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
|
|
GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
|
|
|
|
intptr_t handle = reinterpret_cast<intptr_t>(dlib.GetHandle());
|
|
return Integer::NewFromUint64(handle);
|
|
}
|
|
|
|
} // namespace dart
|