xref: /petsc/src/sys/dll/dlimpl.c (revision 1147fc2a6bf7922defbbca15fc6c33f234803ff0)
1 
2 /*
3    Low-level routines for managing dynamic link libraries (DLLs).
4 */
5 
6 #include <petscsys.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 -    mode - options on how to open library
41 
42    Output Parameter:
43 .    handle
44 
45    Level: developer
46 
47 @*/
48 PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
49 {
50   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
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                   PETSC_NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,PETSC_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 (mode & 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 (mode & 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   PetscFunctionReturn(0);
130 }
131 
132 
133 #undef __FUNCT__
134 #define __FUNCT__ "PetscDLClose"
135 /*@C
136    PetscDLClose -  closes a dynamic library
137 
138    Not Collective
139 
140   Input Parameter:
141 .   handle - the handle for the library obtained with PetscDLOpen()
142 
143   Level: developer
144 @*/
145 PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
146 {
147 
148   PetscFunctionBegin;
149   PetscValidPointer(handle,1);
150 
151   /*
152      --- FreeLibrary ---
153   */
154 #if defined(PETSC_HAVE_WINDOWS_H)
155 #if defined(PETSC_HAVE_FREELIBRARY)
156   if (FreeLibrary((dlhandle_t)*handle) == 0) {
157 #if defined(PETSC_HAVE_GETLASTERROR)
158     char  *buff = NULL;
159     DWORD erc   = GetLastError();
160     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,PETSC_NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,PETSC_NULL);
161     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n",buff);
162     LocalFree(buff);
163 #else
164     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n","unavailable");
165 #endif
166   }
167 #endif /* !PETSC_HAVE_FREELIBRARY */
168 
169   /*
170      --- dclose ---
171   */
172 #elif defined(PETSC_HAVE_DLFCN_H)
173 #if defined(PETSC_HAVE_DLCLOSE)
174 #if defined(PETSC_HAVE_DLERROR)
175   dlerror(); /* clear any previous error */
176 #endif
177   if (dlclose((dlhandle_t)*handle) < 0) {
178 #if defined(PETSC_HAVE_DLERROR)
179     const char *errmsg = dlerror();
180 #else
181     const char *errmsg = "unavailable";
182 #endif
183     PetscErrorPrintf("Error closing dynamic library:\n  Error message from dlclose() %s\n", errmsg);
184   }
185 #endif /* !PETSC_HAVE_DLCLOSE */
186 
187   /*
188      --- unimplemented ---
189   */
190 #else
191   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
192 #endif
193 
194   *handle = PETSC_NULL;
195 
196   PetscFunctionReturn(0);
197 }
198 
199 #undef __FUNCT__
200 #define __FUNCT__ "PetscDLSym"
201 /*@C
202    PetscDLSym - finds a symbol in a dynamic library
203 
204    Not Collective
205 
206    Input Parameters:
207 +   handle - obtained with PetscDLOpen() or PETSC_NULL
208 -   symbol - name of symbol
209 
210    Output Parameter:
211 .   value - pointer to the function, PETSC_NULL if not found
212 
213    Level: developer
214 
215   Notes:
216    If handle is PETSC_NULL, the symbol is looked for in the main executable's dynamic symbol table.
217    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
218    systems this requires platform-specific linker flags.
219 
220 @*/
221 PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
222 {
223   PETSC_UNUSED dlhandle_t dlhandle;
224   dlsymbol_t              dlsymbol;
225 
226   PetscValidCharPointer(symbol,2);
227   PetscValidPointer(value,3);
228 
229   dlhandle = (dlhandle_t) 0;
230   dlsymbol = (dlsymbol_t) 0;
231   *value   = (void *) 0;
232 
233   /*
234      --- GetProcAddress ---
235   */
236 #if defined(PETSC_HAVE_WINDOWS_H)
237 #if defined(PETSC_HAVE_GETPROCADDRESS)
238   if (handle) dlhandle = (dlhandle_t) handle;
239   else dlhandle = (dlhandle_t) GetCurrentProcess();
240   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
241 #if defined(PETSC_HAVE_SETLASTERROR)
242   SetLastError((DWORD)0); /* clear any previous error */
243 #endif
244 #endif /* !PETSC_HAVE_GETPROCADDRESS */
245 
246   /*
247      --- dlsym ---
248   */
249 #elif defined(PETSC_HAVE_DLFCN_H)
250 #if defined(PETSC_HAVE_DLSYM)
251   if (handle) {
252     dlhandle = (dlhandle_t) handle;
253   } else {
254 
255 #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
256     /* Attempt to retrieve the main executable's dlhandle. */
257     { int dlflags1 = 0, dlflags2 = 0;
258 #if defined(PETSC_HAVE_RTLD_LAZY)
259       dlflags1 = RTLD_LAZY;
260 #endif
261       if (!dlflags1) {
262 #if defined(PETSC_HAVE_RTLD_NOW)
263         dlflags1 = RTLD_NOW;
264 #endif
265       }
266 #if defined(PETSC_HAVE_RTLD_LOCAL)
267       dlflags2 = RTLD_LOCAL;
268 #endif
269       if (!dlflags2) {
270 #if defined(PETSC_HAVE_RTLD_GLOBAL)
271         dlflags2 = RTLD_GLOBAL;
272 #endif
273       }
274 #if defined(PETSC_HAVE_DLERROR)
275       if (!(PETSC_RUNNING_ON_VALGRIND)) {
276         dlerror(); /* clear any previous error; valgrind does not like this */
277       }
278 #endif
279       /* Attempt to open the main executable as a dynamic library. */
280 #if defined(PETSC_HAVE_RTDL_DEFAULT)
281       dlhandle = RTLD_DEFAULT;
282 #else
283       dlhandle = dlopen(0, dlflags1|dlflags2);
284 #if defined(PETSC_HAVE_DLERROR)
285       { const char *e = (const char*) dlerror();
286         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);
287       }
288 #endif
289 #endif
290     }
291 #endif
292 #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */
293   }
294 #if defined(PETSC_HAVE_DLERROR)
295   dlerror(); /* clear any previous error */
296 #endif
297   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
298   /*
299      --- unimplemented ---
300   */
301 #else
302   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
303 #endif
304 
305   *value = *((void**)&dlsymbol);
306 
307 #if defined(PETSC_SERIALIZE_FUNCTIONS)
308   if (*value) {
309     PetscErrorCode ierr;
310     ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
311   }
312 #endif
313   return(0);
314 }
315