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;
56: dlflags1 = 0;
57: dlflags2 = 0;
58: dlhandle = (dlhandle_t) 0;
59: *handle = (PetscDLHandle) 0;
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)
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: 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: return ierr;
78: #else
79: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s",name,"unavailable");
80: #endif
81: }
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: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s",name,errmsg);
116: }
117: /*
118: --- unimplemented ---
119: */
120: #else
121: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
122: #endif
124: *handle = (PetscDLHandle) dlhandle;
125: return 0;
126: }
128: /*@C
129: PetscDLClose - closes a dynamic library
131: Not Collective
133: Input Parameter:
134: . handle - the handle for the library obtained with PetscDLOpen()
136: Level: developer
138: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
139: @*/
140: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
141: {
144: /*
145: --- FreeLibrary ---
146: */
147: #if defined(PETSC_HAVE_WINDOWS_H)
148: #if defined(PETSC_HAVE_FREELIBRARY)
149: if (FreeLibrary((dlhandle_t)*handle) == 0) {
150: #if defined(PETSC_HAVE_GETLASTERROR)
151: char *buff = NULL;
152: DWORD erc = GetLastError();
153: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
154: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
155: LocalFree(buff);
156: #else
157: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
158: #endif
159: }
160: #endif /* !PETSC_HAVE_FREELIBRARY */
162: /*
163: --- dclose ---
164: */
165: #elif defined(PETSC_HAVE_DLFCN_H)
166: #if defined(PETSC_HAVE_DLCLOSE)
167: #if defined(PETSC_HAVE_DLERROR)
168: dlerror(); /* clear any previous error */
169: #endif
170: if (dlclose((dlhandle_t)*handle) < 0) {
171: #if defined(PETSC_HAVE_DLERROR)
172: const char *errmsg = dlerror();
173: #else
174: const char *errmsg = "unavailable";
175: #endif
176: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
177: }
178: #endif /* !PETSC_HAVE_DLCLOSE */
180: /*
181: --- unimplemented ---
182: */
183: #else
184: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
185: #endif
187: *handle = NULL;
188: return 0;
189: }
191: /*@C
192: PetscDLSym - finds a symbol in a dynamic library
194: Not Collective
196: Input Parameters:
197: + handle - obtained with PetscDLOpen() or NULL
198: - symbol - name of symbol
200: Output Parameter:
201: . value - pointer to the function, NULL if not found
203: Level: developer
205: Notes:
206: If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
207: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
208: systems this requires platform-specific linker flags.
210: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
211: @*/
212: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
213: {
214: PETSC_UNUSED dlhandle_t dlhandle;
215: dlsymbol_t dlsymbol;
220: dlhandle = (dlhandle_t) 0;
221: dlsymbol = (dlsymbol_t) 0;
222: *value = (void*) 0;
224: /*
225: --- GetProcAddress ---
226: */
227: #if defined(PETSC_HAVE_WINDOWS_H)
228: #if defined(PETSC_HAVE_GETPROCADDRESS)
229: if (handle) dlhandle = (dlhandle_t) handle;
230: else dlhandle = (dlhandle_t) GetCurrentProcess();
231: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
232: #if defined(PETSC_HAVE_SETLASTERROR)
233: SetLastError((DWORD)0); /* clear any previous error */
234: #endif
235: #endif /* !PETSC_HAVE_GETPROCADDRESS */
237: /*
238: --- dlsym ---
239: */
240: #elif defined(PETSC_HAVE_DLFCN_H)
241: #if defined(PETSC_HAVE_DLSYM)
242: if (handle) dlhandle = (dlhandle_t) handle;
243: else {
245: #if defined(PETSC_HAVE_DLOPEN)
246: /* Attempt to retrieve the main executable's dlhandle. */
247: { int dlflags1 = 0, dlflags2 = 0;
248: #if defined(PETSC_HAVE_RTLD_LAZY)
249: dlflags1 = RTLD_LAZY;
250: #endif
251: if (!dlflags1) {
252: #if defined(PETSC_HAVE_RTLD_NOW)
253: dlflags1 = RTLD_NOW;
254: #endif
255: }
256: #if defined(PETSC_HAVE_RTLD_LOCAL)
257: dlflags2 = RTLD_LOCAL;
258: #endif
259: if (!dlflags2) {
260: #if defined(PETSC_HAVE_RTLD_GLOBAL)
261: dlflags2 = RTLD_GLOBAL;
262: #endif
263: }
264: #if defined(PETSC_HAVE_DLERROR)
265: if (!(PETSC_RUNNING_ON_VALGRIND)) {
266: dlerror(); /* clear any previous error; valgrind does not like this */
267: }
268: #endif
269: /* Attempt to open the main executable as a dynamic library. */
270: #if defined(PETSC_HAVE_RTDL_DEFAULT)
271: dlhandle = RTLD_DEFAULT;
272: #else
273: dlhandle = dlopen(NULL, dlflags1|dlflags2);
274: #if defined(PETSC_HAVE_DLERROR)
275: { const char *e = (const char*) dlerror();
277: }
278: #endif
279: #endif
280: }
281: #endif
282: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
283: }
284: #if defined(PETSC_HAVE_DLERROR)
285: dlerror(); /* clear any previous error */
286: #endif
287: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
288: /*
289: --- unimplemented ---
290: */
291: #else
292: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
293: #endif
295: *value = *((void**)&dlsymbol);
297: #if defined(PETSC_SERIALIZE_FUNCTIONS)
298: if (*value) PetscFPTAdd(*value,symbol);
299: #endif
300: return(0);
301: }
303: /*@C
304: PetscDLAddr - find the name of a symbol in a dynamic library
306: Not Collective
308: Input Parameters:
309: + handle - obtained with PetscDLOpen() or NULL
310: - func - pointer to the function, NULL if not found
312: Output Parameter:
313: . name - name of symbol, or NULL if name lookup is not supported.
315: Level: developer
317: Notes:
318: The caller must free the returned name.
320: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
321: systems this requires platform-specific linker flags.
323: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
324: @*/
325: PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
326: {
328: *name = NULL;
329: #if defined(PETSC_HAVE_DLADDR)
330: dlerror(); /* clear any previous error */
331: {
332: Dl_info info;
335: #ifdef PETSC_HAVE_CXX
336: PetscDemangleSymbol(info.dli_sname, name);
337: #else
338: PetscStrallocpy(info.dli_sname, name);
339: #endif
340: }
341: #endif
342: return 0;
343: }