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