Actual source code: dlimpl.c
1: /*
2: Low-level routines for managing dynamic link libraries (DLLs).
3: */
5: #include <petscconf.h>
6: #if defined(PETSC__GNU_SOURCE)
7: #if !defined(_GNU_SOURCE)
8: #define _GNU_SOURCE 1
9: #endif
10: #endif
12: #include <petsc/private/petscimpl.h>
14: #if defined(PETSC_HAVE_WINDOWS_H)
15: #include <windows.h>
16: #endif
17: #if defined(PETSC_HAVE_DLFCN_H)
18: #include <dlfcn.h>
19: #endif
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
32: /*@C
33: PetscDLOpen - opens dynamic library
35: Not Collective
37: Input Parameters:
38: + name - name of library
39: - mode - options on how to open library
41: Output Parameter:
42: . handle - opaque pointer to be used with PetscDLSym()
44: Level: developer
46: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
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;
57: dlflags1 = 0;
58: dlflags2 = 0;
59: dlhandle = (dlhandle_t) 0;
60: *handle = (PetscDLHandle) 0;
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)
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: PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,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: }
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) dlflags1 = RTLD_NOW;
99: #endif
100: #if defined(PETSC_HAVE_RTLD_GLOBAL)
101: dlflags2 = RTLD_GLOBAL;
102: #endif
103: #if defined(PETSC_HAVE_RTLD_LOCAL)
104: if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
105: #endif
106: #if defined(PETSC_HAVE_DLERROR)
107: dlerror(); /* clear any previous error */
108: #endif
109: dlhandle = dlopen(name,dlflags1|dlflags2);
110: if (!dlhandle) {
111: #if defined(PETSC_HAVE_DLERROR)
112: const char *errmsg = dlerror();
113: #else
114: const char *errmsg = "unavailable";
115: #endif
116: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
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
125: *handle = (PetscDLHandle) dlhandle;
126: return(0);
127: }
129: /*@C
130: PetscDLClose - closes a dynamic library
132: Not Collective
134: Input Parameter:
135: . handle - the handle for the library obtained with PetscDLOpen()
137: Level: developer
139: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
140: @*/
141: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
142: {
147: /*
148: --- FreeLibrary ---
149: */
150: #if defined(PETSC_HAVE_WINDOWS_H)
151: #if defined(PETSC_HAVE_FREELIBRARY)
152: if (FreeLibrary((dlhandle_t)*handle) == 0) {
153: #if defined(PETSC_HAVE_GETLASTERROR)
154: char *buff = NULL;
155: DWORD erc = GetLastError();
156: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
157: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
158: LocalFree(buff);
159: #else
160: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
161: #endif
162: }
163: #endif /* !PETSC_HAVE_FREELIBRARY */
165: /*
166: --- dclose ---
167: */
168: #elif defined(PETSC_HAVE_DLFCN_H)
169: #if defined(PETSC_HAVE_DLCLOSE)
170: #if defined(PETSC_HAVE_DLERROR)
171: dlerror(); /* clear any previous error */
172: #endif
173: if (dlclose((dlhandle_t)*handle) < 0) {
174: #if defined(PETSC_HAVE_DLERROR)
175: const char *errmsg = dlerror();
176: #else
177: const char *errmsg = "unavailable";
178: #endif
179: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
180: }
181: #endif /* !PETSC_HAVE_DLCLOSE */
183: /*
184: --- unimplemented ---
185: */
186: #else
187: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
188: #endif
190: *handle = NULL;
191: return(0);
192: }
194: /*@C
195: PetscDLSym - finds a symbol in a dynamic library
197: Not Collective
199: Input Parameters:
200: + handle - obtained with PetscDLOpen() or NULL
201: - symbol - name of symbol
203: Output Parameter:
204: . value - pointer to the function, NULL if not found
206: Level: developer
208: Notes:
209: If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
210: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
211: systems this requires platform-specific linker flags.
213: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
214: @*/
215: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
216: {
217: PETSC_UNUSED dlhandle_t dlhandle;
218: dlsymbol_t dlsymbol;
223: dlhandle = (dlhandle_t) 0;
224: dlsymbol = (dlsymbol_t) 0;
225: *value = (void*) 0;
227: /*
228: --- GetProcAddress ---
229: */
230: #if defined(PETSC_HAVE_WINDOWS_H)
231: #if defined(PETSC_HAVE_GETPROCADDRESS)
232: if (handle) dlhandle = (dlhandle_t) handle;
233: else dlhandle = (dlhandle_t) GetCurrentProcess();
234: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
235: #if defined(PETSC_HAVE_SETLASTERROR)
236: SetLastError((DWORD)0); /* clear any previous error */
237: #endif
238: #endif /* !PETSC_HAVE_GETPROCADDRESS */
240: /*
241: --- dlsym ---
242: */
243: #elif defined(PETSC_HAVE_DLFCN_H)
244: #if defined(PETSC_HAVE_DLSYM)
245: if (handle) dlhandle = (dlhandle_t) handle;
246: else {
248: #if defined(PETSC_HAVE_DLOPEN)
249: /* Attempt to retrieve the main executable's dlhandle. */
250: { int dlflags1 = 0, dlflags2 = 0;
251: #if defined(PETSC_HAVE_RTLD_LAZY)
252: dlflags1 = RTLD_LAZY;
253: #endif
254: if (!dlflags1) {
255: #if defined(PETSC_HAVE_RTLD_NOW)
256: dlflags1 = RTLD_NOW;
257: #endif
258: }
259: #if defined(PETSC_HAVE_RTLD_LOCAL)
260: dlflags2 = RTLD_LOCAL;
261: #endif
262: if (!dlflags2) {
263: #if defined(PETSC_HAVE_RTLD_GLOBAL)
264: dlflags2 = RTLD_GLOBAL;
265: #endif
266: }
267: #if defined(PETSC_HAVE_DLERROR)
268: if (!(PETSC_RUNNING_ON_VALGRIND)) {
269: dlerror(); /* clear any previous error; valgrind does not like this */
270: }
271: #endif
272: /* Attempt to open the main executable as a dynamic library. */
273: #if defined(PETSC_HAVE_RTDL_DEFAULT)
274: dlhandle = RTLD_DEFAULT;
275: #else
276: dlhandle = dlopen(NULL, dlflags1|dlflags2);
277: #if defined(PETSC_HAVE_DLERROR)
278: { const char *e = (const char*) dlerror();
279: 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);
280: }
281: #endif
282: #endif
283: }
284: #endif
285: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
286: }
287: #if defined(PETSC_HAVE_DLERROR)
288: dlerror(); /* clear any previous error */
289: #endif
290: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
291: /*
292: --- unimplemented ---
293: */
294: #else
295: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
296: #endif
298: *value = *((void**)&dlsymbol);
300: #if defined(PETSC_SERIALIZE_FUNCTIONS)
301: if (*value) {
303: PetscFPTAdd(*value,symbol);
304: }
305: #endif
306: return(0);
307: }
309: /*@C
310: PetscDLAddr - find the name of a symbol in a dynamic library
312: Not Collective
314: Input Parameters:
315: + handle - obtained with PetscDLOpen() or NULL
316: - func - pointer to the function, NULL if not found
318: Output Parameter:
319: . name - name of symbol, or NULL if name lookup is not supported.
321: Level: developer
323: Notes:
324: The caller must free the returned name.
326: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
327: systems this requires platform-specific linker flags.
329: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
330: @*/
331: PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
332: {
335: *name = NULL;
336: #if defined(PETSC_HAVE_DLADDR)
337: dlerror(); /* clear any previous error */
338: {
339: Dl_info info;
342: dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
343: #ifdef PETSC_HAVE_CXX
344: PetscDemangleSymbol(info.dli_sname, name);
345: #else
346: PetscStrallocpy(info.dli_sname, name);
347: #endif
348: }
349: #endif
350: return(0);
351: }