1 2 /* 3 Low-level routines for managing dynamic link libraries (DLLs). 4 */ 5 6 #include <petsc-private/petscimpl.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 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 (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW; 99 #endif 100 #if defined(PETSC_HAVE_RTLD_GLOBAL) 101 dlflags2 = RTLD_GLOBAL; 102 #endif 103 #if defined(PETSC_HAVE_RTLD_LOCAL) 104 if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL; 105 #endif 106 #if defined(PETSC_HAVE_DLERROR) 107 dlerror(); /* clear any previous error */ 108 #endif 109 dlhandle = dlopen(name,dlflags1|dlflags2); 110 if (!dlhandle) { 111 #if defined(PETSC_HAVE_DLERROR) 112 const char *errmsg = dlerror(); 113 #else 114 const char *errmsg = "unavailable"; 115 #endif 116 SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n %s\n Error message from dlopen() %s\n",name,errmsg); 117 } 118 119 /* 120 --- unimplemented --- 121 */ 122 #else 123 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 124 #endif 125 126 *handle = (PetscDLHandle) dlhandle; 127 PetscFunctionReturn(0); 128 } 129 130 131 #undef __FUNCT__ 132 #define __FUNCT__ "PetscDLClose" 133 /*@C 134 PetscDLClose - closes a dynamic library 135 136 Not Collective 137 138 Input Parameter: 139 . handle - the handle for the library obtained with PetscDLOpen() 140 141 Level: developer 142 @*/ 143 PetscErrorCode PetscDLClose(PetscDLHandle *handle) 144 { 145 146 PetscFunctionBegin; 147 PetscValidPointer(handle,1); 148 149 /* 150 --- FreeLibrary --- 151 */ 152 #if defined(PETSC_HAVE_WINDOWS_H) 153 #if defined(PETSC_HAVE_FREELIBRARY) 154 if (FreeLibrary((dlhandle_t)*handle) == 0) { 155 #if defined(PETSC_HAVE_GETLASTERROR) 156 char *buff = NULL; 157 DWORD erc = GetLastError(); 158 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL); 159 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n",buff); 160 LocalFree(buff); 161 #else 162 PetscErrorPrintf("Error closing dynamic library:\n Error message from FreeLibrary() %s\n","unavailable"); 163 #endif 164 } 165 #endif /* !PETSC_HAVE_FREELIBRARY */ 166 167 /* 168 --- dclose --- 169 */ 170 #elif defined(PETSC_HAVE_DLFCN_H) 171 #if defined(PETSC_HAVE_DLCLOSE) 172 #if defined(PETSC_HAVE_DLERROR) 173 dlerror(); /* clear any previous error */ 174 #endif 175 if (dlclose((dlhandle_t)*handle) < 0) { 176 #if defined(PETSC_HAVE_DLERROR) 177 const char *errmsg = dlerror(); 178 #else 179 const char *errmsg = "unavailable"; 180 #endif 181 PetscErrorPrintf("Error closing dynamic library:\n Error message from dlclose() %s\n", errmsg); 182 } 183 #endif /* !PETSC_HAVE_DLCLOSE */ 184 185 /* 186 --- unimplemented --- 187 */ 188 #else 189 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 190 #endif 191 192 *handle = NULL; 193 PetscFunctionReturn(0); 194 } 195 196 #undef __FUNCT__ 197 #define __FUNCT__ "PetscDLSym" 198 /*@C 199 PetscDLSym - finds a symbol in a dynamic library 200 201 Not Collective 202 203 Input Parameters: 204 + handle - obtained with PetscDLOpen() or NULL 205 - symbol - name of symbol 206 207 Output Parameter: 208 . value - pointer to the function, NULL if not found 209 210 Level: developer 211 212 Notes: 213 If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table. 214 In order to be dynamically loadable, the symbol has to be exported as such. On many UNIX-like 215 systems this requires platform-specific linker flags. 216 217 @*/ 218 PetscErrorCode PetscDLSym(PetscDLHandle handle,const char symbol[],void **value) 219 { 220 PETSC_UNUSED dlhandle_t dlhandle; 221 dlsymbol_t dlsymbol; 222 223 PetscValidCharPointer(symbol,2); 224 PetscValidPointer(value,3); 225 226 dlhandle = (dlhandle_t) 0; 227 dlsymbol = (dlsymbol_t) 0; 228 *value = (void*) 0; 229 230 /* 231 --- GetProcAddress --- 232 */ 233 #if defined(PETSC_HAVE_WINDOWS_H) 234 #if defined(PETSC_HAVE_GETPROCADDRESS) 235 if (handle) dlhandle = (dlhandle_t) handle; 236 else dlhandle = (dlhandle_t) GetCurrentProcess(); 237 dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol); 238 #if defined(PETSC_HAVE_SETLASTERROR) 239 SetLastError((DWORD)0); /* clear any previous error */ 240 #endif 241 #endif /* !PETSC_HAVE_GETPROCADDRESS */ 242 243 /* 244 --- dlsym --- 245 */ 246 #elif defined(PETSC_HAVE_DLFCN_H) 247 #if defined(PETSC_HAVE_DLSYM) 248 if (handle) dlhandle = (dlhandle_t) handle; 249 else { 250 251 #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES) 252 /* Attempt to retrieve the main executable's dlhandle. */ 253 { int dlflags1 = 0, dlflags2 = 0; 254 #if defined(PETSC_HAVE_RTLD_LAZY) 255 dlflags1 = RTLD_LAZY; 256 #endif 257 if (!dlflags1) { 258 #if defined(PETSC_HAVE_RTLD_NOW) 259 dlflags1 = RTLD_NOW; 260 #endif 261 } 262 #if defined(PETSC_HAVE_RTLD_LOCAL) 263 dlflags2 = RTLD_LOCAL; 264 #endif 265 if (!dlflags2) { 266 #if defined(PETSC_HAVE_RTLD_GLOBAL) 267 dlflags2 = RTLD_GLOBAL; 268 #endif 269 } 270 #if defined(PETSC_HAVE_DLERROR) 271 if (!(PETSC_RUNNING_ON_VALGRIND)) { 272 dlerror(); /* clear any previous error; valgrind does not like this */ 273 } 274 #endif 275 /* Attempt to open the main executable as a dynamic library. */ 276 #if defined(PETSC_HAVE_RTDL_DEFAULT) 277 dlhandle = RTLD_DEFAULT; 278 #else 279 dlhandle = dlopen(0, dlflags1|dlflags2); 280 #if defined(PETSC_HAVE_DLERROR) 281 { const char *e = (const char*) dlerror(); 282 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); 283 } 284 #endif 285 #endif 286 } 287 #endif 288 #endif /* PETSC_HAVE_DLOPEN && PETSC_USE_DYNAMIC_LIBRARIES */ 289 } 290 #if defined(PETSC_HAVE_DLERROR) 291 dlerror(); /* clear any previous error */ 292 #endif 293 dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol); 294 /* 295 --- unimplemented --- 296 */ 297 #else 298 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform"); 299 #endif 300 301 *value = *((void**)&dlsymbol); 302 303 #if defined(PETSC_SERIALIZE_FUNCTIONS) 304 if (*value) { 305 PetscErrorCode ierr; 306 ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr); 307 } 308 #endif 309 return(0); 310 } 311