Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Common Portability Library
4 : * Purpose: Fetch a function pointer from a shared library / DLL.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam
9 : * Copyright (c) 2009-2013, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_port.h"
31 : #include "cpl_conv.h"
32 :
33 : #include <cstddef>
34 :
35 : #include "cpl_config.h"
36 : #include "cpl_error.h"
37 : #include "cpl_string.h"
38 :
39 : /* ==================================================================== */
40 : /* Unix Implementation */
41 : /* ==================================================================== */
42 :
43 : /* MinGW32 might define HAVE_DLFCN_H, so skip the unix implementation */
44 : #if defined(HAVE_DLFCN_H) && !defined(_WIN32)
45 :
46 : #define GOT_GETSYMBOL
47 :
48 : #include <dlfcn.h>
49 :
50 : /************************************************************************/
51 : /* CPLGetSymbol() */
52 : /************************************************************************/
53 :
54 : /**
55 : * Fetch a function pointer from a shared library / DLL.
56 : *
57 : * This function is meant to abstract access to shared libraries and
58 : * DLLs and performs functions similar to dlopen()/dlsym() on Unix and
59 : * LoadLibrary() / GetProcAddress() on Windows.
60 : *
61 : * If no support for loading entry points from a shared library is available
62 : * this function will always return NULL. Rules on when this function
63 : * issues a CPLError() or not are not currently well defined, and will have
64 : * to be resolved in the future.
65 : *
66 : * Currently CPLGetSymbol() doesn't try to:
67 : * <ul>
68 : * <li> prevent the reference count on the library from going up
69 : * for every request, or given any opportunity to unload
70 : * the library.
71 : * <li> Attempt to look for the library in non-standard
72 : * locations.
73 : * <li> Attempt to try variations on the symbol name, like
74 : * pre-pending or post-pending an underscore.
75 : * </ul>
76 : *
77 : * Some of these issues may be worked on in the future.
78 : *
79 : * @param pszLibrary the name of the shared library or DLL containing
80 : * the function. May contain path to file. If not system supplies search
81 : * paths will be used.
82 : * @param pszSymbolName the name of the function to fetch a pointer to.
83 : * @return A pointer to the function if found, or NULL if the function isn't
84 : * found, or the shared library can't be loaded.
85 : */
86 :
87 378 : void *CPLGetSymbol(const char *pszLibrary, const char *pszSymbolName)
88 :
89 : {
90 378 : void *pLibrary = dlopen(pszLibrary, RTLD_LAZY);
91 378 : if (pLibrary == nullptr)
92 : {
93 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", dlerror());
94 0 : return nullptr;
95 : }
96 :
97 378 : void *pSymbol = dlsym(pLibrary, pszSymbolName);
98 :
99 : #if (defined(__APPLE__) && defined(__MACH__))
100 : /* On mach-o systems, C symbols have a leading underscore and depending
101 : * on how dlcompat is configured it may or may not add the leading
102 : * underscore. If dlsym() fails, add an underscore and try again.
103 : */
104 : if (pSymbol == nullptr)
105 : {
106 : char withUnder[256] = {};
107 : snprintf(withUnder, sizeof(withUnder), "_%s", pszSymbolName);
108 : pSymbol = dlsym(pLibrary, withUnder);
109 : }
110 : #endif
111 :
112 378 : if (pSymbol == nullptr)
113 : {
114 0 : CPLError(CE_Failure, CPLE_AppDefined, "%s", dlerror());
115 : // Do not call dlclose here. misc.py:misc_6() demonstrates the crash.
116 : // coverity[leaked_storage]
117 0 : return nullptr;
118 : }
119 :
120 : // coverity[leaked_storage] It is not safe to call dlclose.
121 378 : return (pSymbol);
122 : }
123 :
124 : #endif /* def __unix__ && defined(HAVE_DLFCN_H) */
125 :
126 : /* ==================================================================== */
127 : /* Windows Implementation */
128 : /* ==================================================================== */
129 : #if defined(_WIN32)
130 :
131 : #define GOT_GETSYMBOL
132 :
133 : #include <windows.h>
134 :
135 : /************************************************************************/
136 : /* CPLGetSymbol() */
137 : /************************************************************************/
138 :
139 : void *CPLGetSymbol(const char *pszLibrary, const char *pszSymbolName)
140 :
141 : {
142 : void *pLibrary = nullptr;
143 : void *pSymbol = nullptr;
144 :
145 : // Avoid error boxes to pop up (#5211, #5525).
146 : UINT uOldErrorMode =
147 : SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
148 :
149 : #if defined(_MSC_VER) || __MSVCRT_VERSION__ >= 0x0601
150 : if (CPLTestBool(CPLGetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")))
151 : {
152 : wchar_t *pwszFilename =
153 : CPLRecodeToWChar(pszLibrary, CPL_ENC_UTF8, CPL_ENC_UCS2);
154 : pLibrary = LoadLibraryW(pwszFilename);
155 : CPLFree(pwszFilename);
156 : }
157 : else
158 : #endif
159 : {
160 : pLibrary = LoadLibraryA(pszLibrary);
161 : }
162 :
163 : if (pLibrary <= (void *)HINSTANCE_ERROR)
164 : {
165 : LPVOID lpMsgBuf = nullptr;
166 : int nLastError = GetLastError();
167 :
168 : // Restore old error mode.
169 : SetErrorMode(uOldErrorMode);
170 :
171 : FormatMessage(
172 : FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
173 : FORMAT_MESSAGE_IGNORE_INSERTS,
174 : nullptr, nLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
175 : reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
176 :
177 : CPLError(CE_Failure, CPLE_AppDefined,
178 : "Can't load requested DLL: %s\n%d: %s", pszLibrary, nLastError,
179 : static_cast<const char *>(lpMsgBuf));
180 : return nullptr;
181 : }
182 :
183 : // Restore old error mode.
184 : SetErrorMode(uOldErrorMode);
185 :
186 : pSymbol = reinterpret_cast<void *>(
187 : GetProcAddress(static_cast<HINSTANCE>(pLibrary), pszSymbolName));
188 :
189 : if (pSymbol == nullptr)
190 : {
191 : CPLError(CE_Failure, CPLE_AppDefined,
192 : "Can't find requested entry point: %s", pszSymbolName);
193 : return nullptr;
194 : }
195 :
196 : return (pSymbol);
197 : }
198 :
199 : #endif // def _WIN32
200 :
201 : /* ==================================================================== */
202 : /* Dummy implementation. */
203 : /* ==================================================================== */
204 :
205 : #ifndef GOT_GETSYMBOL
206 :
207 : /************************************************************************/
208 : /* CPLGetSymbol() */
209 : /* */
210 : /* Dummy implementation. */
211 : /************************************************************************/
212 :
213 : void *CPLGetSymbol(const char *pszLibrary, const char *pszEntryPoint)
214 :
215 : {
216 : CPLDebug("CPL",
217 : "CPLGetSymbol(%s,%s) called. Failed as this is stub"
218 : " implementation.",
219 : pszLibrary, pszEntryPoint);
220 : return nullptr;
221 : }
222 : #endif
|