Actual source code: dlimpl.c

petsc-3.7.7 2017-09-25
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

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