Actual source code: dlimpl.c


  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>

 15: /* XXX Should be done better !!!*/
 16: #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
 17: #undef PETSC_HAVE_WINDOWS_H
 18: #undef PETSC_HAVE_DLFCN_H
 19: #endif

 21: #if defined(PETSC_HAVE_WINDOWS_H)
 22: #include <windows.h>
 23: #endif
 24: #if defined(PETSC_HAVE_DLFCN_H)
 25: #include <dlfcn.h>
 26: #endif

 28: #if defined(PETSC_HAVE_WINDOWS_H)
 29: typedef HMODULE dlhandle_t;
 30: typedef FARPROC dlsymbol_t;
 31: #elif defined(PETSC_HAVE_DLFCN_H)
 32: typedef void* dlhandle_t;
 33: typedef void* dlsymbol_t;
 34: #else
 35: typedef void* dlhandle_t;
 36: typedef void* dlsymbol_t;
 37: #endif

 39: /*@C
 40:    PetscDLOpen - opens dynamic library

 42:    Not Collective

 44:    Input Parameters:
 45: +    name - name of library
 46: -    mode - options on how to open library

 48:    Output Parameter:
 49: .    handle - opaque pointer to be used with PetscDLSym()

 51:    Level: developer

 53: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
 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:   }
125:   /*
126:      --- unimplemented ---
127:   */
128: #else
129:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
130: #endif

132:   *handle = (PetscDLHandle) dlhandle;
133:   return(0);
134: }

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

146: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
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: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
221: @*/
222: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
223: {
224:   PETSC_UNUSED dlhandle_t dlhandle;
225:   dlsymbol_t              dlsymbol;


230:   dlhandle = (dlhandle_t) 0;
231:   dlsymbol = (dlsymbol_t) 0;
232:   *value   = (void*) 0;

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

247:   /*
248:      --- dlsym ---
249:   */
250: #elif defined(PETSC_HAVE_DLFCN_H)
251: #if defined(PETSC_HAVE_DLSYM)
252:   if (handle) dlhandle = (dlhandle_t) handle;
253:   else {

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

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

307: #if defined(PETSC_SERIALIZE_FUNCTIONS)
308:   if (*value) {
310:     PetscFPTAdd(*value,symbol);
311:   }
312: #endif
313:   return(0);
314: }

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:   The caller must free the returned name.

333:   In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
334:   systems this requires platform-specific linker flags.

336: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
337: @*/
338: PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
339: {
342:   *name = NULL;
343: #if defined(PETSC_HAVE_DLADDR)
344:   dlerror(); /* clear any previous error */
345:   {
346:     Dl_info        info;

349:     dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
350: #ifdef PETSC_HAVE_CXX
351:     PetscDemangleSymbol(info.dli_sname, name);
352: #else
353:     PetscStrallocpy(info.dli_sname, name);
354: #endif
355:   }
356: #endif
357:   return(0);
358: }