Line data Source code
1 : /**
2 : Copyright (c) 2024 Stappler LLC <admin@stappler.dev>
3 :
4 : Permission is hereby granted, free of charge, to any person obtaining a copy
5 : of this software and associated documentation files (the "Software"), to deal
6 : in the Software without restriction, including without limitation the rights
7 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 : copies of the Software, and to permit persons to whom the Software is
9 : furnished to do so, subject to the following conditions:
10 :
11 : The above copyright notice and this permission notice shall be included in
12 : all copies or substantial portions of the Software.
13 :
14 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 : THE SOFTWARE.
21 : **/
22 :
23 : #include "SPDso.h"
24 : #include "SPMemory.h"
25 :
26 : #if LINUX || ANDROID
27 :
28 : #include <dlfcn.h>
29 :
30 : namespace STAPPLER_VERSIONIZED stappler::dso {
31 :
32 375 : static void * dso_open(StringView name, DsoFlags flags, const char **err) {
33 375 : void *h = nullptr;
34 375 : int f = 0;
35 375 : if ((flags & DsoFlags::Lazy) != DsoFlags::None) {
36 325 : f |= RTLD_LAZY;
37 : }
38 375 : if ((flags & DsoFlags::Global) != DsoFlags::None) {
39 0 : f |= RTLD_GLOBAL;
40 : }
41 375 : if ((flags & DsoFlags::Self) != DsoFlags::None) {
42 50 : h = ::dlopen(nullptr, RTLD_LAZY);
43 : } else {
44 325 : h = ::dlopen(name.terminated() ? name.data() : name.str<mem_std::Interface>().data(), f);
45 : }
46 375 : if (!h) {
47 50 : *err = ::dlerror();
48 : }
49 375 : return h;
50 : }
51 :
52 300 : static void dso_close(DsoFlags flags, void *handle) {
53 300 : if (handle) {
54 300 : ::dlclose(handle);
55 : }
56 300 : }
57 :
58 5700 : static void * dso_sym(void *h, StringView name, const char **err) {
59 5700 : auto s = ::dlsym(h, name.terminated() ? name.data() : name.str<mem_std::Interface>().data());
60 5700 : if (!s) {
61 0 : *err = ::dlerror();
62 : }
63 5700 : return s;
64 : }
65 :
66 : }
67 :
68 : #endif
69 :
70 : #if WIN32
71 :
72 : #include "SPPlatformUnistd.h"
73 : #include <libloaderapi.h>
74 :
75 : namespace STAPPLER_VERSIONIZED stappler::dso {
76 :
77 : static constexpr const char *WIN_FAIL_TO_LOAD = "Fail to load dynamic object";
78 : static constexpr const char *WIN_SYMBOL_NOT_FOUND = "Fail to find symbol in dynamic object";
79 :
80 : static void * dso_open(StringView name, DsoFlags flags, const char **err) {
81 : HMODULE h = NULL;
82 : if ((flags & DsoFlags::Self) != DsoFlags::None) {
83 : h = GetModuleHandleA(nullptr);
84 : } else {
85 : h = LoadLibraryA(LPCSTR(name.terminated() ? name.data() : name.str<mem_std::Interface>().data()));
86 : }
87 :
88 : if (!h) {
89 : *err = WIN_FAIL_TO_LOAD;
90 : }
91 : return (void *)h;
92 : }
93 :
94 : static void dso_close(DsoFlags flags, void *handle) {
95 : if (handle) {
96 : if ((flags & DsoFlags::Self) == DsoFlags::None) {
97 : FreeLibrary(HMODULE(handle));
98 : }
99 : }
100 : }
101 :
102 : static void * dso_sym(void *h, StringView name, const char **err) {
103 : auto s = GetProcAddress(HMODULE(h), name.terminated() ? name.data() : name.str<mem_std::Interface>().data());
104 : if (!s) {
105 : *err = WIN_SYMBOL_NOT_FOUND;
106 : }
107 : return (void *)s;
108 : }
109 :
110 : }
111 :
112 : #endif
113 :
114 : namespace STAPPLER_VERSIONIZED stappler {
115 :
116 : static constexpr const char *ERROR_MOVED_OUT = "Object was moved out";
117 : static constexpr const char *ERROR_NOT_LOADED = "Object was not loaded";
118 :
119 675 : Dso::~Dso() {
120 675 : if (_handle) {
121 300 : close();
122 : }
123 675 : }
124 :
125 225 : Dso::Dso() { }
126 :
127 325 : Dso::Dso(StringView name) : Dso(name, DsoFlags::Lazy) { }
128 :
129 375 : Dso::Dso(StringView name, DsoFlags flags) {
130 375 : _handle = dso::dso_open(name, flags, &_error);
131 375 : }
132 :
133 100 : Dso::Dso(Dso &&other) {
134 100 : _flags = other._flags;
135 100 : _handle = other._handle;
136 100 : _error = other._error;
137 :
138 100 : other._flags = DsoFlags::None;
139 100 : other._handle = nullptr;
140 100 : other._error = ERROR_MOVED_OUT;
141 100 : }
142 :
143 225 : Dso & Dso::operator=(Dso &&other) {
144 225 : if (_handle) {
145 0 : close();
146 : }
147 :
148 225 : _flags = other._flags;
149 225 : _handle = other._handle;
150 225 : _error = other._error;
151 :
152 225 : other._flags = DsoFlags::None;
153 225 : other._handle = nullptr;
154 225 : other._error = ERROR_MOVED_OUT;
155 225 : return *this;
156 : }
157 :
158 300 : void Dso::close() {
159 300 : if (_handle) {
160 300 : dso::dso_close(_flags, _handle);
161 300 : _handle = nullptr;
162 300 : _flags = DsoFlags::None;
163 : } else {
164 0 : _error = ERROR_NOT_LOADED;
165 : }
166 300 : }
167 :
168 5700 : void *Dso::loadSym(StringView name) {
169 5700 : if (_handle) {
170 5700 : if (auto s = dso::dso_sym(_handle, name, &_error)) {
171 5700 : _error = nullptr;
172 5700 : return s;
173 : }
174 : } else {
175 0 : _error = ERROR_NOT_LOADED;
176 : }
177 0 : return nullptr;
178 : }
179 :
180 : }
|