1*330d8983SJohannes Doerfert //===--- generic-elf-64bit/dynamic_ffi/ffi.cpp -------------------- C++ -*-===//
2*330d8983SJohannes Doerfert //
3*330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information.
5*330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*330d8983SJohannes Doerfert //
7*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===//
8*330d8983SJohannes Doerfert //
9*330d8983SJohannes Doerfert // Implement subset of the FFI api by calling into the FFI library via dlopen
10*330d8983SJohannes Doerfert //
11*330d8983SJohannes Doerfert //===----------------------------------------------------------------------===//
12*330d8983SJohannes Doerfert
13*330d8983SJohannes Doerfert #include "llvm/Support/DynamicLibrary.h"
14*330d8983SJohannes Doerfert
15*330d8983SJohannes Doerfert #include "Shared/Debug.h"
16*330d8983SJohannes Doerfert #include <memory>
17*330d8983SJohannes Doerfert
18*330d8983SJohannes Doerfert #include "DLWrap.h"
19*330d8983SJohannes Doerfert #include "ffi.h"
20*330d8983SJohannes Doerfert
21*330d8983SJohannes Doerfert DLWRAP_INITIALIZE()
22*330d8983SJohannes Doerfert
23*330d8983SJohannes Doerfert DLWRAP(ffi_call, 4);
24*330d8983SJohannes Doerfert DLWRAP(ffi_prep_cif, 5);
25*330d8983SJohannes Doerfert
26*330d8983SJohannes Doerfert DLWRAP_FINALIZE()
27*330d8983SJohannes Doerfert
28*330d8983SJohannes Doerfert ffi_type ffi_type_void;
29*330d8983SJohannes Doerfert ffi_type ffi_type_pointer;
30*330d8983SJohannes Doerfert
31*330d8983SJohannes Doerfert // Name of the FFI shared library.
32*330d8983SJohannes Doerfert constexpr const char *FFI_PATH = "libffi.so";
33*330d8983SJohannes Doerfert
34*330d8983SJohannes Doerfert #define DYNAMIC_FFI_SUCCESS 0
35*330d8983SJohannes Doerfert #define DYNAMIC_FFI_FAIL 1
36*330d8983SJohannes Doerfert
37*330d8983SJohannes Doerfert // Initializes the dynamic FFI wrapper.
ffi_init()38*330d8983SJohannes Doerfert uint32_t ffi_init() {
39*330d8983SJohannes Doerfert std::string ErrMsg;
40*330d8983SJohannes Doerfert auto DynlibHandle = std::make_unique<llvm::sys::DynamicLibrary>(
41*330d8983SJohannes Doerfert llvm::sys::DynamicLibrary::getPermanentLibrary(FFI_PATH, &ErrMsg));
42*330d8983SJohannes Doerfert
43*330d8983SJohannes Doerfert if (!DynlibHandle->isValid()) {
44*330d8983SJohannes Doerfert DP("Unable to load library '%s': %s!\n", FFI_PATH, ErrMsg.c_str());
45*330d8983SJohannes Doerfert return DYNAMIC_FFI_FAIL;
46*330d8983SJohannes Doerfert }
47*330d8983SJohannes Doerfert
48*330d8983SJohannes Doerfert for (size_t I = 0; I < dlwrap::size(); I++) {
49*330d8983SJohannes Doerfert const char *Sym = dlwrap::symbol(I);
50*330d8983SJohannes Doerfert
51*330d8983SJohannes Doerfert void *P = DynlibHandle->getAddressOfSymbol(Sym);
52*330d8983SJohannes Doerfert if (P == nullptr) {
53*330d8983SJohannes Doerfert DP("Unable to find '%s' in '%s'!\n", Sym, FFI_PATH);
54*330d8983SJohannes Doerfert return DYNAMIC_FFI_FAIL;
55*330d8983SJohannes Doerfert }
56*330d8983SJohannes Doerfert DP("Implementing %s with dlsym(%s) -> %p\n", Sym, Sym, P);
57*330d8983SJohannes Doerfert
58*330d8983SJohannes Doerfert *dlwrap::pointer(I) = P;
59*330d8983SJohannes Doerfert }
60*330d8983SJohannes Doerfert
61*330d8983SJohannes Doerfert #define DYNAMIC_INIT(SYMBOL) \
62*330d8983SJohannes Doerfert { \
63*330d8983SJohannes Doerfert void *SymbolPtr = DynlibHandle->getAddressOfSymbol(#SYMBOL); \
64*330d8983SJohannes Doerfert if (!SymbolPtr) { \
65*330d8983SJohannes Doerfert DP("Unable to find '%s' in '%s'!\n", #SYMBOL, FFI_PATH); \
66*330d8983SJohannes Doerfert return DYNAMIC_FFI_FAIL; \
67*330d8983SJohannes Doerfert } \
68*330d8983SJohannes Doerfert SYMBOL = *reinterpret_cast<decltype(SYMBOL) *>(SymbolPtr); \
69*330d8983SJohannes Doerfert }
70*330d8983SJohannes Doerfert DYNAMIC_INIT(ffi_type_void);
71*330d8983SJohannes Doerfert DYNAMIC_INIT(ffi_type_pointer);
72*330d8983SJohannes Doerfert #undef DYNAMIC_INIT
73*330d8983SJohannes Doerfert
74*330d8983SJohannes Doerfert return DYNAMIC_FFI_SUCCESS;
75*330d8983SJohannes Doerfert }
76