17d0a6c19SBarry Smith 2ebd79076SLisandro Dalcin /* 3ebd79076SLisandro Dalcin Low-level routines for managing dynamic link libraries (DLLs). 4ebd79076SLisandro Dalcin */ 5ebd79076SLisandro Dalcin 67d5d4d99SBarry Smith #include <petscsys.h> 7ebd79076SLisandro Dalcin 8ebd79076SLisandro Dalcin /* XXX Should be done better !!!*/ 9be1c6ad7SLisandro Dalcin #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 10ebd79076SLisandro Dalcin #undef PETSC_HAVE_WINDOWS_H 11ebd79076SLisandro Dalcin #undef PETSC_HAVE_DLFCN_H 12ebd79076SLisandro Dalcin #endif 13ebd79076SLisandro Dalcin 14ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 15ebd79076SLisandro Dalcin #include <windows.h> 16be1c6ad7SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 17ebd79076SLisandro Dalcin #include <dlfcn.h> 18ebd79076SLisandro Dalcin #endif 19ebd79076SLisandro Dalcin 20ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 21ebd79076SLisandro Dalcin typedef HMODULE dlhandle_t; 226ea75d68SLisandro Dalcin typedef FARPROC dlsymbol_t; 23ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 24ebd79076SLisandro Dalcin typedef void* dlhandle_t; 256ea75d68SLisandro Dalcin typedef void* dlsymbol_t; 26ebd79076SLisandro Dalcin #else 27ebd79076SLisandro Dalcin typedef void* dlhandle_t; 286ea75d68SLisandro Dalcin typedef void* dlsymbol_t; 29ebd79076SLisandro Dalcin #endif 30ebd79076SLisandro Dalcin 31ebd79076SLisandro Dalcin #undef __FUNCT__ 32ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLOpen" 33ebd79076SLisandro Dalcin /*@C 34b235ab32SBarry Smith PetscDLOpen - opens dynamic library 35b235ab32SBarry Smith 36b235ab32SBarry Smith Not Collective 37b235ab32SBarry Smith 38b235ab32SBarry Smith Input Parameters: 39b235ab32SBarry Smith + name - name of library 40*e4d177b5SBarry Smith - mode - options on how to open library 41b235ab32SBarry Smith 42b235ab32SBarry Smith Output Parameter: 43b235ab32SBarry Smith . handle 44b235ab32SBarry Smith 45b235ab32SBarry Smith Level: developer 46b235ab32SBarry Smith 47ebd79076SLisandro Dalcin @*/ 48*e4d177b5SBarry Smith PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle) 49ebd79076SLisandro Dalcin { 508e049581SJed Brown PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */ 51ebd79076SLisandro Dalcin dlhandle_t dlhandle; 52ebd79076SLisandro Dalcin 53ebd79076SLisandro Dalcin PetscFunctionBegin; 54ebd79076SLisandro Dalcin PetscValidCharPointer(name,1); 55ebd79076SLisandro Dalcin PetscValidPointer(handle,3); 56ebd79076SLisandro Dalcin 57be1c6ad7SLisandro Dalcin dlflags1 = 0; 58be1c6ad7SLisandro Dalcin dlflags2 = 0; 595673baf8SLisandro Dalcin dlhandle = (dlhandle_t) 0; 60be1c6ad7SLisandro Dalcin *handle = (PetscDLHandle) 0; 61ebd79076SLisandro Dalcin 625673baf8SLisandro Dalcin /* 635673baf8SLisandro Dalcin --- LoadLibrary --- 645673baf8SLisandro Dalcin */ 65be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY) 66be1c6ad7SLisandro Dalcin dlhandle = LoadLibrary(name); 67ebd79076SLisandro Dalcin if (!dlhandle) { 68ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 69ebd79076SLisandro Dalcin PetscErrorCode ierr; 70ebd79076SLisandro Dalcin DWORD erc; 71b3bb0f5eSLisandro Dalcin char *buff = NULL; 72ebd79076SLisandro Dalcin erc = GetLastError(); 73ebd79076SLisandro Dalcin FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 74*e4d177b5SBarry Smith PETSC_NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,PETSC_NULL); 7530b327c4SMatthew G Knepley ierr = PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,__SDIR__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT, 76be1c6ad7SLisandro Dalcin "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff); 77ebd79076SLisandro Dalcin LocalFree(buff); 78ebd79076SLisandro Dalcin PetscFunctionReturn(ierr); 79ebd79076SLisandro Dalcin #else 80e32f2f54SBarry 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"); 81ebd79076SLisandro Dalcin #endif 82ebd79076SLisandro Dalcin } 835673baf8SLisandro Dalcin 845673baf8SLisandro Dalcin /* 855673baf8SLisandro Dalcin --- dlopen --- 865673baf8SLisandro Dalcin */ 87a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN) 88ebd79076SLisandro Dalcin /* 89ebd79076SLisandro Dalcin Mode indicates symbols required by symbol loaded with dlsym() 90ebd79076SLisandro Dalcin are only loaded when required (not all together) also indicates 91ebd79076SLisandro Dalcin symbols required can be contained in other libraries also opened 92ebd79076SLisandro Dalcin with dlopen() 93ebd79076SLisandro Dalcin */ 94be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY) 95be1c6ad7SLisandro Dalcin dlflags1 = RTLD_LAZY; 96be1c6ad7SLisandro Dalcin #endif 97ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW) 98*e4d177b5SBarry Smith if (mode & PETSC_DL_NOW) 99be1c6ad7SLisandro Dalcin 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) 105*e4d177b5SBarry Smith if (mode & PETSC_DL_LOCAL) 106b3bb0f5eSLisandro Dalcin dlflags2 = RTLD_LOCAL; 107b3bb0f5eSLisandro Dalcin #endif 108be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 109be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 110be1c6ad7SLisandro Dalcin #endif 111be1c6ad7SLisandro Dalcin dlhandle = dlopen(name,dlflags1|dlflags2); 112ebd79076SLisandro Dalcin if (!dlhandle) { 113ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 114ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 115ebd79076SLisandro Dalcin #else 116ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 117ebd79076SLisandro Dalcin #endif 118be015529SBarry 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); 119ebd79076SLisandro Dalcin } 1205673baf8SLisandro Dalcin 1215673baf8SLisandro Dalcin /* 1225673baf8SLisandro Dalcin --- unimplemented --- 1235673baf8SLisandro Dalcin */ 124ebd79076SLisandro Dalcin #else 125e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 126ebd79076SLisandro Dalcin #endif 127ebd79076SLisandro Dalcin 128ebd79076SLisandro Dalcin *handle = (PetscDLHandle) dlhandle; 129ebd79076SLisandro Dalcin PetscFunctionReturn(0); 130ebd79076SLisandro Dalcin } 131ebd79076SLisandro Dalcin 132ebd79076SLisandro Dalcin 133ebd79076SLisandro Dalcin #undef __FUNCT__ 134ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLClose" 135ebd79076SLisandro Dalcin /*@C 136b235ab32SBarry Smith PetscDLClose - closes a dynamic library 137b235ab32SBarry Smith 138b235ab32SBarry Smith Not Collective 139b235ab32SBarry Smith 140b235ab32SBarry Smith Input Parameter: 141b235ab32SBarry Smith . handle - the handle for the library obtained with PetscDLOpen() 142b235ab32SBarry Smith 143b235ab32SBarry Smith Level: developer 144ebd79076SLisandro Dalcin @*/ 1457087cfbeSBarry Smith PetscErrorCode PetscDLClose(PetscDLHandle *handle) 146ebd79076SLisandro Dalcin { 147ebd79076SLisandro Dalcin 148ebd79076SLisandro Dalcin PetscFunctionBegin; 149ebd79076SLisandro Dalcin PetscValidPointer(handle,1); 150ebd79076SLisandro Dalcin 1515673baf8SLisandro Dalcin /* 1525673baf8SLisandro Dalcin --- FreeLibrary --- 1535673baf8SLisandro Dalcin */ 154ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 155be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY) 1568e049581SJed Brown if (FreeLibrary((dlhandle_t)*handle) == 0) { 1575673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR) 158b3bb0f5eSLisandro Dalcin char *buff = NULL; 159a21658a3SLisandro Dalcin DWORD erc = GetLastError(); 160*e4d177b5SBarry Smith FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,PETSC_NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,PETSC_NULL); 1615673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 1625673baf8SLisandro Dalcin LocalFree(buff); 1635673baf8SLisandro Dalcin #else 1645673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 1655673baf8SLisandro Dalcin #endif 1665673baf8SLisandro Dalcin } 167be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */ 168ebd79076SLisandro Dalcin 1695673baf8SLisandro Dalcin /* 1705673baf8SLisandro Dalcin --- dclose --- 1715673baf8SLisandro Dalcin */ 172ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 173a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE) 174be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 175be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 176be1c6ad7SLisandro Dalcin #endif 1778e049581SJed Brown if (dlclose((dlhandle_t)*handle) < 0) { 178ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 179ebd79076SLisandro Dalcin const char *errmsg = dlerror(); 180ebd79076SLisandro Dalcin #else 181ebd79076SLisandro Dalcin const char *errmsg = "unavailable"; 182ebd79076SLisandro Dalcin #endif 1835673baf8SLisandro Dalcin PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 184ebd79076SLisandro Dalcin } 185a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */ 1865673baf8SLisandro Dalcin 1875673baf8SLisandro Dalcin /* 1885673baf8SLisandro Dalcin --- unimplemented --- 1895673baf8SLisandro Dalcin */ 190ebd79076SLisandro Dalcin #else 191e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 192ebd79076SLisandro Dalcin #endif 193ebd79076SLisandro Dalcin 194ebd79076SLisandro Dalcin *handle = PETSC_NULL; 195ebd79076SLisandro Dalcin 196ebd79076SLisandro Dalcin PetscFunctionReturn(0); 197ebd79076SLisandro Dalcin } 198ebd79076SLisandro Dalcin 199ebd79076SLisandro Dalcin #undef __FUNCT__ 200ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLSym" 201ebd79076SLisandro Dalcin /*@C 202b235ab32SBarry Smith PetscDLSym - finds a symbol in a dynamic library 203b235ab32SBarry Smith 204b235ab32SBarry Smith Not Collective 205b235ab32SBarry Smith 206b235ab32SBarry Smith Input Parameters: 2077c62f5d3SDmitry Karpeev + handle - obtained with PetscDLOpen() or PETSC_NULL 208b235ab32SBarry Smith - symbol - name of symbol 209b235ab32SBarry Smith 210b235ab32SBarry Smith Output Parameter: 211*e4d177b5SBarry Smith . value - pointer to the function, PETSC_NULL if not found 212b235ab32SBarry Smith 213b235ab32SBarry Smith Level: developer 214b235ab32SBarry Smith 2157c62f5d3SDmitry Karpeev Notes: 2167c62f5d3SDmitry Karpeev If handle is PETSC_NULL, the symbol is looked for in the main executable's dynamic symbol table. 2177c62f5d3SDmitry Karpeev In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 2187c62f5d3SDmitry Karpeev systems this requires platform-specific linker flags. 2197c62f5d3SDmitry Karpeev 220ebd79076SLisandro Dalcin @*/ 2217087cfbeSBarry Smith PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 222ebd79076SLisandro Dalcin { 2238e049581SJed Brown PETSC_UNUSED dlhandle_t dlhandle; 2246ea75d68SLisandro Dalcin dlsymbol_t dlsymbol; 225ebd79076SLisandro Dalcin 226ebd79076SLisandro Dalcin PetscValidCharPointer(symbol,2); 227ebd79076SLisandro Dalcin PetscValidPointer(value,3); 228ebd79076SLisandro Dalcin 229be1c6ad7SLisandro Dalcin dlhandle = (dlhandle_t) 0; 2306ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) 0; 231a21658a3SLisandro Dalcin *value = (void *) 0; 232ebd79076SLisandro Dalcin 2335673baf8SLisandro Dalcin /* 2345673baf8SLisandro Dalcin --- GetProcAddress --- 2355673baf8SLisandro Dalcin */ 236a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 237a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS) 238*e4d177b5SBarry Smith if (handle) dlhandle = (dlhandle_t) handle; 239*e4d177b5SBarry Smith else dlhandle = (dlhandle_t) GetCurrentProcess(); 2406ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 241a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR) 242a21658a3SLisandro Dalcin SetLastError((DWORD)0); /* clear any previous error */ 243a21658a3SLisandro Dalcin #endif 244a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */ 2455673baf8SLisandro Dalcin 2465673baf8SLisandro Dalcin /* 2475673baf8SLisandro Dalcin --- dlsym --- 2485673baf8SLisandro Dalcin */ 249ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) 250a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM) 2517d421530SBarry Smith if (handle) { 252be1c6ad7SLisandro Dalcin dlhandle = (dlhandle_t) handle; 2537d421530SBarry Smith } else { 2547c62f5d3SDmitry Karpeev 255bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 2567c62f5d3SDmitry Karpeev /* Attempt to retrieve the main executable's dlhandle. */ 2577c62f5d3SDmitry Karpeev { int dlflags1 = 0, dlflags2 = 0; 2587c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY) 2597c62f5d3SDmitry Karpeev dlflags1 = RTLD_LAZY; 2607c62f5d3SDmitry Karpeev #endif 2617c62f5d3SDmitry Karpeev if (!dlflags1) { 2627c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW) 2637c62f5d3SDmitry Karpeev dlflags1 = RTLD_NOW; 2647c62f5d3SDmitry Karpeev #endif 2657c62f5d3SDmitry Karpeev } 2667c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL) 2677c62f5d3SDmitry Karpeev dlflags2 = RTLD_LOCAL; 2687c62f5d3SDmitry Karpeev #endif 2697c62f5d3SDmitry Karpeev if (!dlflags2) { 2707c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL) 2717c62f5d3SDmitry Karpeev dlflags2 = RTLD_GLOBAL; 2727c62f5d3SDmitry Karpeev #endif 2737c62f5d3SDmitry Karpeev } 2747c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 275cae2f346SBarry Smith if (!(PETSC_RUNNING_ON_VALGRIND)) { 2767bb14e67SBarry Smith dlerror(); /* clear any previous error; valgrind does not like this */ 2777bb14e67SBarry Smith } 2787bb14e67SBarry Smith #endif 2797c62f5d3SDmitry Karpeev /* Attempt to open the main executable as a dynamic library. */ 2807d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT) 2817d421530SBarry Smith dlhandle = RTLD_DEFAULT; 2827d421530SBarry Smith #else 2837c62f5d3SDmitry Karpeev dlhandle = dlopen(0, dlflags1|dlflags2); 2847c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR) 2854956914eSSatish Balay { const char *e = (const char*) dlerror(); 2867d421530SBarry 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); 2877c62f5d3SDmitry Karpeev } 2887c62f5d3SDmitry Karpeev #endif 2897d421530SBarry Smith #endif 290be1c6ad7SLisandro Dalcin } 291be1c6ad7SLisandro Dalcin #endif 292fcfd50ebSBarry Smith #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */ 2934956914eSSatish Balay } 294be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR) 295be1c6ad7SLisandro Dalcin dlerror(); /* clear any previous error */ 296be1c6ad7SLisandro Dalcin #endif 2976ea75d68SLisandro Dalcin dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 2985673baf8SLisandro Dalcin /* 2995673baf8SLisandro Dalcin --- unimplemented --- 3005673baf8SLisandro Dalcin */ 301ebd79076SLisandro Dalcin #else 302e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 303ebd79076SLisandro Dalcin #endif 304ebd79076SLisandro Dalcin 3056ea75d68SLisandro Dalcin *value = *((void**)&dlsymbol); 306ebd79076SLisandro Dalcin 3072d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS) 3082d53ad75SBarry Smith if (*value) { 3092d53ad75SBarry Smith PetscErrorCode ierr; 3102d53ad75SBarry Smith ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr); 3112d53ad75SBarry Smith } 3122d53ad75SBarry Smith #endif 3132d53ad75SBarry Smith return(0); 314ebd79076SLisandro Dalcin } 315