1 2 /* 3 Low-level routines for managing dynamic link libraries (DLLs). 4 */ 5 6 #include "../src/sys/dll/dlimpl.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 - flags - options on how to open library 41 42 Output Parameter: 43 . handle 44 45 Level: developer 46 47 @*/ 48 PetscErrorCode PetscDLOpen(const char name[],int flags,PetscDLHandle *handle) 49 { 50 int dlflags1,dlflags2; 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 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,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 (flags & 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 (flags & 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 130 PetscFunctionReturn(0); 131 } 132 133 134 #undef __FUNCT__ 135 #define __FUNCT__ "PetscDLClose" 136 /*@C 137 PetscDLClose - closes a dynamic library 138 139 Not Collective 140 141 Input Parameter: 142 . handle - the handle for the library obtained with PetscDLOpen() 143 144 Level: developer 145 @*/ 146 PetscErrorCode PetscDLClose(PetscDLHandle *handle) 147 { 148 dlhandle_t dlhandle; 149 150 PetscFunctionBegin; 151 PetscValidPointer(handle,1); 152 153 dlhandle = (dlhandle_t) *handle; 154 155 /* 156 --- FreeLibrary --- 157 */ 158 #if defined(PETSC_HAVE_WINDOWS_H) 159 #if defined(PETSC_HAVE_FREELIBRARY) 160 if (FreeLibrary(dlhandle) == 0) { 161 #if defined(PETSC_HAVE_GETLASTERROR) 162 char *buff = NULL; 163 DWORD erc = GetLastError(); 164 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, 165 NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 166 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 167 LocalFree(buff); 168 #else 169 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 170 #endif 171 } 172 #endif /* !PETSC_HAVE_FREELIBRARY */ 173 174 /* 175 --- dclose --- 176 */ 177 #elif defined(PETSC_HAVE_DLFCN_H) 178 #if defined(PETSC_HAVE_DLCLOSE) 179 #if defined(PETSC_HAVE_DLERROR) 180 dlerror(); /* clear any previous error */ 181 #endif 182 if (dlclose(dlhandle) < 0) { 183 #if defined(PETSC_HAVE_DLERROR) 184 const char *errmsg = dlerror(); 185 #else 186 const char *errmsg = "unavailable"; 187 #endif 188 PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 189 } 190 #endif /* !PETSC_HAVE_DLCLOSE */ 191 192 /* 193 --- unimplemented --- 194 */ 195 #else 196 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 197 #endif 198 199 *handle = PETSC_NULL; 200 201 PetscFunctionReturn(0); 202 } 203 204 #if defined(PETSC_HAVE_VALGRIND) 205 #include <valgrind/valgrind.h> 206 #endif 207 208 #undef __FUNCT__ 209 #define __FUNCT__ "PetscDLSym" 210 /*@C 211 PetscDLSym - finds a symbol in a dynamic library 212 213 Not Collective 214 215 Input Parameters: 216 + handle - obtained with PetscDLOpen() or PETSC_NULL 217 - symbol - name of symbol 218 219 Output Parameter: 220 . value - pointer to the function 221 222 Level: developer 223 224 Notes: 225 If handle is PETSC_NULL, the symbol is looked for in the main executable's dynamic symbol table. 226 In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 227 systems this requires platform-specific linker flags. 228 229 @*/ 230 PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 231 { 232 dlhandle_t dlhandle; 233 dlsymbol_t dlsymbol; 234 235 PetscFunctionBegin; 236 PetscValidCharPointer(symbol,2); 237 PetscValidPointer(value,3); 238 239 dlhandle = (dlhandle_t) 0; 240 dlsymbol = (dlsymbol_t) 0; 241 242 *value = (void *) 0; 243 244 /* 245 --- GetProcAddress --- 246 */ 247 #if defined(PETSC_HAVE_WINDOWS_H) 248 #if defined(PETSC_HAVE_GETPROCADDRESS) 249 if (handle != PETSC_NULL) 250 dlhandle = (dlhandle_t) handle; 251 else 252 dlhandle = (dlhandle_t) GetCurrentProcess(); 253 dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 254 #if defined(PETSC_HAVE_SETLASTERROR) 255 SetLastError((DWORD)0); /* clear any previous error */ 256 #endif 257 #endif /* !PETSC_HAVE_GETPROCADDRESS */ 258 259 /* 260 --- dlsym --- 261 */ 262 #elif defined(PETSC_HAVE_DLFCN_H) 263 #if defined(PETSC_HAVE_DLSYM) 264 if (handle != PETSC_NULL) { 265 dlhandle = (dlhandle_t) handle; 266 } 267 else { 268 dlhandle = (dlhandle_t) 0; 269 270 #if defined(PETSC_HAVE_DLOPEN) 271 /* Attempt to retrieve the main executable's dlhandle. */ 272 { int dlflags1 = 0, dlflags2 = 0; 273 #if defined(PETSC_HAVE_RTLD_LAZY) 274 dlflags1 = RTLD_LAZY; 275 #endif 276 if(!dlflags1) { 277 #if defined(PETSC_HAVE_RTLD_NOW) 278 dlflags1 = RTLD_NOW; 279 #endif 280 } 281 #if defined(PETSC_HAVE_RTLD_LOCAL) 282 dlflags2 = RTLD_LOCAL; 283 #endif 284 if(!dlflags2) { 285 #if defined(PETSC_HAVE_RTLD_GLOBAL) 286 dlflags2 = RTLD_GLOBAL; 287 #endif 288 } 289 #if defined(PETSC_HAVE_DLERROR) 290 #if defined(PETSC_HAVE_VALGRIND) 291 if (!(RUNNING_ON_VALGRIND)) { 292 #endif 293 dlerror(); /* clear any previous error; valgrind does not like this */ 294 #if defined(PETSC_HAVE_VALGRIND) 295 } 296 #endif 297 #endif 298 /* Attempt to open the main executable as a dynamic library. */ 299 dlhandle = dlopen(0, dlflags1|dlflags2); 300 } 301 #if defined(PETSC_HAVE_DLERROR) 302 { const char *e = (const char*) dlerror(); 303 if(e){ 304 SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error opening main executable as a dynamic library:\n Error message from dlopen(): '%s'\n", e); 305 } 306 } 307 #endif 308 #endif /* PETSC_HAVE_DLOPEN */ 309 } 310 #if defined(PETSC_HAVE_DLERROR) 311 dlerror(); /* clear any previous error */ 312 #endif 313 dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 314 #if defined(PETSC_HAVE_DLERROR) 315 /* e = dlerror(); */ 316 /* if(e){ */ 317 /* SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Error obtaining symbol '%s' from dynamic library:\n Error message from dlsym(): '%s'\n", symbol, e); */ 318 /* } */ 319 #endif 320 #endif /* !PETSC_HAVE_DLSYM */ 321 322 /* 323 --- unimplemented --- 324 */ 325 #else 326 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 327 #endif 328 329 *value = *((void**)&dlsymbol); 330 331 PetscFunctionReturn(0); 332 } 333