1
2 /*
3 Low-level routines for managing dynamic link libraries (DLLs).
4 */
5
6 #include <petsc/private/petscimpl.h>
7 #include <petscvalgrind.h>
8
9 /* XXX Should be done better !!!*/
10 #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
11 #undef PETSC_HAVE_WINDOWS_H
12 #undef PETSC_HAVE_DLFCN_H
13 #endif
14
15 #if defined(PETSC_HAVE_WINDOWS_H)
16 #include <windows.h>
17 #elif defined(PETSC_HAVE_DLFCN_H)
18 #include <dlfcn.h>
19 #endif
20
21 #if defined(PETSC_HAVE_WINDOWS_H)
22 typedef HMODULE dlhandle_t;
23 typedef FARPROC dlsymbol_t;
24 #elif defined(PETSC_HAVE_DLFCN_H)
25 typedef void* dlhandle_t;
26 typedef void* dlsymbol_t;
27 #else
28 typedef void* dlhandle_t;
29 typedef void* dlsymbol_t;
30 #endif
31
32 /*@C
33 PetscDLOpen - opens dynamic library
34
35 Not Collective
36
37 Input Parameters:
38 + name - name of library
39 - mode - options on how to open library
40
41 Output Parameter:
42 . handle
43
44 Level: developer
45
46 @*/
PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle * handle)47 PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
48 {
49 PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
50 dlhandle_t dlhandle;
51
52 PetscFunctionBegin;
53 PetscValidCharPointer(name,1);
54 PetscValidPointer(handle,3);
55
56 dlflags1 = 0;
57 dlflags2 = 0;
58 dlhandle = (dlhandle_t) 0;
59 *handle = (PetscDLHandle) 0;
60
61 /*
62 --- LoadLibrary ---
63 */
64 #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
65 dlhandle = LoadLibrary(name);
66 if (!dlhandle) {
67 #if defined(PETSC_HAVE_GETLASTERROR)
68 PetscErrorCode ierr;
69 DWORD erc;
70 char *buff = NULL;
71 erc = GetLastError();
72 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
73 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
74 ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
75 "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff);
76 LocalFree(buff);
77 PetscFunctionReturn(ierr);
78 #else
79 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable");
80 #endif
81 }
82
83 /*
84 --- dlopen ---
85 */
86 #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
87 /*
88 Mode indicates symbols required by symbol loaded with dlsym()
89 are only loaded when required (not all together) also indicates
90 symbols required can be contained in other libraries also opened
91 with dlopen()
92 */
93 #if defined(PETSC_HAVE_RTLD_LAZY)
94 dlflags1 = RTLD_LAZY;
95 #endif
96 #if defined(PETSC_HAVE_RTLD_NOW)
97 if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
98 #endif
99 #if defined(PETSC_HAVE_RTLD_GLOBAL)
100 dlflags2 = RTLD_GLOBAL;
101 #endif
102 #if defined(PETSC_HAVE_RTLD_LOCAL)
103 if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
104 #endif
105 #if defined(PETSC_HAVE_DLERROR)
106 dlerror(); /* clear any previous error */
107 #endif
108 dlhandle = dlopen(name,dlflags1|dlflags2);
109 if (!dlhandle) {
110 #if defined(PETSC_HAVE_DLERROR)
111 const char *errmsg = dlerror();
112 #else
113 const char *errmsg = "unavailable";
114 #endif
115 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
116 }
117
118 /*
119 --- unimplemented ---
120 */
121 #else
122 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
123 #endif
124
125 *handle = (PetscDLHandle) dlhandle;
126 PetscFunctionReturn(0);
127 }
128
129
130 /*@C
131 PetscDLClose - closes a dynamic library
132
133 Not Collective
134
135 Input Parameter:
136 . handle - the handle for the library obtained with PetscDLOpen()
137
138 Level: developer
139 @*/
PetscDLClose(PetscDLHandle * handle)140 PetscErrorCode PetscDLClose(PetscDLHandle *handle)
141 {
142
143 PetscFunctionBegin;
144 PetscValidPointer(handle,1);
145
146 /*
147 --- FreeLibrary ---
148 */
149 #if defined(PETSC_HAVE_WINDOWS_H)
150 #if defined(PETSC_HAVE_FREELIBRARY)
151 if (FreeLibrary((dlhandle_t)*handle) == 0) {
152 #if defined(PETSC_HAVE_GETLASTERROR)
153 char *buff = NULL;
154 DWORD erc = GetLastError();
155 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
156 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
157 LocalFree(buff);
158 #else
159 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
160 #endif
161 }
162 #endif /* !PETSC_HAVE_FREELIBRARY */
163
164 /*
165 --- dclose ---
166 */
167 #elif defined(PETSC_HAVE_DLFCN_H)
168 #if defined(PETSC_HAVE_DLCLOSE)
169 #if defined(PETSC_HAVE_DLERROR)
170 dlerror(); /* clear any previous error */
171 #endif
172 if (dlclose((dlhandle_t)*handle) < 0) {
173 #if defined(PETSC_HAVE_DLERROR)
174 const char *errmsg = dlerror();
175 #else
176 const char *errmsg = "unavailable";
177 #endif
178 PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
179 }
180 #endif /* !PETSC_HAVE_DLCLOSE */
181
182 /*
183 --- unimplemented ---
184 */
185 #else
186 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
187 #endif
188
189 *handle = NULL;
190 PetscFunctionReturn(0);
191 }
192
193 /*@C
194 PetscDLSym - finds a symbol in a dynamic library
195
196 Not Collective
197
198 Input Parameters:
199 + handle - obtained with PetscDLOpen() or NULL
200 - symbol - name of symbol
201
202 Output Parameter:
203 . value - pointer to the function, NULL if not found
204
205 Level: developer
206
207 Notes:
208 If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
209 In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
210 systems this requires platform-specific linker flags.
211
212 @*/
PetscDLSym(PetscDLHandle handle,const char symbol[],void ** value)213 PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
214 {
215 PETSC_UNUSED dlhandle_t dlhandle;
216 dlsymbol_t dlsymbol;
217
218 PetscValidCharPointer(symbol,2);
219 PetscValidPointer(value,3);
220
221 dlhandle = (dlhandle_t) 0;
222 dlsymbol = (dlsymbol_t) 0;
223 *value = (void*) 0;
224
225 /*
226 --- GetProcAddress ---
227 */
228 #if defined(PETSC_HAVE_WINDOWS_H)
229 #if defined(PETSC_HAVE_GETPROCADDRESS)
230 if (handle) dlhandle = (dlhandle_t) handle;
231 else dlhandle = (dlhandle_t) GetCurrentProcess();
232 dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
233 #if defined(PETSC_HAVE_SETLASTERROR)
234 SetLastError((DWORD)0); /* clear any previous error */
235 #endif
236 #endif /* !PETSC_HAVE_GETPROCADDRESS */
237
238 /*
239 --- dlsym ---
240 */
241 #elif defined(PETSC_HAVE_DLFCN_H)
242 #if defined(PETSC_HAVE_DLSYM)
243 if (handle) dlhandle = (dlhandle_t) handle;
244 else {
245
246 #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
247 /* Attempt to retrieve the main executable's dlhandle. */
248 { int dlflags1 = 0, dlflags2 = 0;
249 #if defined(PETSC_HAVE_RTLD_LAZY)
250 dlflags1 = RTLD_LAZY;
251 #endif
252 if (!dlflags1) {
253 #if defined(PETSC_HAVE_RTLD_NOW)
254 dlflags1 = RTLD_NOW;
255 #endif
256 }
257 #if defined(PETSC_HAVE_RTLD_LOCAL)
258 dlflags2 = RTLD_LOCAL;
259 #endif
260 if (!dlflags2) {
261 #if defined(PETSC_HAVE_RTLD_GLOBAL)
262 dlflags2 = RTLD_GLOBAL;
263 #endif
264 }
265 #if defined(PETSC_HAVE_DLERROR)
266 if (!(PETSC_RUNNING_ON_VALGRIND)) {
267 dlerror(); /* clear any previous error; valgrind does not like this */
268 }
269 #endif
270 /* Attempt to open the main executable as a dynamic library. */
271 #if defined(PETSC_HAVE_RTDL_DEFAULT)
272 dlhandle = RTLD_DEFAULT;
273 #else
274 dlhandle = dlopen(NULL, dlflags1|dlflags2);
275 #if defined(PETSC_HAVE_DLERROR)
276 { const char *e = (const char*) dlerror();
277 if (e) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error opening main executable as a dynamic library:\n Error message from dlopen(): '%s'\n", e);
278 }
279 #endif
280 #endif
281 }
282 #endif
283 #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
284 }
285 #if defined(PETSC_HAVE_DLERROR)
286 dlerror(); /* clear any previous error */
287 #endif
288 dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
289 /*
290 --- unimplemented ---
291 */
292 #else
293 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
294 #endif
295
296 *value = *((void**)&dlsymbol);
297
298 #if defined(PETSC_SERIALIZE_FUNCTIONS)
299 if (*value) {
300 PetscErrorCode ierr;
301 ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
302 }
303 #endif
304 return(0);
305 }
306