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