Actual source code: dlimpl.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      2: /*
      3:    Low-level routines for managing dynamic link libraries (DLLs).
      4: */

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

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

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

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

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

     37:    Not Collective

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

     43:    Output Parameter:
     44: .    handle

     46:    Level: developer

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

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

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

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

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

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

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

    137:    Not Collective

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

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

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

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

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

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

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

    202:    Not Collective

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

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

    211:    Level: developer

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

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

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

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

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

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

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

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