Actual source code: dlimpl.c
petsc-3.14.6 2021-03-30
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
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
44: Level: developer
46: @*/
47: PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
48: {
49: PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
50: 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: PetscFunctionReturn(ierr);
78: #else
79: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",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: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg);
116: }
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: }
130: /*@C
131: PetscDLClose - closes a dynamic library
133: Not Collective
135: Input Parameter:
136: . handle - the handle for the library obtained with PetscDLOpen()
138: Level: developer
139: @*/
140: PetscErrorCode PetscDLClose(PetscDLHandle *handle)
141: {
146: /*
147: --- FreeLibrary ---
148: */
149: #if defined(PETSC_HAVE_WINDOWS_H)
150: #if defined(PETSC_HAVE_FREELIBRARY)
151: if (FreeLibrary((dlhandle_t)*handle) == 0) {
152: #if defined(PETSC_HAVE_GETLASTERROR)
153: char *buff = NULL;
154: DWORD erc = GetLastError();
155: FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
156: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff);
157: LocalFree(buff);
158: #else
159: PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable");
160: #endif
161: }
162: #endif /* !PETSC_HAVE_FREELIBRARY */
164: /*
165: --- dclose ---
166: */
167: #elif defined(PETSC_HAVE_DLFCN_H)
168: #if defined(PETSC_HAVE_DLCLOSE)
169: #if defined(PETSC_HAVE_DLERROR)
170: dlerror(); /* clear any previous error */
171: #endif
172: if (dlclose((dlhandle_t)*handle) < 0) {
173: #if defined(PETSC_HAVE_DLERROR)
174: const char *errmsg = dlerror();
175: #else
176: const char *errmsg = "unavailable";
177: #endif
178: PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg);
179: }
180: #endif /* !PETSC_HAVE_DLCLOSE */
182: /*
183: --- unimplemented ---
184: */
185: #else
186: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
187: #endif
189: *handle = NULL;
190: return(0);
191: }
193: /*@C
194: PetscDLSym - finds a symbol in a dynamic library
196: Not Collective
198: Input Parameters:
199: + handle - obtained with PetscDLOpen() or NULL
200: - symbol - name of symbol
202: Output Parameter:
203: . value - pointer to the function, NULL if not found
205: Level: developer
207: Notes:
208: If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
209: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
210: systems this requires platform-specific linker flags.
212: @*/
213: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
214: {
215: PETSC_UNUSED dlhandle_t dlhandle;
216: dlsymbol_t dlsymbol;
221: dlhandle = (dlhandle_t) 0;
222: dlsymbol = (dlsymbol_t) 0;
223: *value = (void*) 0;
225: /*
226: --- GetProcAddress ---
227: */
228: #if defined(PETSC_HAVE_WINDOWS_H)
229: #if defined(PETSC_HAVE_GETPROCADDRESS)
230: if (handle) dlhandle = (dlhandle_t) handle;
231: else dlhandle = (dlhandle_t) GetCurrentProcess();
232: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
233: #if defined(PETSC_HAVE_SETLASTERROR)
234: SetLastError((DWORD)0); /* clear any previous error */
235: #endif
236: #endif /* !PETSC_HAVE_GETPROCADDRESS */
238: /*
239: --- dlsym ---
240: */
241: #elif defined(PETSC_HAVE_DLFCN_H)
242: #if defined(PETSC_HAVE_DLSYM)
243: if (handle) dlhandle = (dlhandle_t) handle;
244: else {
246: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
247: /* Attempt to retrieve the main executable's dlhandle. */
248: { int dlflags1 = 0, dlflags2 = 0;
249: #if defined(PETSC_HAVE_RTLD_LAZY)
250: dlflags1 = RTLD_LAZY;
251: #endif
252: if (!dlflags1) {
253: #if defined(PETSC_HAVE_RTLD_NOW)
254: dlflags1 = RTLD_NOW;
255: #endif
256: }
257: #if defined(PETSC_HAVE_RTLD_LOCAL)
258: dlflags2 = RTLD_LOCAL;
259: #endif
260: if (!dlflags2) {
261: #if defined(PETSC_HAVE_RTLD_GLOBAL)
262: dlflags2 = RTLD_GLOBAL;
263: #endif
264: }
265: #if defined(PETSC_HAVE_DLERROR)
266: if (!(PETSC_RUNNING_ON_VALGRIND)) {
267: dlerror(); /* clear any previous error; valgrind does not like this */
268: }
269: #endif
270: /* Attempt to open the main executable as a dynamic library. */
271: #if defined(PETSC_HAVE_RTDL_DEFAULT)
272: dlhandle = RTLD_DEFAULT;
273: #else
274: dlhandle = dlopen(NULL, dlflags1|dlflags2);
275: #if defined(PETSC_HAVE_DLERROR)
276: { const char *e = (const char*) dlerror();
277: 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);
278: }
279: #endif
280: #endif
281: }
282: #endif
283: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
284: }
285: #if defined(PETSC_HAVE_DLERROR)
286: dlerror(); /* clear any previous error */
287: #endif
288: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
289: /*
290: --- unimplemented ---
291: */
292: #else
293: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
294: #endif
296: *value = *((void**)&dlsymbol);
298: #if defined(PETSC_SERIALIZE_FUNCTIONS)
299: if (*value) {
301: PetscFPTAdd(*value,symbol);
302: }
303: #endif
304: return(0);
305: }