// 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 "lib/ffi_dynamic_library.h"

#include "platform/globals.h"
#include "platform/utils.h"
#if defined(DART_HOST_OS_WINDOWS)
#include <Psapi.h>
#include <Windows.h>
#include <combaseapi.h>
#include <stdio.h>
#include <tchar.h>
#endif

#include "vm/bootstrap_natives.h"
#include "vm/dart_api_impl.h"
#include "vm/exceptions.h"
#include "vm/ffi/native_assets.h"
#include "vm/native_entry.h"
#include "vm/symbols.h"
#include "vm/zone_text_buffer.h"

#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) ||              \
    defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
#include <dlfcn.h>
#endif

namespace dart {

#if (defined(DART_INCLUDE_SIMULATOR) && !defined(SIMULATOR_FFI)) ||            \
    (defined(DART_PRECOMPILER) && !defined(TESTING))

DART_NORETURN static void SimulatorUnsupported() {
#if defined(DART_INCLUDE_SIMULATOR)
  Exceptions::ThrowUnsupportedError("Not supported on this simulator.");
#else
  Exceptions::ThrowUnsupportedError("Not supported in precompiler.");
#endif
}

DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_codeAsset, 0, 1) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_executableLibrary, 0, 0) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_close, 0, 1) {
  SimulatorUnsupported();
}
DEFINE_NATIVE_ENTRY(Ffi_dl_providesSymbol, 0, 2) {
  SimulatorUnsupported();
}

DEFINE_NATIVE_ENTRY(Ffi_GetFfiNativeResolver, 1, 0) {
  SimulatorUnsupported();
}

#else  // defined(DART_INCLUDE_SIMULATOR) ||                                   \
       // (defined(DART_PRECOMPILER) && !defined(TESTING))

// If an error occurs populates |error| (if provided) with an error message
// (caller must free this message when it is no longer needed).
static void* LoadDynamicLibrary(const char* library_file,
                                char** error = nullptr) {
  char* utils_error = nullptr;
  void* handle = Utils::LoadDynamicLibrary(
      library_file, /* search_dll_load_dir= */ false, &utils_error);
  if (utils_error != nullptr) {
    if (error != nullptr) {
      *error = OS::SCreate(
          /*use malloc*/ nullptr, "Failed to load dynamic library '%s': %s",
          library_file != nullptr ? library_file : "<process>", utils_error);
    }
    free(utils_error);
  }
  return handle;
}

#if defined(DART_HOST_OS_WINDOWS)
// On windows, nullptr signals trying a lookup in all loaded modules.
const nullptr_t kWindowsDynamicLibraryProcessPtr = nullptr;

void* co_task_mem_allocated = nullptr;

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
void* LookupSymbolInProcess(const char* symbol, char** error) {
  // Force loading ole32.dll.
  if (co_task_mem_allocated == nullptr) {
    co_task_mem_allocated = CoTaskMemAlloc(sizeof(intptr_t));
    CoTaskMemFree(co_task_mem_allocated);
  }

  HANDLE current_process =
      OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE,
                  GetCurrentProcessId());
  if (current_process == nullptr) {
    *error = OS::SCreate(nullptr, "Failed to open current process.");
    return nullptr;
  }

  HMODULE modules[1024];
  DWORD cb_needed;
  if (EnumProcessModules(current_process, modules, sizeof(modules),
                         &cb_needed) != 0) {
    for (intptr_t i = 0; i < (cb_needed / sizeof(HMODULE)); i++) {
      if (auto result =
              reinterpret_cast<void*>(GetProcAddress(modules[i], symbol))) {
        CloseHandle(current_process);
        return result;
      }
    }
  }
  CloseHandle(current_process);

  *error = OS::SCreate(
      nullptr,  // Use `malloc`.
      "None of the loaded modules contained the requested symbol '%s'.",
      symbol);
  return nullptr;
}
#endif

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
static void* ResolveSymbol(void* handle, const char* symbol, char** error) {
#if defined(DART_HOST_OS_WINDOWS)
  if (handle == kWindowsDynamicLibraryProcessPtr) {
    return LookupSymbolInProcess(symbol, error);
  }
#endif
  return Utils::ResolveSymbolInDynamicLibrary(handle, symbol, error);
}

static void* DlsymDynamicLibrary(void* handle,
                                 const char* symbol,
                                 char** error) {
  void* const result = ResolveSymbol(handle, symbol, error);
  if (*error != nullptr) {
    char* inner_error = *error;
    *error =
        OS::SCreate(/*use malloc*/ nullptr, "Failed to lookup symbol '%s': %s",
                    symbol, inner_error);
    free(inner_error);
  }
  return result;
}

static void* ResolveNativeAssetsSymbol(NativeAssetsApi* native_assets_api,
                                       void* handle,
                                       const char* symbol,
                                       char** error) {
  if (native_assets_api->dlsym == nullptr) {
    *error =
        OS::SCreate(/*use malloc*/ nullptr, "NativeAssetsApi::dlsym not set.");
    return nullptr;
  }
  NoActiveIsolateScope no_active_isolate_scope;
  return native_assets_api->dlsym(handle, symbol, error);
}

static void* ResolveDynamicLibrarySymbol(const DynamicLibrary& dlib,
                                         const char* symbol,
                                         char** error) {
  const auto dlsym = dlib.Dlsym();
  if (dlsym == nullptr) {
    *error =
        OS::SCreate(/*use malloc*/ nullptr, "NativeAssetsApi::dlsym not set.");
    return nullptr;
  }
  void* const handle = dlib.GetHandle();
  NoActiveIsolateScope no_active_isolate_scope;
  return dlsym(handle, symbol, error);
}

static bool DynamicLibrarySymbolExists(const DynamicLibrary& dlib,
                                       const char* symbol) {
  char* error = nullptr;
  ResolveDynamicLibrarySymbol(dlib, symbol, &error);
  if (error != nullptr) {
    free(error);
    return false;
  }
  return true;
}

DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, lib_path, arguments->NativeArgAt(0));

  char* error = nullptr;
  void* handle = LoadDynamicLibrary(lib_path.ToCString(), &error);
  if (error != nullptr) {
    const String& msg = String::Handle(String::New(error));
    free(error);
    Exceptions::ThrowArgumentError(msg);
  }
  return DynamicLibrary::New(handle, &DlsymDynamicLibrary,
                             &Utils::UnloadDynamicLibrary);
}

DEFINE_NATIVE_ENTRY(Ffi_dl_processLibrary, 0, 0) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_MACOS) ||              \
    defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_FUCHSIA)
  return DynamicLibrary::New(RTLD_DEFAULT, &DlsymDynamicLibrary,
                             &Utils::UnloadDynamicLibrary);
#else
  return DynamicLibrary::New(kWindowsDynamicLibraryProcessPtr,
                             &DlsymDynamicLibrary,
                             &Utils::UnloadDynamicLibrary);
#endif
}

DEFINE_NATIVE_ENTRY(Ffi_dl_executableLibrary, 0, 0) {
  return DynamicLibrary::New(LoadDynamicLibrary(nullptr), &DlsymDynamicLibrary,
                             &Utils::UnloadDynamicLibrary);
}

DEFINE_NATIVE_ENTRY(Ffi_dl_close, 0, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
  if (dlib.IsClosed()) {
    // Already closed, nothing to do
  } else {
    void* handle = dlib.GetHandle();
    char* error = nullptr;
    const auto dlclose = dlib.Dlclose();
    if (dlclose == nullptr) {
      error = OS::SCreate(/*use malloc*/ nullptr,
                          "NativeAssetsApi::dlclose not set.");
    } else {
      NoActiveIsolateScope no_active_isolate_scope;
      dlclose(handle, &error);
    }

    if (error == nullptr) {
      dlib.SetClosed(true);
    } else {
      const String& msg = String::Handle(String::New(error));
      free(error);
      Exceptions::ThrowStateError(msg);
    }
  }

  return Object::null();
}

DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(String, argSymbolName,
                               arguments->NativeArgAt(1));

  if (dlib.IsClosed()) {
    const String& msg =
        String::Handle(String::New("Cannot lookup symbols in closed library."));
    Exceptions::ThrowStateError(msg);
  }

  char* error = nullptr;
  void* const symbol =
      ResolveDynamicLibrarySymbol(dlib, argSymbolName.ToCString(), &error);
  const uword pointer = reinterpret_cast<uword>(symbol);
  if (error != nullptr) {
    const String& msg = String::Handle(String::New(error));
    free(error);
    Exceptions::ThrowArgumentError(msg);
  }
  return Pointer::New(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);
}

DEFINE_NATIVE_ENTRY(Ffi_dl_providesSymbol, 0, 2) {
  GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
  GET_NON_NULL_NATIVE_ARGUMENT(String, argSymbolName,
                               arguments->NativeArgAt(1));

  return Bool::Get(DynamicLibrarySymbolExists(dlib, argSymbolName.ToCString()))
      .ptr();
}

// nullptr if no native resolver is installed.
static Dart_FfiNativeResolver GetFfiNativeResolver(Thread* const thread,
                                                   const String& lib_url_str) {
  const Library& lib =
      Library::Handle(Library::LookupLibrary(thread, lib_url_str));
  if (lib.IsNull()) {
    // It is not an error to not have a native resolver installed.
    return nullptr;
  }
  return lib.ffi_native_resolver();
}

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
static void* FfiResolveWithFfiNativeResolver(Thread* const thread,
                                             Dart_FfiNativeResolver resolver,
                                             const String& symbol,
                                             intptr_t args_n,
                                             char** error) {
  auto* result = resolver(symbol.ToCString(), args_n);
  if (result == nullptr) {
    *error = OS::SCreate(/*use malloc*/ nullptr,
                         "Couldn't resolve function: '%s'", symbol.ToCString());
  }
  return result;
}

// Array::null if asset is not in mapping or no mapping.
static ArrayPtr GetAssetLocation(Thread* const thread, const String& asset) {
  Zone* const zone = thread->zone();
  auto& result = Array::Handle(zone);

  const auto& native_assets_map =
      Array::Handle(zone, GetNativeAssetsMap(thread));
  if (!native_assets_map.IsNull()) {
    NativeAssetsMap map(native_assets_map.ptr());
    const auto& lookup = Object::Handle(zone, map.GetOrNull(asset));
    if (!lookup.IsNull()) {
      result = Array::Cast(lookup).ptr();
    }
    map.Release();
  }
  return result.ptr();
}

// String is zone allocated.
static char* AvailableAssetsToCString(Thread* const thread) {
  Zone* const zone = thread->zone();

  const auto& native_assets_map =
      Array::Handle(zone, GetNativeAssetsMap(thread));
  ZoneTextBuffer buffer(zone, 1024);

  if (native_assets_map.IsNull()) {
    buffer.Printf("No available native assets.");
  } else {
    bool first = true;
    buffer.Printf("Available native assets: ");
    NativeAssetsMap map(native_assets_map.ptr());
    NativeAssetsMap::Iterator it(&map);
    auto& asset_id = String::Handle(zone);
    while (it.MoveNext()) {
      if (!first) {
        buffer.Printf(", ");
      }
      first = false;
      auto entry = it.Current();
      asset_id ^= map.GetKey(entry);
      buffer.Printf("%s", asset_id.ToCString());
    }
    buffer.Printf(".");
    map.Release();
  }
  return buffer.buffer();
}

struct AssetLibraryLoadResult {
  void* handle = nullptr;
  Dart_NativeAssetsDlsymCallback dlsym = nullptr;
  Dart_NativeAssetsDlcloseCallback dlclose = nullptr;
};

// If an error occurs populates |error| with an error message
// (caller must free this message when it is no longer needed).
static AssetLibraryLoadResult LoadAssetLibraryFromKernelMapping(
    Thread* const thread,
    const String& asset,
    char** error) {
  AssetLibraryLoadResult result;
  NativeAssetsApi* native_assets_api =
      thread->isolate_group()->native_assets_api();

  // Fall back on VM reading ffi:native-assets from special library in kernel.
  Zone* const zone = thread->zone();
  const auto& asset_location =
      Array::Handle(zone, GetAssetLocation(thread, asset));
  ASSERT(!asset_location.IsNull());
  result.dlsym = native_assets_api->dlsym;
  result.dlclose = native_assets_api->dlclose;

  const auto& asset_type =
      String::Cast(Object::Handle(zone, asset_location.At(0)));
  String& path = String::Handle(zone);
  const char* path_cstr = nullptr;
  if (asset_type.Equals(Symbols::absolute()) ||
      asset_type.Equals(Symbols::relative()) ||
      asset_type.Equals(Symbols::system())) {
    path = String::RawCast(asset_location.At(1));
    path_cstr = path.ToCString();
  }

  if (asset_type.Equals(Symbols::absolute())) {
    if (native_assets_api->dlopen_absolute == nullptr) {
      *error = OS::SCreate(/*use malloc*/ nullptr,
                           "NativeAssetsApi::dlopen_absolute not set.");
      return result;
    }
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_absolute(path_cstr, error);
  } else if (asset_type.Equals(Symbols::relative())) {
    if (native_assets_api->dlopen_relative == nullptr) {
      *error = OS::SCreate(/*use malloc*/ nullptr,
                           "NativeAssetsApi::dlopen_relative not set.");
      return result;
    }
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_relative(path_cstr, error);
  } else if (asset_type.Equals(Symbols::system())) {
    if (native_assets_api->dlopen_system == nullptr) {
      *error = OS::SCreate(/*use malloc*/ nullptr,
                           "NativeAssetsApi::dlopen_system not set.");
      return result;
    }
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_system(path_cstr, error);
  } else if (asset_type.Equals(Symbols::executable())) {
    if (native_assets_api->dlopen_executable == nullptr) {
      *error = OS::SCreate(/*use malloc*/ nullptr,
                           "NativeAssetsApi::dlopen_executable not set.");
      return result;
    }
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_executable(error);
  } else {
    RELEASE_ASSERT(asset_type.Equals(Symbols::process()));
    if (native_assets_api->dlopen_process == nullptr) {
      *error = OS::SCreate(/*use malloc*/ nullptr,
                           "NativeAssetsApi::dlopen_process not set.");
      return result;
    }
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_process(error);
  }
  return result;
}

// Returns whether |asset| is registered with either the embedder or the
// native-assets mapping in the kernel.
//
// If an error occurs populates |error| with an error message (caller must free
// this message when it is no longer needed).
static bool ContainsAsset(Thread* const thread,
                          const String& asset,
                          char** error) {
  NativeAssetsApi* native_assets_api =
      thread->isolate_group()->native_assets_api();
  const bool has_contains_asset = native_assets_api->contains_asset != nullptr;
  const bool has_dlopen_asset = native_assets_api->dlopen_asset != nullptr;
  if (has_contains_asset != has_dlopen_asset) {
    *error = OS::SCreate(
        /*use malloc*/ nullptr,
        "NativeAssetsApi::contains_asset and NativeAssetsApi::dlopen_asset "
        "must be provided together.");
    return false;
  }
  if (has_dlopen_asset) {
    NoActiveIsolateScope no_active_isolate_scope;
    return native_assets_api->contains_asset(asset.ToCString());
  }

  Zone* const zone = thread->zone();
  const auto& asset_location =
      Array::Handle(zone, GetAssetLocation(thread, asset));
  return !asset_location.IsNull();
}

// Loads |asset|, which must have been found by ContainsAsset.
//
// If an error occurs populates |error| with an error message (caller must free
// this message when it is no longer needed).
//
// A successful process or executable lookup can return a nullptr handle.
static AssetLibraryLoadResult LoadAssetLibrary(Thread* const thread,
                                               const String& asset,
                                               char** error) {
  AssetLibraryLoadResult result;
  NativeAssetsApi* native_assets_api =
      thread->isolate_group()->native_assets_api();
  if (native_assets_api->dlopen_asset != nullptr) {
    // Let embedder resolve the asset id to asset path.
    NoActiveIsolateScope no_active_isolate_scope;
    result.handle = native_assets_api->dlopen_asset(asset.ToCString(), error);
    result.dlsym = native_assets_api->dlsym;
    result.dlclose = native_assets_api->dlclose;
    return result;
  }
  return LoadAssetLibraryFromKernelMapping(thread, asset, error);
}

static void* FfiResolveAsset(Thread* const thread,
                             const String& asset,
                             const String& symbol,
                             char** error) {
  NativeAssetsApi* native_assets_api =
      thread->isolate_group()->native_assets_api();

  if (native_assets_api->dlopen_asset == nullptr &&
      native_assets_api->dlopen != nullptr) {
    // Legacy embedder resolution cannot distinguish a missing asset from a
    // successful process lookup. Keep it only for @Native compatibility.
    void* handle = nullptr;
    {
      NoActiveIsolateScope no_active_isolate_scope;
      handle = native_assets_api->dlopen(asset.ToCString(), error);
    }
    if (*error != nullptr) {
      return nullptr;
    }
    if (handle != nullptr) {
      return ResolveNativeAssetsSymbol(native_assets_api, handle,
                                       symbol.ToCString(), error);
    }
  }

  if (!ContainsAsset(thread, asset, error)) {
    return nullptr;
  }

  auto library = LoadAssetLibrary(thread, asset, error);
  if (*error != nullptr) {
    return nullptr;
  }
  return ResolveNativeAssetsSymbol(native_assets_api, library.handle,
                                   symbol.ToCString(), error);
}

DEFINE_NATIVE_ENTRY(Ffi_dl_codeAsset, 0, 1) {
  GET_NON_NULL_NATIVE_ARGUMENT(String, asset_id, arguments->NativeArgAt(0));
  NativeAssetsApi* native_assets_api =
      thread->isolate_group()->native_assets_api();
  char* error = nullptr;
  if (native_assets_api->dlopen_asset == nullptr &&
      native_assets_api->dlopen != nullptr) {
    const char* const message =
        "DynamicLibrary.codeAsset is not supported by this embedder. "
        "NativeAssetsApi::dlopen_asset and NativeAssetsApi::contains_asset "
        "must be provided.";
    Exceptions::ThrowUnsupportedError(message);
  }

  const bool asset_found = ContainsAsset(thread, asset_id, &error);
  if (error != nullptr) {
    const String& msg = String::Handle(String::New(error));
    free(error);
    Exceptions::ThrowArgumentError(msg);
  }
  if (!asset_found) {
    const char* const format = "No asset with id '%s' found. %s";
    String& msg = String::Handle();
    if (native_assets_api->available_assets != nullptr) {
      char* available_assets = native_assets_api->available_assets();
      msg =
          String::NewFormatted(format, asset_id.ToCString(), available_assets);
      free(available_assets);
    } else {
      msg = String::NewFormatted(format, asset_id.ToCString(),
                                 AvailableAssetsToCString(thread));
    }
    Exceptions::ThrowArgumentError(msg);
  }

  auto result = LoadAssetLibrary(thread, asset_id, &error);
  if (error != nullptr) {
    const String& msg = String::Handle(String::New(error));
    free(error);
    Exceptions::ThrowArgumentError(msg);
  }
  return DynamicLibrary::New(result.handle, result.dlsym, result.dlclose);
}

// Frees |error|.
static void ThrowFfiResolveError(const String& symbol,
                                 const String& asset,
                                 char* error) {
  const String& error_message = String::Handle(String::NewFormatted(
      "Couldn't resolve native function '%s' in '%s' : %s.\n",
      symbol.ToCString(), asset.ToCString(), error));
  free(error);
  Exceptions::ThrowArgumentError(error_message);
}

intptr_t FfiResolveInternal(const String& asset,
                            const String& symbol,
                            uintptr_t args_n,
                            char** error) {
  Thread* thread = Thread::Current();
  // Resolver resolution.
  auto resolver = GetFfiNativeResolver(thread, asset);
  if (resolver != nullptr) {
    void* ffi_native_result = FfiResolveWithFfiNativeResolver(
        thread, resolver, symbol, args_n, error);
    return reinterpret_cast<intptr_t>(ffi_native_result);
  }

  // Native assets resolution.
  void* asset_result = FfiResolveAsset(thread, asset, symbol, error);
  if (asset_result != nullptr || *error != nullptr) {
    return reinterpret_cast<intptr_t>(asset_result);
  }

  // Resolution in current process.
#if !defined(DART_HOST_OS_WINDOWS)
  void* const result = Utils::ResolveSymbolInDynamicLibrary(
      RTLD_DEFAULT, symbol.ToCString(), error);
#else
  void* const result = LookupSymbolInProcess(symbol.ToCString(), error);
#endif

  if (*error != nullptr) {
    // Process lookup failed, but the user might have tried to use native
    // asset lookup. So augment the error message to include native assets info.
    char* process_lookup_error = *error;
    NativeAssetsApi* native_assets_api =
        thread->isolate_group()->native_assets_api();
    const char* const format =
        "No asset with id '%s' found. %s "
        "Attempted to fallback to process lookup. %s";
    if (native_assets_api->available_assets != nullptr) {
      // Embedder is resolving asset ids to asset paths.
      char* available_assets = native_assets_api->available_assets();
      *error = OS::SCreate(/*use malloc*/ nullptr, format, asset.ToCString(),
                           available_assets, process_lookup_error);
      free(available_assets);
    } else {
      // VM is resolving asset ids to asset paths.
      *error =
          OS::SCreate(/*use malloc*/ nullptr, format, asset.ToCString(),
                      AvailableAssetsToCString(thread), process_lookup_error);
    }
    free(process_lookup_error);
  }

  return reinterpret_cast<intptr_t>(result);
}

// FFI native C function pointer resolver.
static intptr_t FfiResolve(Dart_Handle asset_handle,
                           Dart_Handle symbol_handle,
                           uintptr_t args_n) {
  auto* const thread = Thread::Current();
  DARTSCOPE(thread);
  auto* const zone = thread->zone();
  const String& asset = Api::UnwrapStringHandle(zone, asset_handle);
  const String& symbol = Api::UnwrapStringHandle(zone, symbol_handle);
  char* error = nullptr;

  const intptr_t result = FfiResolveInternal(asset, symbol, args_n, &error);
  if (error != nullptr) {
    ThrowFfiResolveError(symbol, asset, error);
  }
  ASSERT(result != 0x0);
  return result;
}

// Bootstrap to get the FFI Native resolver through a `native` call.
DEFINE_NATIVE_ENTRY(Ffi_GetFfiNativeResolver, 1, 0) {
  return Pointer::New(reinterpret_cast<intptr_t>(FfiResolve));
}

#endif  // (defined(DART_INCLUDE_SIMULATOR) && !defined (SIMULATOR_FFI)) ||    \
        // (defined(DART_PRECOMPILER) && !defined(TESTING))

}  // namespace dart
