Date: 2022-03-31T04:46:05+00:00

Actual source code: dlimpl.c

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

      5: #include <petscconf.h>
      6: #if defined(PETSC__GNU_SOURCE)
      7:   #if !defined(_GNU_SOURCE)
      8:     #define _GNU_SOURCE 1
      9:   #endif
     10: #endif

     12: #include <petsc/private/petscimpl.h>

     14: #if defined(PETSC_HAVE_WINDOWS_H)
     15: #include <windows.h>
     16: #endif
     17: #if 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 - opaque pointer to be used with PetscDLSym()

     44:    Level: developer

     46: .seealso: PetscDLClose(), PetscDLSym(), PetscDLAddr()
     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;

     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:     return ierr;
     78: #else
     79:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s",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:     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s",name,errmsg);
    116:   }
    117:   /*
    118:      --- unimplemented ---
    119:   */
    120: #else
    121:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
    122: #endif

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

    128: /*@C
    129:    PetscDLClose -  closes a dynamic library

    131:    Not Collective

    133:   Input Parameter:
    134: .   handle - the handle for the library obtained with PetscDLOpen()

    136:   Level: developer

    138: .seealso: PetscDLOpen(), PetscDLSym(), PetscDLAddr()
    139: @*/
    140: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
    141: {

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

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

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

    187:   *handle = NULL;
    188:   return 0;
    189: }

    191: /*@C
    192:    PetscDLSym - finds a symbol in a dynamic library

    194:    Not Collective

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

    200:    Output Parameter:
    201: .   value - pointer to the function, NULL if not found

    203:    Level: developer

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

    210: .seealso: PetscDLClose(), PetscDLOpen(), PetscDLAddr()
    211: @*/
    212: PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
    213: {
    214:   PETSC_UNUSED dlhandle_t dlhandle;
    215:   dlsymbol_t              dlsymbol;

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

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

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

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

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

    297: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    298:   if (*value) PetscFPTAdd(*value,symbol);
    299: #endif
    300:   return(0);
    301: }

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

    306:   Not Collective

    308:   Input Parameters:
    309: + handle - obtained with PetscDLOpen() or NULL
    310: - func   - pointer to the function, NULL if not found

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

    315:   Level: developer

    317:   Notes:
    318:   The caller must free the returned name.

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

    323: .seealso: PetscDLClose(), PetscDLSym(), PetscDLOpen()
    324: @*/
    325: PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
    326: {
    328:   *name = NULL;
    329: #if defined(PETSC_HAVE_DLADDR)
    330:   dlerror(); /* clear any previous error */
    331:   {
    332:     Dl_info info;

    335: #ifdef PETSC_HAVE_CXX
    336:     PetscDemangleSymbol(info.dli_sname, name);
    337: #else
    338:     PetscStrallocpy(info.dli_sname, name);
    339: #endif
    340:   }
    341: #endif
    342:   return 0;
    343: }