xref: /petsc/src/sys/dll/dlimpl.c (revision 009bbdc485cd9ad46be9940d3549e2dde9cdc322)
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   PetscFunctionReturn(0);
196 }
197 
198 #undef __FUNCT__
199 #define __FUNCT__ "PetscDLSym"
200 /*@C
201    PetscDLSym - finds a symbol in a dynamic library
202 
203    Not Collective
204 
205    Input Parameters:
206 +   handle - obtained with PetscDLOpen() or PETSC_NULL
207 -   symbol - name of symbol
208 
209    Output Parameter:
210 .   value - pointer to the function, PETSC_NULL if not found
211 
212    Level: developer
213 
214   Notes:
215    If handle is PETSC_NULL, the symbol is looked for in the main executable's dynamic symbol table.
216    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
217    systems this requires platform-specific linker flags.
218 
219 @*/
220 PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
221 {
222   PETSC_UNUSED dlhandle_t dlhandle;
223   dlsymbol_t              dlsymbol;
224 
225   PetscValidCharPointer(symbol,2);
226   PetscValidPointer(value,3);
227 
228   dlhandle = (dlhandle_t) 0;
229   dlsymbol = (dlsymbol_t) 0;
230   *value   = (void *) 0;
231 
232   /*
233      --- GetProcAddress ---
234   */
235 #if defined(PETSC_HAVE_WINDOWS_H)
236 #if defined(PETSC_HAVE_GETPROCADDRESS)
237   if (handle) dlhandle = (dlhandle_t) handle;
238   else dlhandle = (dlhandle_t) GetCurrentProcess();
239   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
240 #if defined(PETSC_HAVE_SETLASTERROR)
241   SetLastError((DWORD)0); /* clear any previous error */
242 #endif
243 #endif /* !PETSC_HAVE_GETPROCADDRESS */
244 
245   /*
246      --- dlsym ---
247   */
248 #elif defined(PETSC_HAVE_DLFCN_H)
249 #if defined(PETSC_HAVE_DLSYM)
250   if (handle) {
251     dlhandle = (dlhandle_t) handle;
252   } else {
253 
254 #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
255     /* Attempt to retrieve the main executable's dlhandle. */
256     { int dlflags1 = 0, dlflags2 = 0;
257 #if defined(PETSC_HAVE_RTLD_LAZY)
258       dlflags1 = RTLD_LAZY;
259 #endif
260       if (!dlflags1) {
261 #if defined(PETSC_HAVE_RTLD_NOW)
262         dlflags1 = RTLD_NOW;
263 #endif
264       }
265 #if defined(PETSC_HAVE_RTLD_LOCAL)
266       dlflags2 = RTLD_LOCAL;
267 #endif
268       if (!dlflags2) {
269 #if defined(PETSC_HAVE_RTLD_GLOBAL)
270         dlflags2 = RTLD_GLOBAL;
271 #endif
272       }
273 #if defined(PETSC_HAVE_DLERROR)
274       if (!(PETSC_RUNNING_ON_VALGRIND)) {
275         dlerror(); /* clear any previous error; valgrind does not like this */
276       }
277 #endif
278       /* Attempt to open the main executable as a dynamic library. */
279 #if defined(PETSC_HAVE_RTDL_DEFAULT)
280       dlhandle = RTLD_DEFAULT;
281 #else
282       dlhandle = dlopen(0, dlflags1|dlflags2);
283 #if defined(PETSC_HAVE_DLERROR)
284       { const char *e = (const char*) dlerror();
285         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);
286       }
287 #endif
288 #endif
289     }
290 #endif
291 #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */
292   }
293 #if defined(PETSC_HAVE_DLERROR)
294   dlerror(); /* clear any previous error */
295 #endif
296   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
297   /*
298      --- unimplemented ---
299   */
300 #else
301   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
302 #endif
303 
304   *value = *((void**)&dlsymbol);
305 
306 #if defined(PETSC_SERIALIZE_FUNCTIONS)
307   if (*value) {
308     PetscErrorCode ierr;
309     ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
310   }
311 #endif
312   return(0);
313 }
314