| //===--- 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 <memory> |
| |
| #include "DLWrap.h" |
| #include "ffi.h" |
| |
| 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>( |
| llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg)); |
| if (!DynlibHandle->isValid()) |
| 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) |
| return DYNAMIC_FFI_FAIL; |
| |
| *dlwrap::pointer(I) = P; |
| } |
| |
| #define DYNAMIC_INIT(SYMBOL) \ |
| { \ |
| void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \ |
| if (!SymbolPtr) \ |
| return DYNAMIC_FFI_FAIL; \ |
| SYMBOL = *reinterpret_cast<decltype(SYMBOL) *>(SymbolPtr); \ |
| } |
| DYNAMIC_INIT(ffi_type_void); |
| DYNAMIC_INIT(ffi_type_pointer); |
| #undef DYNAMIC_INIT |
| |
| return DYNAMIC_FFI_SUCCESS; |
| } |