jaulib v1.3.0
Jau Support Library (C++, Java, ..)
unix_dyn_linker.cpp
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24#if !defined(_WIN32)
25
26 #if defined(__linux__)
27 #ifndef _GNU_SOURCE
28 #define _GNU_SOURCE
29 #endif
30 #else
31 // NOP
32 #endif
33
34 #include <dlfcn.h>
35 #include <cinttypes>
36
37 #include <cassert>
38
39 #include "jau/os/dyn_linker.hpp"
40
41 #ifndef RTLD_DEFAULT
42 #define LIB_DEFAULT ((void *) 0)
43 #endif
44
45 namespace jau::os::impl {
46
47 using namespace jau::os;
48
50 private:
51 void* const m_lib_default;
52 void* const m_lib_next;
53
54 int const m_flag_lazy;
55 int const m_flag_now;
56 int const m_flag_local;
57 int const m_flag_global;
58
59 protected:
60 UnixDynamicLinker(void* const lib_default, void* const lib_next,
61 int const flag_lazy, int const flag_now, int const flag_local, int const flag_global)
62 : m_lib_default(lib_default), m_lib_next(lib_next),
63 m_flag_lazy(flag_lazy), m_flag_now(flag_now), m_flag_local(flag_local), m_flag_global(flag_global)
64 {
65 (void)m_lib_next;
66 (void)m_flag_now;
67 }
68
69 libhandle_t openLibraryGlobalImpl(const std::string& pathname) noexcept override {
70 return ::dlopen((char *) pathname.c_str(), m_flag_lazy | m_flag_global);
71
72 }
73 libhandle_t openLibraryLocalImpl(const std::string& pathname) noexcept override {
74 return ::dlopen((char *) pathname.c_str(), m_flag_lazy | m_flag_local);
75 }
76
77 const char* lookupLibraryPathnameImpl(libhandle_t handle, const std::string& symbolName) noexcept override {
78 if( nullptr != handle && symbolName.length() > 0 ) {
79 symhandle_t addr = ::dlsym(handle, symbolName.c_str());
80 if( nullptr != addr ) {
81 Dl_info info;
82 if( 0 != ::dladdr(addr, &info) ) {
83 return info.dli_fname;
84 } else {
85 return nullptr;
86 }
87 }
88 }
89 return nullptr;
90 }
91
92 symhandle_t lookupSymbolGlobalImpl(const std::string& symbolName) noexcept override {
93 return ::dlsym(m_lib_default, symbolName.c_str());
94 }
95
96 symhandle_t lookupSymbolLocalImpl(libhandle_t handle, const std::string& symbolName) noexcept override {
97 if( nullptr != handle ) {
98 return ::dlsym(handle, symbolName.c_str());
99 } else {
100 return nullptr;
101 }
102 }
103
104 void closeLibraryImpl(libhandle_t handle) noexcept override {
105 if( nullptr != handle ) {
106 ::dlclose(handle);
107 }
108 }
109
110 std::string getLastErrorImpl() noexcept override {
111 const char * res = ::dlerror();
112 if( nullptr != res ) {
113 return std::string(res);
114 } else {
115 return std::string();
116 }
117 }
118 };
119
120 /**
121 * POSIX specialization of UnixDynamicLinkerImpl with POSIX flags and mode values.
122 */
124 private:
125 constexpr static void* const LIB_DEFAULT = nullptr;
126 inline static void* const LIB_NEXT = reinterpret_cast<void *>( -1l ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
127
128 constexpr static int const FLAG_LAZY = 0x00001;
129 constexpr static int const FLAG_NOW = 0x00002;
130 constexpr static int const FLAG_LOCAL = 0x00000;
131 constexpr static int const FLAG_GLOBAL = 0x00100;
132
133 public:
135 : UnixDynamicLinker(LIB_DEFAULT, LIB_NEXT, FLAG_LAZY, FLAG_NOW, FLAG_LOCAL, FLAG_GLOBAL) {}
136 };
137
138 /**
139 * Darwin (MacOSX/iOS) specialization of UnixDynamicLinkerImpl with non-POSIX flags and mode values.
140 */
142 private:
143 inline static void* const LIB_DEFAULT = reinterpret_cast<void *>( -2l ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
144 inline static void* const LIB_NEXT = reinterpret_cast<void *>( -1l ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
145
146 constexpr static int const FLAG_LAZY = 0x00001;
147 constexpr static int const FLAG_NOW = 0x00002;
148 constexpr static int const FLAG_LOCAL = 0x00004;
149 constexpr static int const FLAG_GLOBAL = 0x00008;
150
151 public:
153 : UnixDynamicLinker(LIB_DEFAULT, LIB_NEXT, FLAG_LAZY, FLAG_NOW, FLAG_LOCAL, FLAG_GLOBAL) {}
154 };
155
156 /**
157 * Bionic 32bit (Android) specialization of UnixDynamicLinkerImpl with non-POSIX flags and mode values.
158 *
159 * Note: Bionic 64bit seems to POSIX compliant
160 */
162 private:
163 inline static void* const LIB_DEFAULT = reinterpret_cast<void *>( 0xfffffffful ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
164 inline static void* const LIB_NEXT = reinterpret_cast<void *>( 0xfffffffeul ); // NOLINT(performance-no-int-to-ptr,-warnings-as-errors)
165
166 constexpr static int const FLAG_LAZY = 0x00001;
167 constexpr static int const FLAG_NOW = 0x00000;
168 constexpr static int const FLAG_LOCAL = 0x00000;
169 constexpr static int const FLAG_GLOBAL = 0x00002;
170 // constexpr static int const FLAG_NOLOAD = 0x00004;
171
172 public:
174 : UnixDynamicLinker(LIB_DEFAULT, LIB_NEXT, FLAG_LAZY, FLAG_NOW, FLAG_LOCAL, FLAG_GLOBAL) {}
175 };
176 } // namespace jau::os::impl
177
178 jau::os::DynamicLinker* jau::os::DynamicLinker::create() {
179 if constexpr ( jau::os::is_android() && 32 == jau::cpu::pointer_bit_size() ) {
181 } else if constexpr ( jau::os::is_darwin() ) {
183 } else {
185 }
186 }
187
188#endif // !_WIN32
Low level secure dynamic linker access.
Definition: dyn_linker.hpp:45
void * symhandle_t
symbol handle within a library
Definition: dyn_linker.hpp:50
void * libhandle_t
library handle
Definition: dyn_linker.hpp:48
Bionic 32bit (Android) specialization of UnixDynamicLinkerImpl with non-POSIX flags and mode values.
Darwin (MacOSX/iOS) specialization of UnixDynamicLinkerImpl with non-POSIX flags and mode values.
POSIX specialization of UnixDynamicLinkerImpl with POSIX flags and mode values.
symhandle_t lookupSymbolLocalImpl(libhandle_t handle, const std::string &symbolName) noexcept override
void closeLibraryImpl(libhandle_t handle) noexcept override
UnixDynamicLinker(void *const lib_default, void *const lib_next, int const flag_lazy, int const flag_now, int const flag_local, int const flag_global)
std::string getLastErrorImpl() noexcept override
libhandle_t openLibraryLocalImpl(const std::string &pathname) noexcept override
symhandle_t lookupSymbolGlobalImpl(const std::string &symbolName) noexcept override
const char * lookupLibraryPathnameImpl(libhandle_t handle, const std::string &symbolName) noexcept override
libhandle_t openLibraryGlobalImpl(const std::string &pathname) noexcept override
constexpr bool is_darwin() noexcept
Evaluates true if platform os_type::native contains os_type::Darwin.
Definition: os_support.hpp:212
constexpr bool is_android() noexcept
Evaluates true if platform os_type::native contains os_type::Android.
Definition: os_support.hpp:206
constexpr size_t pointer_bit_size() noexcept
Returns the compile time pointer architecture size in bits.
Definition: cpuid.hpp:45
Author: Sven Gothel sgothel@jausoft.com Copyright (c) 2024 Gothel Software e.K.
Definition: dyn_linker.hpp:37