17d0a6c19SBarry Smith 2ebd79076SLisandro Dalcin /* 3ebd79076SLisandro Dalcin Low-level routines for managing dynamic link libraries (DLLs). 4ebd79076SLisandro Dalcin */ 5ebd79076SLisandro Dalcin 6af0996ceSBarry Smith #include <petsc/private/petscimpl.h> 7022afb99SBarry Smith #include <petscvalgrind.h> 8ebd79076SLisandro Dalcin 9ebd79076SLisandro Dalcin /* XXX Should be done better !!!*/ 10be1c6ad7SLisandro Dalcin #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 11ebd79076SLisandro Dalcin #undef PETSC_HAVE_WINDOWS_H 12ebd79076SLisandro Dalcin #undef PETSC_HAVE_DLFCN_H 13ebd79076SLisandro Dalcin #endif 14ebd79076SLisandro Dalcin 15ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 16ebd79076SLisandro Dalcin #include <windows.h> 17be1c6ad7SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 18ebd79076SLisandro Dalcin #include <dlfcn.h> 19ebd79076SLisandro Dalcin #endif 20ebd79076SLisandro Dalcin 21ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 22ebd79076SLisandro Dalcin typedef HMODULE dlhandle_t; 236ea75d68SLisandro Dalcin typedef FARPROC dlsymbol_t; 24ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 25ebd79076SLisandro Dalcin typedef void* dlhandle_t; 266ea75d68SLisandro Dalcin typedef void* dlsymbol_t; 27ebd79076SLisandro Dalcin #else 28ebd79076SLisandro Dalcin typedef void* dlhandle_t; 296ea75d68SLisandro Dalcin typedef void* dlsymbol_t; 30ebd79076SLisandro Dalcin #endif 31ebd79076SLisandro Dalcin 32ebd79076SLisandro Dalcin /*@C 33b235ab32SBarry Smith PetscDLOpen - opens dynamic library 34b235ab32SBarry Smith 35b235ab32SBarry Smith Not Collective 36b235ab32SBarry Smith 37b235ab32SBarry Smith Input Parameters: 38b235ab32SBarry Smith + name - name of library 39e4d177b5SBarry Smith - mode - options on how to open library 40b235ab32SBarry Smith 41b235ab32SBarry Smith Output Parameter: 42b235ab32SBarry Smith . handle 43b235ab32SBarry Smith 44b235ab32SBarry Smith Level: developer 45b235ab32SBarry Smith 46ebd79076SLisandro Dalcin @*/ 47e4d177b5SBarry Smith PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle) 48ebd79076SLisandro Dalcin { 498e049581SJed Brown PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */ 50ebd79076SLisandro Dalcin dlhandle_t dlhandle; 51ebd79076SLisandro Dalcin 52ebd79076SLisandro Dalcin PetscFunctionBegin; 53ebd79076SLisandro Dalcin PetscValidCharPointer(name,1); 54ebd79076SLisandro Dalcin PetscValidPointer(handle,3); 55ebd79076SLisandro Dalcin 56be1c6ad7SLisandro Dalcin dlflags1 = 0; 57be1c6ad7SLisandro Dalcin dlflags2 = 0; 585673baf8SLisandro Dalcin dlhandle = (dlhandle_t) 0; 59be1c6ad7SLisandro Dalcin *handle = (PetscDLHandle) 0; 60ebd79076SLisandro Dalcin 615673baf8SLisandro Dalcin /* 625673baf8SLisandro Dalcin --- LoadLibrary --- 635673baf8SLisandro Dalcin */ 64be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY) 65be1c6ad7SLisandro Dalcin dlhandle = LoadLibrary(name); 66ebd79076SLisandro Dalcin if (!dlhandle) { 67ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 68ebd79076SLisandro Dalcin PetscErrorCode ierr; 69ebd79076SLisandro Dalcin DWORD erc; 70b3bb0f5eSLisandro Dalcin char *buff = NULL; 71ebd79076SLisandro Dalcin erc = GetLastError(); 72ebd79076SLisandro Dalcin FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 730298fd71SBarry Smith NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 74*fbfcfee5SBarry Smith ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT, 75be1c6ad7SLisandro Dalcin "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff); 76ebd79076SLisandro Dalcin LocalFree(buff); 77ebd79076SLisandro Dalcin PetscFunctionReturn(ierr); 78ebd79076SLisandro Dalcin #else 79e32f2f54SBarry Smith SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable"); 80ebd79076SLisandro Dalcin #endif 81ebd79076SLisandro Dalcin } 825673baf8SLisandro Dalcin 835673baf8SLisandro Dalcin /* 845673baf8SLisandro Dalcin --- dlopen --- 855673baf8SLisandro Dalcin */ 86a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN) 87ebd79076SLisandro Dalcin /* 88ebd79076SLisandro Dalcin Mode indicates symbols required by symbol loaded with dlsym() 89ebd79076SLisandro Dalcin are only loaded when required (not all together) also indicates 90ebd79076SLisandro Dalcin symbols required can be contained in other libraries also opened 91ebd79076SLisandro Dalcin with dlopen() 92ebd79076SLisandro Dalcin */ 93be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY) 94be1c6ad7SLisandro Dalcin dlflags1 = RTLD_LAZY; 95be1c6ad7SLisandro Dalcin #endif 96ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW) 97a297a907SKarl Rupp if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW; 98ebd79076SLisandro Dalcin #endif 99ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_GLOBAL) 100be1c6ad7SLisandro Dalcin dlflags2 = RTLD_GLOBAL; 101ebd79076SLisandro Dalcin #endif 102b3bb0f5eSLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LOCAL) 103a297a907SKarl Rupp if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL; 104b3bb0f5eSLisandro Dalcin #endif 105be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 106be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 107be1c6ad7SLisandro Dalcin #endif 108be1c6ad7SLisandro Dalcin dlhandle = dlopen(name,dlflags1|dlflags2); 109ebd79076SLisandro Dalcin if (!dlhandle) { 110ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 111ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 112ebd79076SLisandro Dalcin #else 113ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 114ebd79076SLisandro Dalcin #endif 115be015529SBarry Smith SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg); 116ebd79076SLisandro Dalcin } 1175673baf8SLisandro Dalcin 1185673baf8SLisandro Dalcin /* 1195673baf8SLisandro Dalcin --- unimplemented --- 1205673baf8SLisandro Dalcin */ 121ebd79076SLisandro Dalcin #else 122e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 123ebd79076SLisandro Dalcin #endif 124ebd79076SLisandro Dalcin 125ebd79076SLisandro Dalcin *handle = (PetscDLHandle) dlhandle; 126ebd79076SLisandro Dalcin PetscFunctionReturn(0); 127ebd79076SLisandro Dalcin } 128ebd79076SLisandro Dalcin 129ebd79076SLisandro Dalcin 130ebd79076SLisandro Dalcin /*@C 131b235ab32SBarry Smith PetscDLClose - closes a dynamic library 132b235ab32SBarry Smith 133b235ab32SBarry Smith Not Collective 134b235ab32SBarry Smith 135b235ab32SBarry Smith Input Parameter: 136b235ab32SBarry Smith . handle - the handle for the library obtained with PetscDLOpen() 137b235ab32SBarry Smith 138b235ab32SBarry Smith Level: developer 139ebd79076SLisandro Dalcin @*/ 1407087cfbeSBarry Smith PetscErrorCode PetscDLClose(PetscDLHandle *handle) 141ebd79076SLisandro Dalcin { 142ebd79076SLisandro Dalcin 143ebd79076SLisandro Dalcin PetscFunctionBegin; 144ebd79076SLisandro Dalcin PetscValidPointer(handle,1); 145ebd79076SLisandro Dalcin 1465673baf8SLisandro Dalcin /* 1475673baf8SLisandro Dalcin --- FreeLibrary --- 1485673baf8SLisandro Dalcin */ 149ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 150be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY) 1518e049581SJed Brown if (FreeLibrary((dlhandle_t)*handle) == 0) { 1525673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 153b3bb0f5eSLisandro Dalcin char *buff = NULL; 154a21658a3SLisandro Dalcin DWORD erc = GetLastError(); 1550298fd71SBarry Smith FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 1565673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 1575673baf8SLisandro Dalcin LocalFree(buff); 1585673baf8SLisandro Dalcin #else 1595673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 1605673baf8SLisandro Dalcin #endif 1615673baf8SLisandro Dalcin } 162be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */ 163ebd79076SLisandro Dalcin 1645673baf8SLisandro Dalcin /* 1655673baf8SLisandro Dalcin --- dclose --- 1665673baf8SLisandro Dalcin */ 167ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 168a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE) 169be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 170be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 171be1c6ad7SLisandro Dalcin #endif 1728e049581SJed Brown if (dlclose((dlhandle_t)*handle) < 0) { 173ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 174ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 175ebd79076SLisandro Dalcin #else 176ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 177ebd79076SLisandro Dalcin #endif 1785673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 179ebd79076SLisandro Dalcin } 180a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */ 1815673baf8SLisandro Dalcin 1825673baf8SLisandro Dalcin /* 1835673baf8SLisandro Dalcin --- unimplemented --- 1845673baf8SLisandro Dalcin */ 185ebd79076SLisandro Dalcin #else 186e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 187ebd79076SLisandro Dalcin #endif 188ebd79076SLisandro Dalcin 1890298fd71SBarry Smith *handle = NULL; 190ebd79076SLisandro Dalcin PetscFunctionReturn(0); 191ebd79076SLisandro Dalcin } 192ebd79076SLisandro Dalcin 193ebd79076SLisandro Dalcin /*@C 194b235ab32SBarry Smith PetscDLSym - finds a symbol in a dynamic library 195b235ab32SBarry Smith 196b235ab32SBarry Smith Not Collective 197b235ab32SBarry Smith 198b235ab32SBarry Smith Input Parameters: 1990298fd71SBarry Smith + handle - obtained with PetscDLOpen() or NULL 200b235ab32SBarry Smith - symbol - name of symbol 201b235ab32SBarry Smith 202b235ab32SBarry Smith Output Parameter: 2030298fd71SBarry Smith . value - pointer to the function, NULL if not found 204b235ab32SBarry Smith 205b235ab32SBarry Smith Level: developer 206b235ab32SBarry Smith 2077c62f5d3SDmitry Karpeev Notes: 2080298fd71SBarry Smith If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table. 2097c62f5d3SDmitry Karpeev In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 2107c62f5d3SDmitry Karpeev systems this requires platform-specific linker flags. 2117c62f5d3SDmitry Karpeev 212ebd79076SLisandro Dalcin @*/ 2137087cfbeSBarry Smith PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 214ebd79076SLisandro Dalcin { 2158e049581SJed Brown PETSC_UNUSED dlhandle_t dlhandle; 2166ea75d68SLisandro Dalcin dlsymbol_t dlsymbol; 217ebd79076SLisandro Dalcin 218ebd79076SLisandro Dalcin PetscValidCharPointer(symbol,2); 219ebd79076SLisandro Dalcin PetscValidPointer(value,3); 220ebd79076SLisandro Dalcin 221be1c6ad7SLisandro Dalcin dlhandle = (dlhandle_t) 0; 2226ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) 0; 223a21658a3SLisandro Dalcin *value = (void*) 0; 224ebd79076SLisandro Dalcin 2255673baf8SLisandro Dalcin /* 2265673baf8SLisandro Dalcin --- GetProcAddress --- 2275673baf8SLisandro Dalcin */ 228a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 229a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS) 230e4d177b5SBarry Smith if (handle) dlhandle = (dlhandle_t) handle; 231e4d177b5SBarry Smith else dlhandle = (dlhandle_t) GetCurrentProcess(); 2326ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 233a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR) 234a21658a3SLisandro Dalcin SetLastError((DWORD)0); /* clear any previous error */ 235a21658a3SLisandro Dalcin #endif 236a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */ 2375673baf8SLisandro Dalcin 2385673baf8SLisandro Dalcin /* 2395673baf8SLisandro Dalcin --- dlsym --- 2405673baf8SLisandro Dalcin */ 241ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 242a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM) 243a297a907SKarl Rupp if (handle) dlhandle = (dlhandle_t) handle; 244a297a907SKarl Rupp else { 2457c62f5d3SDmitry Karpeev 246bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 2477c62f5d3SDmitry Karpeev /* Attempt to retrieve the main executable's dlhandle. */ 2487c62f5d3SDmitry Karpeev { int dlflags1 = 0, dlflags2 = 0; 2497c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY) 2507c62f5d3SDmitry Karpeev dlflags1 = RTLD_LAZY; 2517c62f5d3SDmitry Karpeev #endif 2527c62f5d3SDmitry Karpeev if (!dlflags1) { 2537c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW) 2547c62f5d3SDmitry Karpeev dlflags1 = RTLD_NOW; 2557c62f5d3SDmitry Karpeev #endif 2567c62f5d3SDmitry Karpeev } 2577c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL) 2587c62f5d3SDmitry Karpeev dlflags2 = RTLD_LOCAL; 2597c62f5d3SDmitry Karpeev #endif 2607c62f5d3SDmitry Karpeev if (!dlflags2) { 2617c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL) 2627c62f5d3SDmitry Karpeev dlflags2 = RTLD_GLOBAL; 2637c62f5d3SDmitry Karpeev #endif 2647c62f5d3SDmitry Karpeev } 2657c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 266cae2f346SBarry Smith if (!(PETSC_RUNNING_ON_VALGRIND)) { 2677bb14e67SBarry Smith dlerror(); /* clear any previous error; valgrind does not like this */ 2687bb14e67SBarry Smith } 2697bb14e67SBarry Smith #endif 2707c62f5d3SDmitry Karpeev /* Attempt to open the main executable as a dynamic library. */ 2717d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT) 2727d421530SBarry Smith dlhandle = RTLD_DEFAULT; 2737d421530SBarry Smith #else 2747c62f5d3SDmitry Karpeev dlhandle = dlopen(0, dlflags1|dlflags2); 2757c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 2764956914eSSatish Balay { const char *e = (const char*) dlerror(); 2777d421530SBarry Smith 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); 2787c62f5d3SDmitry Karpeev } 2797c62f5d3SDmitry Karpeev #endif 2807d421530SBarry Smith #endif 281be1c6ad7SLisandro Dalcin } 282be1c6ad7SLisandro Dalcin #endif 283aa2d57e9SJed Brown #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */ 2844956914eSSatish Balay } 285be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 286be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 287be1c6ad7SLisandro Dalcin #endif 2886ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 2895673baf8SLisandro Dalcin /* 2905673baf8SLisandro Dalcin --- unimplemented --- 2915673baf8SLisandro Dalcin */ 292ebd79076SLisandro Dalcin #else 293e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 294ebd79076SLisandro Dalcin #endif 295ebd79076SLisandro Dalcin 2966ea75d68SLisandro Dalcin *value = *((void**)&dlsymbol); 297ebd79076SLisandro Dalcin 2982d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 2992d53ad75SBarry Smith if (*value) { 3002d53ad75SBarry Smith PetscErrorCode ierr; 3012d53ad75SBarry Smith ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr); 3022d53ad75SBarry Smith } 3032d53ad75SBarry Smith #endif 3042d53ad75SBarry Smith return(0); 305ebd79076SLisandro Dalcin } 306