Actual source code: dlimpl.c

petsc-3.4.5 2014-06-29
  2: /*
  3:    Low-level routines for managing dynamic link libraries (DLLs).
  4: */

  6: #include <petsc-private/petscimpl.h>

  8: /* XXX Should be done better !!!*/
  9: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
 10: #undef PETSC_HAVE_WINDOWS_H
 11: #undef PETSC_HAVE_DLFCN_H
 12: #endif

 14: #if defined(PETSC_HAVE_WINDOWS_H)
 15: #include <windows.h>
 16: #elif defined(PETSC_HAVE_DLFCN_H)
 17: #include <dlfcn.h>
 18: #endif

 20: #if defined(PETSC_HAVE_WINDOWS_H)
 21: typedef HMODULE dlhandle_t;
 22: typedef FARPROC dlsymbol_t;
 23: #elif defined(PETSC_HAVE_DLFCN_H)
 24: typedef void* dlhandle_t;
 25: typedef void* dlsymbol_t;
 26: #else
 27: typedef void* dlhandle_t;
 28: typedef void* dlsymbol_t;
 29: #endif

 33: /*@C
 34:    PetscDLOpen - opens dynamic library

 36:    Not Collective

 38:    Input Parameters:
 39: +    name - name of library
 40: -    mode - options on how to open library

 42:    Output Parameter:
 43: .    handle

 45:    Level: developer

 47: @*/
 48: PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
 49: {
 50:   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
 51:   dlhandle_t       dlhandle;


 57:   dlflags1 = 0;
 58:   dlflags2 = 0;
 59:   dlhandle = (dlhandle_t) 0;
 60:   *handle  = (PetscDLHandle) 0;

 62:   /*
 63:      --- LoadLibrary ---
 64:   */
 65: #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
 66:   dlhandle = LoadLibrary(name);
 67:   if (!dlhandle) {
 68: #if defined(PETSC_HAVE_GETLASTERROR)
 70:     DWORD          erc;
 71:     char           *buff = NULL;
 72:     erc = GetLastError();
 73:     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
 74:                   NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
 75:     PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,__SDIR__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
 76:                       "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,buff);
 77:     LocalFree(buff);
 78:     PetscFunctionReturn(ierr);
 79: #else
 80:     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,"unavailable");
 81: #endif
 82:   }

 84:   /*
 85:      --- dlopen ---
 86:   */
 87: #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
 88:   /*
 89:       Mode indicates symbols required by symbol loaded with dlsym()
 90:      are only loaded when required (not all together) also indicates
 91:      symbols required can be contained in other libraries also opened
 92:      with dlopen()
 93:   */
 94: #if defined(PETSC_HAVE_RTLD_LAZY)
 95:   dlflags1 = RTLD_LAZY;
 96: #endif
 97: #if defined(PETSC_HAVE_RTLD_NOW)
 98:   if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
 99: #endif
100: #if defined(PETSC_HAVE_RTLD_GLOBAL)
101:   dlflags2 = RTLD_GLOBAL;
102: #endif
103: #if defined(PETSC_HAVE_RTLD_LOCAL)
104:   if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
105: #endif
106: #if defined(PETSC_HAVE_DLERROR)
107:   dlerror(); /* clear any previous error */
108: #endif
109:   dlhandle = dlopen(name,dlflags1|dlflags2);
110:   if (!dlhandle) {
111: #if defined(PETSC_HAVE_DLERROR)
112:     const char *errmsg = dlerror();
113: #else
114:     const char *errmsg = "unavailable";
115: #endif
116:     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s\n",name,errmsg);
117:   }

119:   /*
120:      --- unimplemented ---
121:   */
122: #else
123:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
124: #endif

126:   *handle = (PetscDLHandle) dlhandle;
127:   return(0);
128: }


133: /*@C
134:    PetscDLClose -  closes a dynamic library

136:    Not Collective

138:   Input Parameter:
139: .   handle - the handle for the library obtained with PetscDLOpen()

141:   Level: developer
142: @*/
143: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
144: {


149:   /*
150:      --- FreeLibrary ---
151:   */
152: #if defined(PETSC_HAVE_WINDOWS_H)
153: #if defined(PETSC_HAVE_FREELIBRARY)
154:   if (FreeLibrary((dlhandle_t)*handle) == 0) {
155: #if defined(PETSC_HAVE_GETLASTERROR)
156:     char  *buff = NULL;
157:     DWORD erc   = GetLastError();
158:     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
159:     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n",buff);
160:     LocalFree(buff);
161: #else
162:     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n","unavailable");
163: #endif
164:   }
165: #endif /* !PETSC_HAVE_FREELIBRARY */

167:   /*
168:      --- dclose ---
169:   */
170: #elif defined(PETSC_HAVE_DLFCN_H)
171: #if defined(PETSC_HAVE_DLCLOSE)
172: #if defined(PETSC_HAVE_DLERROR)
173:   dlerror(); /* clear any previous error */
174: #endif
175:   if (dlclose((dlhandle_t)*handle) < 0) {
176: #if defined(PETSC_HAVE_DLERROR)
177:     const char *errmsg = dlerror();
178: #else
179:     const char *errmsg = "unavailable";
180: #endif
181:     PetscErrorPrintf("Error closing dynamic library:\n  Error message from dlclose() %s\n", errmsg);
182:   }
183: #endif /* !PETSC_HAVE_DLCLOSE */

185:   /*
186:      --- unimplemented ---
187:   */
188: #else
189:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
190: #endif

192:   *handle = NULL;
193:   return(0);
194: }

198: /*@C
199:    PetscDLSym - finds a symbol in a dynamic library

201:    Not Collective

203:    Input Parameters:
204: +   handle - obtained with PetscDLOpen() or NULL
205: -   symbol - name of symbol

207:    Output Parameter:
208: .   value - pointer to the function, NULL if not found

210:    Level: developer

212:   Notes:
213:    If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
214:    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
215:    systems this requires platform-specific linker flags.

217: @*/
218: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
219: {
220:   PETSC_UNUSED dlhandle_t dlhandle;
221:   dlsymbol_t              dlsymbol;


226:   dlhandle = (dlhandle_t) 0;
227:   dlsymbol = (dlsymbol_t) 0;
228:   *value   = (void*) 0;

230:   /*
231:      --- GetProcAddress ---
232:   */
233: #if defined(PETSC_HAVE_WINDOWS_H)
234: #if defined(PETSC_HAVE_GETPROCADDRESS)
235:   if (handle) dlhandle = (dlhandle_t) handle;
236:   else dlhandle = (dlhandle_t) GetCurrentProcess();
237:   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
238: #if defined(PETSC_HAVE_SETLASTERROR)
239:   SetLastError((DWORD)0); /* clear any previous error */
240: #endif
241: #endif /* !PETSC_HAVE_GETPROCADDRESS */

243:   /*
244:      --- dlsym ---
245:   */
246: #elif defined(PETSC_HAVE_DLFCN_H)
247: #if defined(PETSC_HAVE_DLSYM)
248:   if (handle) dlhandle = (dlhandle_t) handle;
249:   else {

251: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
252:     /* Attempt to retrieve the main executable's dlhandle. */
253:     { int dlflags1 = 0, dlflags2 = 0;
254: #if defined(PETSC_HAVE_RTLD_LAZY)
255:       dlflags1 = RTLD_LAZY;
256: #endif
257:       if (!dlflags1) {
258: #if defined(PETSC_HAVE_RTLD_NOW)
259:         dlflags1 = RTLD_NOW;
260: #endif
261:       }
262: #if defined(PETSC_HAVE_RTLD_LOCAL)
263:       dlflags2 = RTLD_LOCAL;
264: #endif
265:       if (!dlflags2) {
266: #if defined(PETSC_HAVE_RTLD_GLOBAL)
267:         dlflags2 = RTLD_GLOBAL;
268: #endif
269:       }
270: #if defined(PETSC_HAVE_DLERROR)
271:       if (!(PETSC_RUNNING_ON_VALGRIND)) {
272:         dlerror(); /* clear any previous error; valgrind does not like this */
273:       }
274: #endif
275:       /* Attempt to open the main executable as a dynamic library. */
276: #if defined(PETSC_HAVE_RTDL_DEFAULT)
277:       dlhandle = RTLD_DEFAULT;
278: #else
279:       dlhandle = dlopen(0, dlflags1|dlflags2);
280: #if defined(PETSC_HAVE_DLERROR)
281:       { const char *e = (const char*) dlerror();
282:         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);
283:       }
284: #endif
285: #endif
286:     }
287: #endif
288: #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */
289:   }
290: #if defined(PETSC_HAVE_DLERROR)
291:   dlerror(); /* clear any previous error */
292: #endif
293:   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
294:   /*
295:      --- unimplemented ---
296:   */
297: #else
298:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
299: #endif

301:   *value = *((void**)&dlsymbol);

303: #if defined(PETSC_SERIALIZE_FUNCTIONS)
304:   if (*value) {
306:     PetscFPTAdd(*value,symbol);
307:   }
308: #endif
309:   return(0);
310: }