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