1 2 /* 3 Low-level routines for managing dynamic link libraries (DLLs). 4 */ 5 6 #include <petsc-private/petscimpl.h> 7 #include <petscvalgrind.h> 8 9 /* XXX Should be done better !!!*/ 10 #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 11 #undef PETSC_HAVE_WINDOWS_H 12 #undef PETSC_HAVE_DLFCN_H 13 #endif 14 15 #if defined(PETSC_HAVE_WINDOWS_H) 16 #include <windows.h> 17 #elif defined(PETSC_HAVE_DLFCN_H) 18 #include <dlfcn.h> 19 #endif 20 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 31 32 #undef __FUNCT__ 33 #define __FUNCT__ "PetscDLOpen" 34 /*@C 35 PetscDLOpen - opens dynamic library 36 37 Not Collective 38 39 Input Parameters: 40 + name - name of library 41 - mode - options on how to open library 42 43 Output Parameter: 44 . handle 45 46 Level: developer 47 48 @*/ 49 PetscErrorCode PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle) 50 { 51 PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */ 52 dlhandle_t dlhandle; 53 54 PetscFunctionBegin; 55 PetscValidCharPointer(name,1); 56 PetscValidPointer(handle,3); 57 58 dlflags1 = 0; 59 dlflags2 = 0; 60 dlhandle = (dlhandle_t) 0; 61 *handle = (PetscDLHandle) 0; 62 63 /* 64 --- LoadLibrary --- 65 */ 66 #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY) 67 dlhandle = LoadLibrary(name); 68 if (!dlhandle) { 69 #if defined(PETSC_HAVE_GETLASTERROR) 70 PetscErrorCode ierr; 71 DWORD erc; 72 char *buff = NULL; 73 erc = GetLastError(); 74 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 75 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 76 ierr = PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT, 77 "Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,buff); 78 LocalFree(buff); 79 PetscFunctionReturn(ierr); 80 #else 81 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from LoadLibrary() %s\n",name,"unavailable"); 82 #endif 83 } 84 85 /* 86 --- dlopen --- 87 */ 88 #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN) 89 /* 90 Mode indicates symbols required by symbol loaded with dlsym() 91 are only loaded when required (not all together) also indicates 92 symbols required can be contained in other libraries also opened 93 with dlopen() 94 */ 95 #if defined(PETSC_HAVE_RTLD_LAZY) 96 dlflags1 = RTLD_LAZY; 97 #endif 98 #if defined(PETSC_HAVE_RTLD_NOW) 99 if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW; 100 #endif 101 #if defined(PETSC_HAVE_RTLD_GLOBAL) 102 dlflags2 = RTLD_GLOBAL; 103 #endif 104 #if defined(PETSC_HAVE_RTLD_LOCAL) 105 if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL; 106 #endif 107 #if defined(PETSC_HAVE_DLERROR) 108 dlerror(); /* clear any previous error */ 109 #endif 110 dlhandle = dlopen(name,dlflags1|dlflags2); 111 if (!dlhandle) { 112 #if defined(PETSC_HAVE_DLERROR) 113 const char *errmsg = dlerror(); 114 #else 115 const char *errmsg = "unavailable"; 116 #endif 117 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg); 118 } 119 120 /* 121 --- unimplemented --- 122 */ 123 #else 124 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 125 #endif 126 127 *handle = (PetscDLHandle) dlhandle; 128 PetscFunctionReturn(0); 129 } 130 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PetscDLClose" 134 /*@C 135 PetscDLClose - closes a dynamic library 136 137 Not Collective 138 139 Input Parameter: 140 . handle - the handle for the library obtained with PetscDLOpen() 141 142 Level: developer 143 @*/ 144 PetscErrorCode PetscDLClose(PetscDLHandle *handle) 145 { 146 147 PetscFunctionBegin; 148 PetscValidPointer(handle,1); 149 150 /* 151 --- FreeLibrary --- 152 */ 153 #if defined(PETSC_HAVE_WINDOWS_H) 154 #if defined(PETSC_HAVE_FREELIBRARY) 155 if (FreeLibrary((dlhandle_t)*handle) == 0) { 156 #if defined(PETSC_HAVE_GETLASTERROR) 157 char *buff = NULL; 158 DWORD erc = GetLastError(); 159 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 160 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 161 LocalFree(buff); 162 #else 163 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 164 #endif 165 } 166 #endif /* !PETSC_HAVE_FREELIBRARY */ 167 168 /* 169 --- dclose --- 170 */ 171 #elif defined(PETSC_HAVE_DLFCN_H) 172 #if defined(PETSC_HAVE_DLCLOSE) 173 #if defined(PETSC_HAVE_DLERROR) 174 dlerror(); /* clear any previous error */ 175 #endif 176 if (dlclose((dlhandle_t)*handle) < 0) { 177 #if defined(PETSC_HAVE_DLERROR) 178 const char *errmsg = dlerror(); 179 #else 180 const char *errmsg = "unavailable"; 181 #endif 182 PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 183 } 184 #endif /* !PETSC_HAVE_DLCLOSE */ 185 186 /* 187 --- unimplemented --- 188 */ 189 #else 190 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 191 #endif 192 193 *handle = NULL; 194 PetscFunctionReturn(0); 195 } 196 197 #undef __FUNCT__ 198 #define __FUNCT__ "PetscDLSym" 199 /*@C 200 PetscDLSym - finds a symbol in a dynamic library 201 202 Not Collective 203 204 Input Parameters: 205 + handle - obtained with PetscDLOpen() or NULL 206 - symbol - name of symbol 207 208 Output Parameter: 209 . value - pointer to the function, NULL if not found 210 211 Level: developer 212 213 Notes: 214 If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table. 215 In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 216 systems this requires platform-specific linker flags. 217 218 @*/ 219 PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 220 { 221 PETSC_UNUSED dlhandle_t dlhandle; 222 dlsymbol_t dlsymbol; 223 224 PetscValidCharPointer(symbol,2); 225 PetscValidPointer(value,3); 226 227 dlhandle = (dlhandle_t) 0; 228 dlsymbol = (dlsymbol_t) 0; 229 *value = (void*) 0; 230 231 /* 232 --- GetProcAddress --- 233 */ 234 #if defined(PETSC_HAVE_WINDOWS_H) 235 #if defined(PETSC_HAVE_GETPROCADDRESS) 236 if (handle) dlhandle = (dlhandle_t) handle; 237 else dlhandle = (dlhandle_t) GetCurrentProcess(); 238 dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 239 #if defined(PETSC_HAVE_SETLASTERROR) 240 SetLastError((DWORD)0); /* clear any previous error */ 241 #endif 242 #endif /* !PETSC_HAVE_GETPROCADDRESS */ 243 244 /* 245 --- dlsym --- 246 */ 247 #elif defined(PETSC_HAVE_DLFCN_H) 248 #if defined(PETSC_HAVE_DLSYM) 249 if (handle) dlhandle = (dlhandle_t) handle; 250 else { 251 252 #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 253 /* Attempt to retrieve the main executable's dlhandle. */ 254 { int dlflags1 = 0, dlflags2 = 0; 255 #if defined(PETSC_HAVE_RTLD_LAZY) 256 dlflags1 = RTLD_LAZY; 257 #endif 258 if (!dlflags1) { 259 #if defined(PETSC_HAVE_RTLD_NOW) 260 dlflags1 = RTLD_NOW; 261 #endif 262 } 263 #if defined(PETSC_HAVE_RTLD_LOCAL) 264 dlflags2 = RTLD_LOCAL; 265 #endif 266 if (!dlflags2) { 267 #if defined(PETSC_HAVE_RTLD_GLOBAL) 268 dlflags2 = RTLD_GLOBAL; 269 #endif 270 } 271 #if defined(PETSC_HAVE_DLERROR) 272 if (!(PETSC_RUNNING_ON_VALGRIND)) { 273 dlerror(); /* clear any previous error; valgrind does not like this */ 274 } 275 #endif 276 /* Attempt to open the main executable as a dynamic library. */ 277 #if defined(PETSC_HAVE_RTDL_DEFAULT) 278 dlhandle = RTLD_DEFAULT; 279 #else 280 dlhandle = dlopen(0, dlflags1|dlflags2); 281 #if defined(PETSC_HAVE_DLERROR) 282 { const char *e = (const char*) dlerror(); 283 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); 284 } 285 #endif 286 #endif 287 } 288 #endif 289 #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */ 290 } 291 #if defined(PETSC_HAVE_DLERROR) 292 dlerror(); /* clear any previous error */ 293 #endif 294 dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 295 /* 296 --- unimplemented --- 297 */ 298 #else 299 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 300 #endif 301 302 *value = *((void**)&dlsymbol); 303 304 #if defined(PETSC_SERIALIZE_FUNCTIONS) 305 if (*value) { 306 PetscErrorCode ierr; 307 ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr); 308 } 309 #endif 310 return(0); 311 } 312