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