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

source code of offload/plugins-nextgen/host/dynamic_ffi/ffi.cpp