Actual source code: dlimpl.c

petsc-3.13.6 2020-09-29
Report Typos and Errors

  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: }