Actual source code: dlimpl.c
petsc-3.15.0 2021-03-30
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
52: Level: developer
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: }
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
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: @*/
221: PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
222: {
223: PETSC_UNUSED dlhandle_t dlhandle;
224: dlsymbol_t dlsymbol;
229: dlhandle = (dlhandle_t) 0;
230: dlsymbol = (dlsymbol_t) 0;
231: *value = (void*) 0;
233: /*
234: --- GetProcAddress ---
235: */
236: #if defined(PETSC_HAVE_WINDOWS_H)
237: #if defined(PETSC_HAVE_GETPROCADDRESS)
238: if (handle) dlhandle = (dlhandle_t) handle;
239: else dlhandle = (dlhandle_t) GetCurrentProcess();
240: dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
241: #if defined(PETSC_HAVE_SETLASTERROR)
242: SetLastError((DWORD)0); /* clear any previous error */
243: #endif
244: #endif /* !PETSC_HAVE_GETPROCADDRESS */
246: /*
247: --- dlsym ---
248: */
249: #elif defined(PETSC_HAVE_DLFCN_H)
250: #if defined(PETSC_HAVE_DLSYM)
251: if (handle) dlhandle = (dlhandle_t) handle;
252: else {
254: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
255: /* Attempt to retrieve the main executable's dlhandle. */
256: { int dlflags1 = 0, dlflags2 = 0;
257: #if defined(PETSC_HAVE_RTLD_LAZY)
258: dlflags1 = RTLD_LAZY;
259: #endif
260: if (!dlflags1) {
261: #if defined(PETSC_HAVE_RTLD_NOW)
262: dlflags1 = RTLD_NOW;
263: #endif
264: }
265: #if defined(PETSC_HAVE_RTLD_LOCAL)
266: dlflags2 = RTLD_LOCAL;
267: #endif
268: if (!dlflags2) {
269: #if defined(PETSC_HAVE_RTLD_GLOBAL)
270: dlflags2 = RTLD_GLOBAL;
271: #endif
272: }
273: #if defined(PETSC_HAVE_DLERROR)
274: if (!(PETSC_RUNNING_ON_VALGRIND)) {
275: dlerror(); /* clear any previous error; valgrind does not like this */
276: }
277: #endif
278: /* Attempt to open the main executable as a dynamic library. */
279: #if defined(PETSC_HAVE_RTDL_DEFAULT)
280: dlhandle = RTLD_DEFAULT;
281: #else
282: dlhandle = dlopen(NULL, dlflags1|dlflags2);
283: #if defined(PETSC_HAVE_DLERROR)
284: { const char *e = (const char*) dlerror();
285: 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);
286: }
287: #endif
288: #endif
289: }
290: #endif
291: #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
292: }
293: #if defined(PETSC_HAVE_DLERROR)
294: dlerror(); /* clear any previous error */
295: #endif
296: dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
297: /*
298: --- unimplemented ---
299: */
300: #else
301: SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
302: #endif
304: *value = *((void**)&dlsymbol);
306: #if defined(PETSC_SERIALIZE_FUNCTIONS)
307: if (*value) {
309: PetscFPTAdd(*value,symbol);
310: }
311: #endif
312: return(0);
313: }
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: In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like
332: systems this requires platform-specific linker flags.
333: @*/
334: PetscErrorCode PetscDLAddr(void (*func)(void), const char **name)
335: {
338: *name = NULL;
339: #if defined(PETSC_HAVE_DLADDR)
340: dlerror(); /* clear any previous error */
341: {
342: Dl_info info;
345: dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
346: *name = info.dli_sname;
347: }
348: #endif
349: return(0);
350: }