Actual source code: dlimpl.c

petsc-3.3-p7 2013-05-11
  2: /*
  3:    Low-level routines for managing dynamic link libraries (DLLs).
  4: */

  6: #include <../src/sys/dll/dlimpl.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: -    flags - options on how to open library

 42:    Output Parameter:
 43: .    handle

 45:    Level: developer

 47: @*/
 48: PetscErrorCode  PetscDLOpen(const char name[],int flags,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 (flags & PETSC_DL_NOW)
 99:     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 (flags & PETSC_DL_LOCAL)
106:     dlflags2 = RTLD_LOCAL;
107: #endif
108: #if defined(PETSC_HAVE_DLERROR)
109:   dlerror(); /* clear any previous error */
110: #endif
111:   dlhandle = dlopen(name,dlflags1|dlflags2);
112:   if (!dlhandle) {
113: #if defined(PETSC_HAVE_DLERROR)
114:     const char *errmsg = dlerror();
115: #else
116:     const char *errmsg = "unavailable";
117: #endif
118:     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s\n",name,errmsg);
119:   }

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

128:   *handle = (PetscDLHandle) dlhandle;

130:   return(0);
131: }


136: /*@C
137:    PetscDLClose -  closes a dynamic library

139:    Not Collective

141:   Input Parameter:
142: .   handle - the handle for the library obtained with PetscDLOpen()

144:   Level: developer
145: @*/
146: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
147: {


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

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

189:   /* 
190:      --- unimplemented --- 
191:   */
192: #else
193:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
194: #endif

196:   *handle = PETSC_NULL;

198:   return(0);
199: }

201: #if defined(PETSC_HAVE_VALGRIND)
202: #include <valgrind/valgrind.h>
203: #endif

207: /*@C
208:    PetscDLSym - finds a symbol in a dynamic library

210:    Not Collective

212:    Input Parameters:
213: +   handle - obtained with PetscDLOpen() or PETSC_NULL
214: -   symbol - name of symbol

216:    Output Parameter:
217: .   value - pointer to the function

219:    Level: developer

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

226: @*/
227: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
228: {
229:   PETSC_UNUSED dlhandle_t dlhandle;
230:   dlsymbol_t dlsymbol;


236:   dlhandle = (dlhandle_t) 0;
237:   dlsymbol = (dlsymbol_t) 0;

239:   *value   = (void *) 0;

241:   /* 
242:      --- GetProcAddress ---
243:   */
244: #if defined(PETSC_HAVE_WINDOWS_H) 
245: #if defined(PETSC_HAVE_GETPROCADDRESS)
246:   if (handle)
247:     dlhandle = (dlhandle_t) handle;
248:   else
249:     dlhandle = (dlhandle_t) GetCurrentProcess();
250:   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
251: #if defined(PETSC_HAVE_SETLASTERROR)
252:   SetLastError((DWORD)0); /* clear any previous error */
253: #endif
254: #endif /* !PETSC_HAVE_GETPROCADDRESS */

256:   /* 
257:      --- dlsym ---
258:   */
259: #elif defined(PETSC_HAVE_DLFCN_H)
260: #if defined(PETSC_HAVE_DLSYM)
261:   if (handle) {
262:     dlhandle = (dlhandle_t) handle;
263:   } else {

265: 
266: #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
267:     /* Attempt to retrieve the main executable's dlhandle. */
268:     { int dlflags1 = 0, dlflags2 = 0;
269: #if defined(PETSC_HAVE_RTLD_LAZY)
270:       dlflags1 = RTLD_LAZY;
271: #endif
272:       if (!dlflags1) {
273: #if defined(PETSC_HAVE_RTLD_NOW)
274:         dlflags1 = RTLD_NOW;
275: #endif
276:       }
277: #if defined(PETSC_HAVE_RTLD_LOCAL)
278:       dlflags2 = RTLD_LOCAL;
279: #endif
280:       if(!dlflags2) {
281: #if defined(PETSC_HAVE_RTLD_GLOBAL)
282:         dlflags2 = RTLD_GLOBAL;
283: #endif
284:       }
285: #if defined(PETSC_HAVE_DLERROR)
286: #if defined(PETSC_HAVE_VALGRIND)
287:       if (!(RUNNING_ON_VALGRIND)) {
288: #endif
289:         dlerror(); /* clear any previous error; valgrind does not like this */
290: #if defined(PETSC_HAVE_VALGRIND)
291:       }
292: #endif
293: #endif
294:       /* Attempt to open the main executable as a dynamic library. */
295: #if defined(PETSC_HAVE_RTDL_DEFAULT)
296:       dlhandle = RTLD_DEFAULT;
297: #else
298:       dlhandle = dlopen(0, dlflags1|dlflags2);
299: #if defined(PETSC_HAVE_DLERROR)
300:       { const char *e = (const char*) dlerror();
301:         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);
302:       }
303: #endif
304: #endif
305:     }
306: #endif
307: #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */
308:   }
309: #if defined(PETSC_HAVE_DLERROR)
310:   dlerror(); /* clear any previous error */
311: #endif
312:   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
313:   /* 
314:      --- unimplemented --- 
315:   */
316: #else
317:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
318: #endif

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

322:   return(0);
323: }