//===--- generic-elf-64bit/dynamic_ffi/ffi.cpp -------------------- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // Implement subset of the FFI api by calling into the FFI library via dlopen // //===----------------------------------------------------------------------===// #include "llvm/Support/DynamicLibrary.h" #include "Shared/Debug.h" #include #include "DLWrap.h" #include "ffi.h" using namespace llvm::offload::debug; DLWRAP_INITIALIZE() DLWRAP(ffi_call, 4); DLWRAP(ffi_prep_cif, 5); DLWRAP_FINALIZE() ffi_type ffi_type_void; ffi_type ffi_type_pointer; // Name of the FFI shared library. constexpr const char *FFI_PATH = "libffi.so"; #define DYNAMIC_FFI_SUCCESS 0 #define DYNAMIC_FFI_FAIL 1 // Initializes the dynamic FFI wrapper. uint32_t ffi_init() { std::string ErrMsg; auto DynlibHandle = std::make_unique( llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg)); if (!DynlibHandle->isValid()) { ODBG(OLDT_Init) << "Unable to load library '" << FFI_PATH << "': " << ErrMsg << "!"; return DYNAMIC_FFI_FAIL; } for (size_t I = 0; I < dlwrap::size(); I++) { const char *Sym = dlwrap::symbol(I); void *P = DynlibHandle->getAddressOfSymbol(Sym); if (P == nullptr) { ODBG(OLDT_Init) << "Unable to find '" << Sym << "' in '" << FFI_PATH << "'!"; return DYNAMIC_FFI_FAIL; } ODBG(OLDT_Init) << "Implementing " << Sym << " with dlsym(" << Sym << ") -> " << P; *dlwrap::pointer(I) = P; } #define DYNAMIC_INIT(SYMBOL) \ { \ void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ if (!SymbolPtr) { \ ODBG(OLDT_Init) << "Unable to find '" << #SYMBOL << "' in '" << FFI_PATH \ << "'!"; \ return DYNAMIC_FFI_FAIL; \ } \ SYMBOL = *reinterpret_cast(SymbolPtr); \ } DYNAMIC_INIT(ffi_type_void); DYNAMIC_INIT(ffi_type_pointer); #undef DYNAMIC_INIT return DYNAMIC_FFI_SUCCESS; }