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>
 14: #include <petscvalgrind.h>

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

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

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

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

 43:    Not Collective

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

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

 52:    Level: developer

 54: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
 55: @*/
 56: PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
 57: {
 58:   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
 59:   dlhandle_t       dlhandle;


 65:   dlflags1 = 0;
 66:   dlflags2 = 0;
 67:   dlhandle = (dlhandle_t) 0;
 68:   *handle  = (PetscDLHandle) 0;

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

 92:   /*
 93:      --- dlopen ---
 94:   */
 95: #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
 96:   /*
 97:       Mode indicates symbols required by symbol loaded with dlsym()
 98:      are only loaded when required (not all together) also indicates
 99:      symbols required can be contained in other libraries also opened
100:      with dlopen()
101:   */
102: #if defined(PETSC_HAVE_RTLD_LAZY)
103:   dlflags1 = RTLD_LAZY;
104: #endif
105: #if defined(PETSC_HAVE_RTLD_NOW)
106:   if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
107: #endif
108: #if defined(PETSC_HAVE_RTLD_GLOBAL)
109:   dlflags2 = RTLD_GLOBAL;
110: #endif
111: #if defined(PETSC_HAVE_RTLD_LOCAL)
112:   if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
113: #endif
114: #if defined(PETSC_HAVE_DLERROR)
115:   dlerror(); /* clear any previous error */
116: #endif
117:   dlhandle = dlopen(name,dlflags1|dlflags2);
118:   if (!dlhandle) {
119: #if defined(PETSC_HAVE_DLERROR)
120:     const char *errmsg = dlerror();
121: #else
122:     const char *errmsg = "unavailable";
123: #endif
124:     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s\n",name,errmsg);
125:   }
126:   /*
127:      --- unimplemented ---
128:   */
129: #else
130:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
131: #endif

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


138: /*@C
139:    PetscDLClose -  closes a dynamic library

141:    Not Collective

143:   Input Parameter:
144: .   handle - the handle for the library obtained with PetscDLOpen()

146:   Level: developer

148: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
149: @*/
150: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
151: {


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

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

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

199:   *handle = NULL;
200:   return(0);
201: }

203: /*@C
204:    PetscDLSym - finds a symbol in a dynamic library

206:    Not Collective

208:    Input Parameters:
209: +   handle - obtained with PetscDLOpen() or NULL
210: -   symbol - name of symbol

212:    Output Parameter:
213: .   value - pointer to the function, NULL if not found

215:    Level: developer

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

222: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
223: @*/
224: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
225: {
226:   PETSC_UNUSED dlhandle_t dlhandle;
227:   dlsymbol_t              dlsymbol;


232:   dlhandle = (dlhandle_t) 0;
233:   dlsymbol = (dlsymbol_t) 0;
234:   *value   = (void*) 0;

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

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

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

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

309: #if defined(PETSC_SERIALIZE_FUNCTIONS)
310:   if (*value) {
312:     PetscFPTAdd(*value,symbol);
313:   }
314: #endif
315:   return(0);
316: }


319: /*@C
320:   PetscDLAddr - find the name of a symbol in a dynamic library

322:   Not Collective

324:   Input Parameters:
325: + handle - obtained with PetscDLOpen() or NULL
326: - func   - pointer to the function, NULL if not found

328:   Output Parameter:
329: . name   - name of symbol, or NULL if name lookup is not supported

331:   Level: developer

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

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

350:     dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
351:     *name = info.dli_sname;
352:   }
353: #endif
354:   return(0);
355: }