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>
14: #include <petscvalgrind.h>
16: /* XXX Should be done better !!!*/
17: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
18: #undef PETSC_HAVE_WINDOWS_H
19: #undef PETSC_HAVE_DLFCN_H
20: #endif
22: #if defined(PETSC_HAVE_WINDOWS_H)
23: #include <windows.h>
24: #endif
25: #if defined(PETSC_HAVE_DLFCN_H)
26: #include <dlfcn.h>
27: #endif
29: #if defined(PETSC_HAVE_WINDOWS_H)
30: typedef HMODULE dlhandle_t;
31: typedef FARPROC dlsymbol_t;
32: #elif defined(PETSC_HAVE_DLFCN_H)
33: typedef void* dlhandle_t;
34: typedef void* dlsymbol_t;
35: #else
36: typedef void* dlhandle_t;
37: typedef void* dlsymbol_t;
38: #endif
40: /*@C
41: PetscDLOpen - opens dynamic library
43: Not Collective
45: Input Parameters:
46: + name - name of library
47: - mode - options on how to open library
49: Output Parameter:
50: . handle - opaque pointer to be used with PetscDLSym()
52: Level: developer
54: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
55: @*/
56: PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
57: {
58: PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
59: dlhandle_t dlhandle;
65: dlflags1 = 0;
66: dlflags2 = 0;
67: dlhandle = (dlhandle_t) 0;
68: *handle = (PetscDLHandle) 0;
70: /*
71: --- LoadLibrary ---
72: */
73: #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
74: dlhandle = LoadLibrary(name);
75: if (!dlhandle) {
76: #if defined(PETSC_HAVE_GETLASTERROR)
78: DWORD erc;
79: char *buff = NULL;
80: erc = GetLastError();
81: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
82: NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
83: PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
84: "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff);
85: LocalFree(buff);
86: PetscFunctionReturn(ierr);
87: #else
88: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable");
89: #endif
90: }
92: /*
93: --- dlopen ---
94: */
95: #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
96: /*
97: Mode indicates symbols required by symbol loaded with dlsym()
98: are only loaded when required (not all together) also indicates
99: symbols required can be contained in other libraries also opened
100: with dlopen()
101: */
102: #if defined(PETSC_HAVE_RTLD_LAZY)
103: dlflags1 = RTLD_LAZY;
104: #endif
105: #if defined(PETSC_HAVE_RTLD_NOW)
106: if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
107: #endif
108: #if defined(PETSC_HAVE_RTLD_GLOBAL)
109: dlflags2 = RTLD_GLOBAL;
110: #endif
111: #if defined(PETSC_HAVE_RTLD_LOCAL)
112: if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
113: #endif
114: #if defined(PETSC_HAVE_DLERROR)
115: dlerror(); /* clear any previous error */
116: #endif
117: dlhandle = dlopen(name,dlflags1|dlflags2);
118: if (!dlhandle) {
119: #if defined(PETSC_HAVE_DLERROR)
120: const char *errmsg = dlerror();
121: #else
122: const char *errmsg = "unavailable";
123: #endif
124: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
125: }
126: /*
127: --- unimplemented ---
128: */
129: #else
130: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
131: #endif
133: *handle = (PetscDLHandle) dlhandle;
134: return(0);
135: }
138: /*@C
139: PetscDLClose - closes a dynamic library
141: Not Collective
143: Input Parameter:
144: . handle - the handle for the library obtained with PetscDLOpen()
146: Level: developer
148: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
149: @*/
150: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
151: {
156: /*
157: --- FreeLibrary ---
158: */
159: #if defined(PETSC_HAVE_WINDOWS_H)
160: #if defined(PETSC_HAVE_FREELIBRARY)
161: if (FreeLibrary((dlhandle_t)*handle) == 0) {
162: #if defined(PETSC_HAVE_GETLASTERROR)
163: char *buff = NULL;
164: DWORD erc = GetLastError();
165: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
166: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
167: LocalFree(buff);
168: #else
169: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
170: #endif
171: }
172: #endif /* !PETSC_HAVE_FREELIBRARY */
174: /*
175: --- dclose ---
176: */
177: #elif defined(PETSC_HAVE_DLFCN_H)
178: #if defined(PETSC_HAVE_DLCLOSE)
179: #if defined(PETSC_HAVE_DLERROR)
180: dlerror(); /* clear any previous error */
181: #endif
182: if (dlclose((dlhandle_t)*handle) < 0) {
183: #if defined(PETSC_HAVE_DLERROR)
184: const char *errmsg = dlerror();
185: #else
186: const char *errmsg = "unavailable";
187: #endif
188: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
189: }
190: #endif /* !PETSC_HAVE_DLCLOSE */
192: /*
193: --- unimplemented ---
194: */
195: #else
196: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
197: #endif
199: *handle = NULL;
200: return(0);
201: }
203: /*@C
204: PetscDLSym - finds a symbol in a dynamic library
206: Not Collective
208: Input Parameters:
209: + handle - obtained with PetscDLOpen() or NULL
210: - symbol - name of symbol
212: Output Parameter:
213: . value - pointer to the function, NULL if not found
215: Level: developer
217: Notes:
218: If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
219: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
220: systems this requires platform-specific linker flags.
222: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
223: @*/
224: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
225: {
226: PETSC_UNUSED dlhandle_t dlhandle;
227: dlsymbol_t dlsymbol;
232: dlhandle = (dlhandle_t) 0;
233: dlsymbol = (dlsymbol_t) 0;
234: *value = (void*) 0;
236: /*
237: --- GetProcAddress ---
238: */
239: #if defined(PETSC_HAVE_WINDOWS_H)
240: #if defined(PETSC_HAVE_GETPROCADDRESS)
241: if (handle) dlhandle = (dlhandle_t) handle;
242: else dlhandle = (dlhandle_t) GetCurrentProcess();
243: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
244: #if defined(PETSC_HAVE_SETLASTERROR)
245: SetLastError((DWORD)0); /* clear any previous error */
246: #endif
247: #endif /* !PETSC_HAVE_GETPROCADDRESS */
249: /*
250: --- dlsym ---
251: */
252: #elif defined(PETSC_HAVE_DLFCN_H)
253: #if defined(PETSC_HAVE_DLSYM)
254: if (handle) dlhandle = (dlhandle_t) handle;
255: else {
257: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
258: /* Attempt to retrieve the main executable's dlhandle. */
259: { int dlflags1 = 0, dlflags2 = 0;
260: #if defined(PETSC_HAVE_RTLD_LAZY)
261: dlflags1 = RTLD_LAZY;
262: #endif
263: if (!dlflags1) {
264: #if defined(PETSC_HAVE_RTLD_NOW)
265: dlflags1 = RTLD_NOW;
266: #endif
267: }
268: #if defined(PETSC_HAVE_RTLD_LOCAL)
269: dlflags2 = RTLD_LOCAL;
270: #endif
271: if (!dlflags2) {
272: #if defined(PETSC_HAVE_RTLD_GLOBAL)
273: dlflags2 = RTLD_GLOBAL;
274: #endif
275: }
276: #if defined(PETSC_HAVE_DLERROR)
277: if (!(PETSC_RUNNING_ON_VALGRIND)) {
278: dlerror(); /* clear any previous error; valgrind does not like this */
279: }
280: #endif
281: /* Attempt to open the main executable as a dynamic library. */
282: #if defined(PETSC_HAVE_RTDL_DEFAULT)
283: dlhandle = RTLD_DEFAULT;
284: #else
285: dlhandle = dlopen(NULL, dlflags1|dlflags2);
286: #if defined(PETSC_HAVE_DLERROR)
287: { const char *e = (const char*) dlerror();
288: 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);
289: }
290: #endif
291: #endif
292: }
293: #endif
294: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
295: }
296: #if defined(PETSC_HAVE_DLERROR)
297: dlerror(); /* clear any previous error */
298: #endif
299: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
300: /*
301: --- unimplemented ---
302: */
303: #else
304: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
305: #endif
307: *value = *((void**)&dlsymbol);
309: #if defined(PETSC_SERIALIZE_FUNCTIONS)
310: if (*value) {
312: PetscFPTAdd(*value,symbol);
313: }
314: #endif
315: return(0);
316: }
319: /*@C
320: PetscDLAddr - find the name of a symbol in a dynamic library
322: Not Collective
324: Input Parameters:
325: + handle - obtained with PetscDLOpen() or NULL
326: - func - pointer to the function, NULL if not found
328: Output Parameter:
329: . name - name of symbol, or NULL if name lookup is not supported
331: Level: developer
333: Notes:
334: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
335: systems this requires platform-specific linker flags.
337: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
338: @*/
339: PetscErrorCode PetscDLAddr(void (*func)(void), const char **name)
340: {
343: *name = NULL;
344: #if defined(PETSC_HAVE_DLADDR)
345: dlerror(); /* clear any previous error */
346: {
347: Dl_info info;
350: dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
351: *name = info.dli_sname;
352: }
353: #endif
354: return(0);
355: }