Actual source code: dlimpl.c
petsc-3.15.0 2021-03-30
Report Typos and Errors

      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

     52:    Level: developer

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

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

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

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

    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
    147: @*/
    148: PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
    149: {

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

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

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

    197:   *handle = NULL;
    198:   return(0);
    199: }

    201: /*@C
    202:    PetscDLSym - finds a symbol in a dynamic library

    204:    Not Collective

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

    210:    Output Parameter:
    211: .   value - pointer to the function, NULL if not found

    213:    Level: developer

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

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

    229:   dlhandle = (dlhandle_t) 0;
    230:   dlsymbol = (dlsymbol_t) 0;
    231:   *value   = (void*) 0;

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

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

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

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

    306: #if defined(PETSC_SERIALIZE_FUNCTIONS)
    307:   if (*value) {
    309:     PetscFPTAdd(*value,symbol);
    310:   }
    311: #endif
    312:   return(0);
    313: }

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

    319:   Not Collective

    321:   Input Parameters:
    322: + handle - obtained with PetscDLOpen() or NULL
    323: - func   - pointer to the function, NULL if not found

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

    328:   Level: developer

    330:   Notes:
    331:   In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
    332:   systems this requires platform-specific linker flags.
    333: @*/
    334: PetscErrorCode PetscDLAddr(void (*func)(void), const char **name)
    335: {
    338:   *name = NULL;
    339: #if defined(PETSC_HAVE_DLADDR)
    340:   dlerror(); /* clear any previous error */
    341:   {
    342:     Dl_info        info;

    345:     dladdr(*(void **) &func, &info);if (!ierr) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
    346:     *name = info.dli_sname;
    347:   }
    348: #endif
    349:   return(0);
    350: }