17d0a6c19SBarry Smith 2ebd79076SLisandro Dalcin /* 3ebd79076SLisandro Dalcin Low-level routines for managing dynamic link libraries (DLLs). 4ebd79076SLisandro Dalcin */ 5ebd79076SLisandro Dalcin 6afcb2eb5SJed Brown #include <petsc-private/petscimpl.h> 7*022afb99SBarry 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 #undef __FUNCT__ 33ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLOpen" 34ebd79076SLisandro Dalcin /*@C 35b235ab32SBarry Smith PetscDLOpen - opens dynamic library 36b235ab32SBarry Smith 37b235ab32SBarry Smith Not Collective 38b235ab32SBarry Smith 39b235ab32SBarry Smith Input Parameters: 40b235ab32SBarry Smith + name - name of library 41e4d177b5SBarry Smith - mode - options on how to open library 42b235ab32SBarry Smith 43b235ab32SBarry Smith Output Parameter: 44b235ab32SBarry Smith . handle 45b235ab32SBarry Smith 46b235ab32SBarry Smith Level: developer 47b235ab32SBarry Smith 48ebd79076SLisandro Dalcin @*/ 49e4d177b5SBarry Smith PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle) 50ebd79076SLisandro Dalcin { 518e049581SJed Brown PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */ 52ebd79076SLisandro Dalcin dlhandle_t dlhandle; 53ebd79076SLisandro Dalcin 54ebd79076SLisandro Dalcin PetscFunctionBegin; 55ebd79076SLisandro Dalcin PetscValidCharPointer(name,1); 56ebd79076SLisandro Dalcin PetscValidPointer(handle,3); 57ebd79076SLisandro Dalcin 58be1c6ad7SLisandro Dalcin dlflags1 = 0; 59be1c6ad7SLisandro Dalcin dlflags2 = 0; 605673baf8SLisandro Dalcin dlhandle = (dlhandle_t) 0; 61be1c6ad7SLisandro Dalcin *handle = (PetscDLHandle) 0; 62ebd79076SLisandro Dalcin 635673baf8SLisandro Dalcin /* 645673baf8SLisandro Dalcin --- LoadLibrary --- 655673baf8SLisandro Dalcin */ 66be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY) 67be1c6ad7SLisandro Dalcin dlhandle = LoadLibrary(name); 68ebd79076SLisandro Dalcin if (!dlhandle) { 69ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 70ebd79076SLisandro Dalcin PetscErrorCode ierr; 71ebd79076SLisandro Dalcin DWORD erc; 72b3bb0f5eSLisandro Dalcin char *buff = NULL; 73ebd79076SLisandro Dalcin erc = GetLastError(); 74ebd79076SLisandro Dalcin FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 750298fd71SBarry Smith NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 76efca3c55SSatish Balay ierr = PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT, 77be1c6ad7SLisandro Dalcin "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff); 78ebd79076SLisandro Dalcin LocalFree(buff); 79ebd79076SLisandro Dalcin PetscFunctionReturn(ierr); 80ebd79076SLisandro Dalcin #else 81e32f2f54SBarry 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"); 82ebd79076SLisandro Dalcin #endif 83ebd79076SLisandro Dalcin } 845673baf8SLisandro Dalcin 855673baf8SLisandro Dalcin /* 865673baf8SLisandro Dalcin --- dlopen --- 875673baf8SLisandro Dalcin */ 88a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN) 89ebd79076SLisandro Dalcin /* 90ebd79076SLisandro Dalcin Mode indicates symbols required by symbol loaded with dlsym() 91ebd79076SLisandro Dalcin are only loaded when required (not all together) also indicates 92ebd79076SLisandro Dalcin symbols required can be contained in other libraries also opened 93ebd79076SLisandro Dalcin with dlopen() 94ebd79076SLisandro Dalcin */ 95be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY) 96be1c6ad7SLisandro Dalcin dlflags1 = RTLD_LAZY; 97be1c6ad7SLisandro Dalcin #endif 98ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW) 99a297a907SKarl Rupp if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW; 100ebd79076SLisandro Dalcin #endif 101ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_GLOBAL) 102be1c6ad7SLisandro Dalcin dlflags2 = RTLD_GLOBAL; 103ebd79076SLisandro Dalcin #endif 104b3bb0f5eSLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LOCAL) 105a297a907SKarl Rupp if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL; 106b3bb0f5eSLisandro Dalcin #endif 107be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 108be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 109be1c6ad7SLisandro Dalcin #endif 110be1c6ad7SLisandro Dalcin dlhandle = dlopen(name,dlflags1|dlflags2); 111ebd79076SLisandro Dalcin if (!dlhandle) { 112ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 113ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 114ebd79076SLisandro Dalcin #else 115ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 116ebd79076SLisandro Dalcin #endif 117be015529SBarry 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); 118ebd79076SLisandro Dalcin } 1195673baf8SLisandro Dalcin 1205673baf8SLisandro Dalcin /* 1215673baf8SLisandro Dalcin --- unimplemented --- 1225673baf8SLisandro Dalcin */ 123ebd79076SLisandro Dalcin #else 124e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 125ebd79076SLisandro Dalcin #endif 126ebd79076SLisandro Dalcin 127ebd79076SLisandro Dalcin *handle = (PetscDLHandle) dlhandle; 128ebd79076SLisandro Dalcin PetscFunctionReturn(0); 129ebd79076SLisandro Dalcin } 130ebd79076SLisandro Dalcin 131ebd79076SLisandro Dalcin 132ebd79076SLisandro Dalcin #undef __FUNCT__ 133ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLClose" 134ebd79076SLisandro Dalcin /*@C 135b235ab32SBarry Smith PetscDLClose - closes a dynamic library 136b235ab32SBarry Smith 137b235ab32SBarry Smith Not Collective 138b235ab32SBarry Smith 139b235ab32SBarry Smith Input Parameter: 140b235ab32SBarry Smith . handle - the handle for the library obtained with PetscDLOpen() 141b235ab32SBarry Smith 142b235ab32SBarry Smith Level: developer 143ebd79076SLisandro Dalcin @*/ 1447087cfbeSBarry Smith PetscErrorCode PetscDLClose(PetscDLHandle *handle) 145ebd79076SLisandro Dalcin { 146ebd79076SLisandro Dalcin 147ebd79076SLisandro Dalcin PetscFunctionBegin; 148ebd79076SLisandro Dalcin PetscValidPointer(handle,1); 149ebd79076SLisandro Dalcin 1505673baf8SLisandro Dalcin /* 1515673baf8SLisandro Dalcin --- FreeLibrary --- 1525673baf8SLisandro Dalcin */ 153ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 154be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY) 1558e049581SJed Brown if (FreeLibrary((dlhandle_t)*handle) == 0) { 1565673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 157b3bb0f5eSLisandro Dalcin char *buff = NULL; 158a21658a3SLisandro Dalcin DWORD erc = GetLastError(); 1590298fd71SBarry 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); 1605673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 1615673baf8SLisandro Dalcin LocalFree(buff); 1625673baf8SLisandro Dalcin #else 1635673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 1645673baf8SLisandro Dalcin #endif 1655673baf8SLisandro Dalcin } 166be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */ 167ebd79076SLisandro Dalcin 1685673baf8SLisandro Dalcin /* 1695673baf8SLisandro Dalcin --- dclose --- 1705673baf8SLisandro Dalcin */ 171ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 172a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE) 173be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 174be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 175be1c6ad7SLisandro Dalcin #endif 1768e049581SJed Brown if (dlclose((dlhandle_t)*handle) < 0) { 177ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 178ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 179ebd79076SLisandro Dalcin #else 180ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 181ebd79076SLisandro Dalcin #endif 1825673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 183ebd79076SLisandro Dalcin } 184a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */ 1855673baf8SLisandro Dalcin 1865673baf8SLisandro Dalcin /* 1875673baf8SLisandro Dalcin --- unimplemented --- 1885673baf8SLisandro Dalcin */ 189ebd79076SLisandro Dalcin #else 190e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 191ebd79076SLisandro Dalcin #endif 192ebd79076SLisandro Dalcin 1930298fd71SBarry Smith *handle = NULL; 194ebd79076SLisandro Dalcin PetscFunctionReturn(0); 195ebd79076SLisandro Dalcin } 196ebd79076SLisandro Dalcin 197ebd79076SLisandro Dalcin #undef __FUNCT__ 198ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLSym" 199ebd79076SLisandro Dalcin /*@C 200b235ab32SBarry Smith PetscDLSym - finds a symbol in a dynamic library 201b235ab32SBarry Smith 202b235ab32SBarry Smith Not Collective 203b235ab32SBarry Smith 204b235ab32SBarry Smith Input Parameters: 2050298fd71SBarry Smith + handle - obtained with PetscDLOpen() or NULL 206b235ab32SBarry Smith - symbol - name of symbol 207b235ab32SBarry Smith 208b235ab32SBarry Smith Output Parameter: 2090298fd71SBarry Smith . value - pointer to the function, NULL if not found 210b235ab32SBarry Smith 211b235ab32SBarry Smith Level: developer 212b235ab32SBarry Smith 2137c62f5d3SDmitry Karpeev Notes: 2140298fd71SBarry Smith If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table. 2157c62f5d3SDmitry Karpeev In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 2167c62f5d3SDmitry Karpeev systems this requires platform-specific linker flags. 2177c62f5d3SDmitry Karpeev 218ebd79076SLisandro Dalcin @*/ 2197087cfbeSBarry Smith PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 220ebd79076SLisandro Dalcin { 2218e049581SJed Brown PETSC_UNUSED dlhandle_t dlhandle; 2226ea75d68SLisandro Dalcin dlsymbol_t dlsymbol; 223ebd79076SLisandro Dalcin 224ebd79076SLisandro Dalcin PetscValidCharPointer(symbol,2); 225ebd79076SLisandro Dalcin PetscValidPointer(value,3); 226ebd79076SLisandro Dalcin 227be1c6ad7SLisandro Dalcin dlhandle = (dlhandle_t) 0; 2286ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) 0; 229a21658a3SLisandro Dalcin *value = (void*) 0; 230ebd79076SLisandro Dalcin 2315673baf8SLisandro Dalcin /* 2325673baf8SLisandro Dalcin --- GetProcAddress --- 2335673baf8SLisandro Dalcin */ 234a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 235a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS) 236e4d177b5SBarry Smith if (handle) dlhandle = (dlhandle_t) handle; 237e4d177b5SBarry Smith else dlhandle = (dlhandle_t) GetCurrentProcess(); 2386ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 239a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR) 240a21658a3SLisandro Dalcin SetLastError((DWORD)0); /* clear any previous error */ 241a21658a3SLisandro Dalcin #endif 242a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */ 2435673baf8SLisandro Dalcin 2445673baf8SLisandro Dalcin /* 2455673baf8SLisandro Dalcin --- dlsym --- 2465673baf8SLisandro Dalcin */ 247ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 248a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM) 249a297a907SKarl Rupp if (handle) dlhandle = (dlhandle_t) handle; 250a297a907SKarl Rupp else { 2517c62f5d3SDmitry Karpeev 252bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 2537c62f5d3SDmitry Karpeev /* Attempt to retrieve the main executable's dlhandle. */ 2547c62f5d3SDmitry Karpeev { int dlflags1 = 0, dlflags2 = 0; 2557c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY) 2567c62f5d3SDmitry Karpeev dlflags1 = RTLD_LAZY; 2577c62f5d3SDmitry Karpeev #endif 2587c62f5d3SDmitry Karpeev if (!dlflags1) { 2597c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW) 2607c62f5d3SDmitry Karpeev dlflags1 = RTLD_NOW; 2617c62f5d3SDmitry Karpeev #endif 2627c62f5d3SDmitry Karpeev } 2637c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL) 2647c62f5d3SDmitry Karpeev dlflags2 = RTLD_LOCAL; 2657c62f5d3SDmitry Karpeev #endif 2667c62f5d3SDmitry Karpeev if (!dlflags2) { 2677c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL) 2687c62f5d3SDmitry Karpeev dlflags2 = RTLD_GLOBAL; 2697c62f5d3SDmitry Karpeev #endif 2707c62f5d3SDmitry Karpeev } 2717c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 272cae2f346SBarry Smith if (!(PETSC_RUNNING_ON_VALGRIND)) { 2737bb14e67SBarry Smith dlerror(); /* clear any previous error; valgrind does not like this */ 2747bb14e67SBarry Smith } 2757bb14e67SBarry Smith #endif 2767c62f5d3SDmitry Karpeev /* Attempt to open the main executable as a dynamic library. */ 2777d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT) 2787d421530SBarry Smith dlhandle = RTLD_DEFAULT; 2797d421530SBarry Smith #else 2807c62f5d3SDmitry Karpeev dlhandle = dlopen(0, dlflags1|dlflags2); 2817c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 2824956914eSSatish Balay { const char *e = (const char*) dlerror(); 2837d421530SBarry 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); 2847c62f5d3SDmitry Karpeev } 2857c62f5d3SDmitry Karpeev #endif 2867d421530SBarry Smith #endif 287be1c6ad7SLisandro Dalcin } 288be1c6ad7SLisandro Dalcin #endif 289aa2d57e9SJed Brown #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */ 2904956914eSSatish Balay } 291be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 292be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 293be1c6ad7SLisandro Dalcin #endif 2946ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 2955673baf8SLisandro Dalcin /* 2965673baf8SLisandro Dalcin --- unimplemented --- 2975673baf8SLisandro Dalcin */ 298ebd79076SLisandro Dalcin #else 299e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 300ebd79076SLisandro Dalcin #endif 301ebd79076SLisandro Dalcin 3026ea75d68SLisandro Dalcin *value = *((void**)&dlsymbol); 303ebd79076SLisandro Dalcin 3042d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 3052d53ad75SBarry Smith if (*value) { 3062d53ad75SBarry Smith PetscErrorCode ierr; 3072d53ad75SBarry Smith ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr); 3082d53ad75SBarry Smith } 3092d53ad75SBarry Smith #endif 3102d53ad75SBarry Smith return(0); 311ebd79076SLisandro Dalcin } 312