Actual source code: dlimpl.c
petsc-3.7.7 2017-09-25
2: /*
3: Low-level routines for managing dynamic link libraries (DLLs).
4: */
6: #include <petsc/private/petscimpl.h>
7: #include <petscvalgrind.h>
9: /* XXX Should be done better !!!*/
10: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
11: #undef PETSC_HAVE_WINDOWS_H
12: #undef PETSC_HAVE_DLFCN_H
13: #endif
15: #if defined(PETSC_HAVE_WINDOWS_H)
16: #include <windows.h>
17: #elif 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
34: /*@C
35: PetscDLOpen - opens dynamic library
37: Not Collective
39: Input Parameters:
40: + name - name of library
41: - mode - options on how to open library
43: Output Parameter:
44: . handle
46: Level: developer
48: @*/
49: PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
50: {
51: PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
52: dlhandle_t dlhandle;
58: dlflags1 = 0;
59: dlflags2 = 0;
60: dlhandle = (dlhandle_t) 0;
61: *handle = (PetscDLHandle) 0;
63: /*
64: --- LoadLibrary ---
65: */
66: #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
67: dlhandle = LoadLibrary(name);
68: if (!dlhandle) {
69: #if defined(PETSC_HAVE_GETLASTERROR)
71: DWORD erc;
72: char *buff = NULL;
73: erc = GetLastError();
74: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
75: NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
76: PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
77: "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff);
78: LocalFree(buff);
79: PetscFunctionReturn(ierr);
80: #else
81: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable");
82: #endif
83: }
85: /*
86: --- dlopen ---
87: */
88: #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
89: /*
90: Mode indicates symbols required by symbol loaded with dlsym()
91: are only loaded when required (not all together) also indicates
92: symbols required can be contained in other libraries also opened
93: with dlopen()
94: */
95: #if defined(PETSC_HAVE_RTLD_LAZY)
96: dlflags1 = RTLD_LAZY;
97: #endif
98: #if defined(PETSC_HAVE_RTLD_NOW)
99: if (mode & PETSC_DL_NOW) 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) dlflags2 = RTLD_LOCAL;
106: #endif
107: #if defined(PETSC_HAVE_DLERROR)
108: dlerror(); /* clear any previous error */
109: #endif
110: dlhandle = dlopen(name,dlflags1|dlflags2);
111: if (!dlhandle) {
112: #if defined(PETSC_HAVE_DLERROR)
113: const char *errmsg = dlerror();
114: #else
115: const char *errmsg = "unavailable";
116: #endif
117: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
118: }
120: /*
121: --- unimplemented ---
122: */
123: #else
124: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
125: #endif
127: *handle = (PetscDLHandle) dlhandle;
128: return(0);
129: }
134: /*@C
135: PetscDLClose - closes a dynamic library
137: Not Collective
139: Input Parameter:
140: . handle - the handle for the library obtained with PetscDLOpen()
142: Level: developer
143: @*/
144: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
145: {
150: /*
151: --- FreeLibrary ---
152: */
153: #if defined(PETSC_HAVE_WINDOWS_H)
154: #if defined(PETSC_HAVE_FREELIBRARY)
155: if (FreeLibrary((dlhandle_t)*handle) == 0) {
156: #if defined(PETSC_HAVE_GETLASTERROR)
157: char *buff = NULL;
158: DWORD erc = GetLastError();
159: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
160: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
161: LocalFree(buff);
162: #else
163: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
164: #endif
165: }
166: #endif /* !PETSC_HAVE_FREELIBRARY */
168: /*
169: --- dclose ---
170: */
171: #elif defined(PETSC_HAVE_DLFCN_H)
172: #if defined(PETSC_HAVE_DLCLOSE)
173: #if defined(PETSC_HAVE_DLERROR)
174: dlerror(); /* clear any previous error */
175: #endif
176: if (dlclose((dlhandle_t)*handle) < 0) {
177: #if defined(PETSC_HAVE_DLERROR)
178: const char *errmsg = dlerror();
179: #else
180: const char *errmsg = "unavailable";
181: #endif
182: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
183: }
184: #endif /* !PETSC_HAVE_DLCLOSE */
186: /*
187: --- unimplemented ---
188: */
189: #else
190: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
191: #endif
193: *handle = NULL;
194: return(0);
195: }
199: /*@C
200: PetscDLSym - finds a symbol in a dynamic library
202: Not Collective
204: Input Parameters:
205: + handle - obtained with PetscDLOpen() or NULL
206: - symbol - name of symbol
208: Output Parameter:
209: . value - pointer to the function, NULL if not found
211: Level: developer
213: Notes:
214: If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
215: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
216: systems this requires platform-specific linker flags.
218: @*/
219: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
220: {
221: PETSC_UNUSED dlhandle_t dlhandle;
222: dlsymbol_t dlsymbol;
227: dlhandle = (dlhandle_t) 0;
228: dlsymbol = (dlsymbol_t) 0;
229: *value = (void*) 0;
231: /*
232: --- GetProcAddress ---
233: */
234: #if defined(PETSC_HAVE_WINDOWS_H)
235: #if defined(PETSC_HAVE_GETPROCADDRESS)
236: if (handle) dlhandle = (dlhandle_t) handle;
237: else dlhandle = (dlhandle_t) GetCurrentProcess();
238: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
239: #if defined(PETSC_HAVE_SETLASTERROR)
240: SetLastError((DWORD)0); /* clear any previous error */
241: #endif
242: #endif /* !PETSC_HAVE_GETPROCADDRESS */
244: /*
245: --- dlsym ---
246: */
247: #elif defined(PETSC_HAVE_DLFCN_H)
248: #if defined(PETSC_HAVE_DLSYM)
249: if (handle) dlhandle = (dlhandle_t) handle;
250: else {
252: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
253: /* Attempt to retrieve the main executable's dlhandle. */
254: { int dlflags1 = 0, dlflags2 = 0;
255: #if defined(PETSC_HAVE_RTLD_LAZY)
256: dlflags1 = RTLD_LAZY;
257: #endif
258: if (!dlflags1) {
259: #if defined(PETSC_HAVE_RTLD_NOW)
260: dlflags1 = RTLD_NOW;
261: #endif
262: }
263: #if defined(PETSC_HAVE_RTLD_LOCAL)
264: dlflags2 = RTLD_LOCAL;
265: #endif
266: if (!dlflags2) {
267: #if defined(PETSC_HAVE_RTLD_GLOBAL)
268: dlflags2 = RTLD_GLOBAL;
269: #endif
270: }
271: #if defined(PETSC_HAVE_DLERROR)
272: if (!(PETSC_RUNNING_ON_VALGRIND)) {
273: dlerror(); /* clear any previous error; valgrind does not like this */
274: }
275: #endif
276: /* Attempt to open the main executable as a dynamic library. */
277: #if defined(PETSC_HAVE_RTDL_DEFAULT)
278: dlhandle = RTLD_DEFAULT;
279: #else
280: dlhandle = dlopen(0, dlflags1|dlflags2);
281: #if defined(PETSC_HAVE_DLERROR)
282: { const char *e = (const char*) dlerror();
283: 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);
284: }
285: #endif
286: #endif
287: }
288: #endif
289: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
290: }
291: #if defined(PETSC_HAVE_DLERROR)
292: dlerror(); /* clear any previous error */
293: #endif
294: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
295: /*
296: --- unimplemented ---
297: */
298: #else
299: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
300: #endif
302: *value = *((void**)&dlsymbol);
304: #if defined(PETSC_SERIALIZE_FUNCTIONS)
305: if (*value) {
307: PetscFPTAdd(*value,symbol);
308: }
309: #endif
310: return(0);
311: }