Files
sdk/runtime/bin/extensions.cc
T
Zachary Anderson b990bc3794 Fix native extension lookup
This CL allows native extension lookup to defer to the platform's
library lookup (e.g. dlopen) when the library cannot be found next to
the importing Dart library. It also allows dart-ext: to accept an
absolute path to the native library.

R=asiva@google.com

Review URL: https://codereview.chromium.org/2285223003 .
2016-08-30 09:31:47 -07:00

146 lines
4.5 KiB
C++

// Copyright (c) 2012, 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 "bin/extensions.h"
#include <stdio.h>
#include "bin/dartutils.h"
#include "bin/file.h"
#include "bin/platform.h"
#include "bin/utils.h"
#include "include/dart_api.h"
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
static char PathSeparator() {
const char* sep = File::PathSeparator();
ASSERT(strlen(sep) == 1);
return sep[0];
}
void* Extensions::MakePathAndResolve(const char* dir, const char* name) {
// First try to find the library with a suffix specifying the architecture.
{
const char* path_components[] = {
dir,
Platform::LibraryPrefix(),
name,
"-",
Platform::HostArchitecture(), // arm
".",
Platform::LibraryExtension(), // so
NULL,
};
const char* library_file = Concatenate(path_components);
void* library_handle = LoadExtensionLibrary(library_file);
if (library_handle != NULL) {
return library_handle;
}
}
// Fall back on a library name without the suffix.
{
const char* path_components[] = {
dir,
Platform::LibraryPrefix(),
name,
".",
Platform::LibraryExtension(), // so
NULL,
};
const char* library_file = Concatenate(path_components);
return LoadExtensionLibrary(library_file);
}
}
// IMPORTANT: In the absolute path case, do not extract the filename and search
// for that by passing it to LoadExtensionLibrary. That can lead to confusion in
// which the absolute path is wrong, and a different version of the library is
// loaded from the standard location.
void* Extensions::ResolveAbsPathExtension(const char* extension_path) {
const char* last_slash = strrchr(extension_path, PathSeparator()) + 1;
char* name = strdup(last_slash);
char* dir = StringUtils::StrNDup(extension_path, last_slash - extension_path);
void* library_handle = MakePathAndResolve(dir, name);
free(dir);
free(name);
return library_handle;
}
void* Extensions::ResolveExtension(const char* extension_directory,
const char* extension_name) {
// If the path following dart-ext is an absolute path, then only look for the
// library there.
if (File::IsAbsolutePath(extension_name)) {
return ResolveAbsPathExtension(extension_name);
}
// If the path following dart-ext is just a file name, first look next to
// the importing Dart library.
void* library_handle = MakePathAndResolve(extension_directory,
extension_name);
if (library_handle != NULL) {
return library_handle;
}
// Then pass the library name down to the platform. E.g. dlopen will do its
// own search in standard search locations.
return MakePathAndResolve("", extension_name);
}
Dart_Handle Extensions::LoadExtension(const char* extension_directory,
const char* extension_name,
Dart_Handle parent_library) {
void* library_handle = ResolveExtension(extension_directory, extension_name);
if (library_handle == NULL) {
return GetError();
}
const char* extension = extension_name;
if (File::IsAbsolutePath(extension_name)) {
extension = strrchr(extension_name, PathSeparator()) + 1;
}
const char* strings[] = { extension, "_Init", NULL };
const char* init_function_name = Concatenate(strings);
void* init_function = ResolveSymbol(library_handle, init_function_name);
Dart_Handle result = GetError();
if (Dart_IsError(result)) {
return result;
}
ASSERT(init_function != NULL);
typedef Dart_Handle (*InitFunctionType)(Dart_Handle import_map);
InitFunctionType fn = reinterpret_cast<InitFunctionType>(init_function);
return (*fn)(parent_library);
}
// Concatenates a NULL terminated array of strings.
// The returned string is scope allocated.
const char* Extensions::Concatenate(const char** strings) {
int size = 1; // null termination.
for (int i = 0; strings[i] != NULL; i++) {
size += strlen(strings[i]);
}
char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(size));
int index = 0;
for (int i = 0; strings[i] != NULL; i++) {
index += snprintf(result + index, size - index, "%s", strings[i]);
}
ASSERT(index == size - 1);
ASSERT(result[size - 1] == '\0');
return result;
}
} // namespace bin
} // namespace dart