[vm/ffi] DynamicLibrary.process() and DynamicLibrary.executable()

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>
This commit is contained in:
Samir Jindel 2019-08-19 14:24:01 +00:00 committed by commit-bot@chromium.org
parent 2891ec679b
commit e64738ffbc
5 changed files with 68 additions and 12 deletions

View file

@ -36,14 +36,20 @@ static void* LoadExtensionLibrary(const char* library_file) {
#elif defined(HOST_OS_WINDOWS)
SetLastError(0); // Clear any errors.
// 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);
void* ext;
void* ext = LoadLibraryW(name);
delete[] name;
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();
@ -70,6 +76,22 @@ DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
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.

View file

@ -8,6 +8,8 @@ import "dart:_internal" show patch;
import 'dart:typed_data' show TypedData;
DynamicLibrary _open(String name) native "Ffi_dl_open";
DynamicLibrary _processLibrary() native "Ffi_dl_processLibrary";
DynamicLibrary _executableLibrary() native "Ffi_dl_executableLibrary";
@patch
@pragma("vm:entry-point")
@ -17,6 +19,12 @@ class DynamicLibrary {
return _open(name);
}
@patch
factory DynamicLibrary.process() => _processLibrary();
@patch
factory DynamicLibrary.executable() => _executableLibrary();
@patch
Pointer<T> lookup<T extends NativeType>(String symbolName)
native "Ffi_dl_lookup";

View file

@ -389,6 +389,8 @@ namespace dart {
V(Ffi_dl_lookup, 2) \
V(Ffi_dl_getHandle, 1) \
V(Ffi_asExternalTypedData, 2) \
V(Ffi_dl_processLibrary, 0) \
V(Ffi_dl_executableLibrary, 0) \
V(TransferableTypedData_factory, 2) \
V(TransferableTypedData_materialize, 1)

View file

@ -6,11 +6,20 @@ part of dart.ffi;
/// Represents a dynamically loaded C library.
class DynamicLibrary {
/// Loads a dynamic library file. This is the equivalent of dlopen.
/// Creates a dynamic library holding all global symbols.
///
/// Any symbol in a library currently loaded with global visibility (including
/// the executable itself) may be resolved in this library.
///
/// This feature is not available on Windows, instead an exception is thrown.
external factory DynamicLibrary.process();
/// Creates a dynamic library representing the running executable.
external factory DynamicLibrary.executable();
/// Loads a dynamic library file with local visibility.
///
/// Throws an [ArgumentError] if loading the dynamic library fails.
///
/// Note that it loads the functions in the library lazily (RTLD_LAZY).
external factory DynamicLibrary.open(String name);
/// Looks up a symbol in the [DynamicLibrary] and returns its address in

View file

@ -8,12 +8,13 @@
library FfiTest;
import 'dart:io';
import 'dart:ffi';
import 'dylib_utils.dart';
import 'package:expect/expect.dart';
import 'dylib_utils.dart';
void main() {
testOpen();
testOpenError();
@ -42,6 +43,20 @@ void testLookup() {
DynamicLibrary l = dlopenPlatformSpecific("ffi_test_dynamic_library");
var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
Expect.approxEquals(12.0, timesFour(3));
if (Platform.isMacOS ||
Platform.isIOS ||
Platform.isAndroid ||
Platform.isLinux) {
// Lookup a symbol from 'libc' since it's loaded with global visibility.
DynamicLibrary p = DynamicLibrary.process();
Expect.isTrue(p.lookup<Void>("strcmp") != nullptr);
} else {
Expect.throws<UnsupportedError>(() => DynamicLibrary.process());
}
DynamicLibrary e = DynamicLibrary.executable();
Expect.isTrue(e.lookup("Dart_Invoke") != nullptr);
}
void testLookupError() {