Actual source code: dlimpl.c
petsc-3.10.5 2019-03-28
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

     32: /*@C
     33:    PetscDLOpen - opens dynamic library

     35:    Not Collective

     37:    Input Parameters:
     38: +    name - name of library
     39: -    mode - options on how to open library

     41:    Output Parameter:
     42: .    handle

     44:    Level: developer

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

     56:   dlflags1 = 0;
     57:   dlflags2 = 0;
     58:   dlhandle = (dlhandle_t) 0;
     59:   *handle  = (PetscDLHandle) 0;

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

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

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

    125:   *handle = (PetscDLHandle) dlhandle;
    126:   return(0);
    127: }

    130: /*@C
    131:    PetscDLClose -  closes a dynamic library

    133:    Not Collective

    135:   Input Parameter:
    136: .   handle - the handle for the library obtained with PetscDLOpen()

    138:   Level: developer
    139: @*/
    140: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
    141: {

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

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

    182:   /*
    183:      --- unimplemented ---
    184:   */
    185: #else
    186:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
    187: #endif

    189:   *handle = NULL;
    190:   return(0);
    191: }

    193: /*@C
    194:    PetscDLSym - finds a symbol in a dynamic library

    196:    Not Collective

    198:    Input Parameters:
    199: +   handle - obtained with PetscDLOpen() or NULL
    200: -   symbol - name of symbol

    202:    Output Parameter:
    203: .   value - pointer to the function, NULL if not found

    205:    Level: developer

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

    212: @*/
    213: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
    214: {
    215:   PETSC_UNUSED dlhandle_t dlhandle;
    216:   dlsymbol_t              dlsymbol;

    221:   dlhandle = (dlhandle_t) 0;
    222:   dlsymbol = (dlsymbol_t) 0;
    223:   *value   = (void*) 0;

    225:   /*
    226:      --- GetProcAddress ---
    227:   */
    228: #if defined(PETSC_HAVE_WINDOWS_H)
    229: #if defined(PETSC_HAVE_GETPROCADDRESS)
    230:   if (handle) dlhandle = (dlhandle_t) handle;
    231:   else dlhandle = (dlhandle_t) GetCurrentProcess();
    232:   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
    233: #if defined(PETSC_HAVE_SETLASTERROR)
    234:   SetLastError((DWORD)0); /* clear any previous error */
    235: #endif
    236: #endif /* !PETSC_HAVE_GETPROCADDRESS */

    238:   /*
    239:      --- dlsym ---
    240:   */
    241: #elif defined(PETSC_HAVE_DLFCN_H)
    242: #if defined(PETSC_HAVE_DLSYM)
    243:   if (handle) dlhandle = (dlhandle_t) handle;
    244:   else {

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

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

    298: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    299:   if (*value) {
    301:     PetscFPTAdd(*value,symbol);
    302:   }
    303: #endif
    304:   return(0);
    305: }