Actual source code: dlimpl.c
2: /*
3: Low-level routines for managing dynamic link libraries (DLLs).
4: */
6: #include <petscconf.h>
7: #if defined(PETSC__GNU_SOURCE)
8: #if !defined(_GNU_SOURCE)
9: #define _GNU_SOURCE 1
10: #endif
11: #endif
13: #include <petsc/private/petscimpl.h>
15: /* XXX Should be done better !!!*/
16: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
17: #undef PETSC_HAVE_WINDOWS_H
18: #undef PETSC_HAVE_DLFCN_H
19: #endif
21: #if defined(PETSC_HAVE_WINDOWS_H)
22: #include <windows.h>
23: #endif
24: #if defined(PETSC_HAVE_DLFCN_H)
25: #include <dlfcn.h>
26: #endif
28: #if defined(PETSC_HAVE_WINDOWS_H)
29: typedef HMODULE dlhandle_t;
30: typedef FARPROC dlsymbol_t;
31: #elif defined(PETSC_HAVE_DLFCN_H)
32: typedef void* dlhandle_t;
33: typedef void* dlsymbol_t;
34: #else
35: typedef void* dlhandle_t;
36: typedef void* dlsymbol_t;
37: #endif
39: /*@C
40: PetscDLOpen - opens dynamic library
42: Not Collective
44: Input Parameters:
45: + name - name of library
46: - mode - options on how to open library
48: Output Parameter:
49: . handle - opaque pointer to be used with PetscDLSym()
51: Level: developer
53: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
54: @*/
55: PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
56: {
57: PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
58: dlhandle_t dlhandle;
64: dlflags1 = 0;
65: dlflags2 = 0;
66: dlhandle = (dlhandle_t) 0;
67: *handle = (PetscDLHandle) 0;
69: /*
70: --- LoadLibrary ---
71: */
72: #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
73: dlhandle = LoadLibrary(name);
74: if (!dlhandle) {
75: #if defined(PETSC_HAVE_GETLASTERROR)
77: DWORD erc;
78: char *buff = NULL;
79: erc = GetLastError();
80: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
81: NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
82: PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
83: "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff);
84: LocalFree(buff);
85: PetscFunctionReturn(ierr);
86: #else
87: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable");
88: #endif
89: }
91: /*
92: --- dlopen ---
93: */
94: #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
95: /*
96: Mode indicates symbols required by symbol loaded with dlsym()
97: are only loaded when required (not all together) also indicates
98: symbols required can be contained in other libraries also opened
99: with dlopen()
100: */
101: #if defined(PETSC_HAVE_RTLD_LAZY)
102: dlflags1 = RTLD_LAZY;
103: #endif
104: #if defined(PETSC_HAVE_RTLD_NOW)
105: if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
106: #endif
107: #if defined(PETSC_HAVE_RTLD_GLOBAL)
108: dlflags2 = RTLD_GLOBAL;
109: #endif
110: #if defined(PETSC_HAVE_RTLD_LOCAL)
111: if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
112: #endif
113: #if defined(PETSC_HAVE_DLERROR)
114: dlerror(); /* clear any previous error */
115: #endif
116: dlhandle = dlopen(name,dlflags1|dlflags2);
117: if (!dlhandle) {
118: #if defined(PETSC_HAVE_DLERROR)
119: const char *errmsg = dlerror();
120: #else
121: const char *errmsg = "unavailable";
122: #endif
123: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
124: }
125: /*
126: --- unimplemented ---
127: */
128: #else
129: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
130: #endif
132: *handle = (PetscDLHandle) dlhandle;
133: return(0);
134: }
136: /*@C
137: PetscDLClose - closes a dynamic library
139: Not Collective
141: Input Parameter:
142: . handle - the handle for the library obtained with PetscDLOpen()
144: Level: developer
146: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
147: @*/
148: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
149: {
154: /*
155: --- FreeLibrary ---
156: */
157: #if defined(PETSC_HAVE_WINDOWS_H)
158: #if defined(PETSC_HAVE_FREELIBRARY)
159: if (FreeLibrary((dlhandle_t)*handle) == 0) {
160: #if defined(PETSC_HAVE_GETLASTERROR)
161: char *buff = NULL;
162: DWORD erc = GetLastError();
163: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
164: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
165: LocalFree(buff);
166: #else
167: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
168: #endif
169: }
170: #endif /* !PETSC_HAVE_FREELIBRARY */
172: /*
173: --- dclose ---
174: */
175: #elif defined(PETSC_HAVE_DLFCN_H)
176: #if defined(PETSC_HAVE_DLCLOSE)
177: #if defined(PETSC_HAVE_DLERROR)
178: dlerror(); /* clear any previous error */
179: #endif
180: if (dlclose((dlhandle_t)*handle) < 0) {
181: #if defined(PETSC_HAVE_DLERROR)
182: const char *errmsg = dlerror();
183: #else
184: const char *errmsg = "unavailable";
185: #endif
186: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
187: }
188: #endif /* !PETSC_HAVE_DLCLOSE */
190: /*
191: --- unimplemented ---
192: */
193: #else
194: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
195: #endif
197: *handle = NULL;
198: return(0);
199: }
201: /*@C
202: PetscDLSym - finds a symbol in a dynamic library
204: Not Collective
206: Input Parameters:
207: + handle - obtained with PetscDLOpen() or NULL
208: - symbol - name of symbol
210: Output Parameter:
211: . value - pointer to the function, NULL if not found
213: Level: developer
215: Notes:
216: If handle is 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.
220: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
221: @*/
222: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
223: {
224: PETSC_UNUSED dlhandle_t dlhandle;
225: dlsymbol_t dlsymbol;
230: dlhandle = (dlhandle_t) 0;
231: dlsymbol = (dlsymbol_t) 0;
232: *value = (void*) 0;
234: /*
235: --- GetProcAddress ---
236: */
237: #if defined(PETSC_HAVE_WINDOWS_H)
238: #if defined(PETSC_HAVE_GETPROCADDRESS)
239: if (handle) dlhandle = (dlhandle_t) handle;
240: else dlhandle = (dlhandle_t) GetCurrentProcess();
241: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
242: #if defined(PETSC_HAVE_SETLASTERROR)
243: SetLastError((DWORD)0); /* clear any previous error */
244: #endif
245: #endif /* !PETSC_HAVE_GETPROCADDRESS */
247: /*
248: --- dlsym ---
249: */
250: #elif defined(PETSC_HAVE_DLFCN_H)
251: #if defined(PETSC_HAVE_DLSYM)
252: if (handle) dlhandle = (dlhandle_t) handle;
253: else {
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(NULL, 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_HAVE_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
305: *value = *((void**)&dlsymbol);
307: #if defined(PETSC_SERIALIZE_FUNCTIONS)
308: if (*value) {
310: PetscFPTAdd(*value,symbol);
311: }
312: #endif
313: return(0);
314: }
316: /*@C
317: PetscDLAddr - find the name of a symbol in a dynamic library
319: Not Collective
321: Input Parameters:
322: + handle - obtained with PetscDLOpen() or NULL
323: - func - pointer to the function, NULL if not found
325: Output Parameter:
326: . name - name of symbol, or NULL if name lookup is not supported.
328: Level: developer
330: Notes:
331: The caller must free the returned name.
333: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
334: systems this requires platform-specific linker flags.
336: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
337: @*/
338: PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
339: {
342: *name = NULL;
343: #if defined(PETSC_HAVE_DLADDR)
344: dlerror(); /* clear any previous error */
345: {
346: Dl_info info;
349: dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
350: #ifdef PETSC_HAVE_CXX
351: PetscDemangleSymbol(info.dli_sname, name);
352: #else
353: PetscStrallocpy(info.dli_sname, name);
354: #endif
355: }
356: #endif
357: return(0);
358: }