Date: 2013-07-02T14:38:42+00:00

Actual source code: dlimpl.c
petsc-3.4.2 2013-07-02

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