xref: /petsc/src/sys/dll/dlimpl.c (revision fbfcfee5110779e3d6a9465ca0a2e0f9a1a6e5e3)
17d0a6c19SBarry Smith 
2ebd79076SLisandro Dalcin /*
3ebd79076SLisandro Dalcin    Low-level routines for managing dynamic link libraries (DLLs).
4ebd79076SLisandro Dalcin */
5ebd79076SLisandro Dalcin 
6af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
7022afb99SBarry Smith #include <petscvalgrind.h>
8ebd79076SLisandro Dalcin 
9ebd79076SLisandro Dalcin /* XXX Should be done better !!!*/
10be1c6ad7SLisandro Dalcin #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
11ebd79076SLisandro Dalcin #undef PETSC_HAVE_WINDOWS_H
12ebd79076SLisandro Dalcin #undef PETSC_HAVE_DLFCN_H
13ebd79076SLisandro Dalcin #endif
14ebd79076SLisandro Dalcin 
15ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
16ebd79076SLisandro Dalcin #include <windows.h>
17be1c6ad7SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
18ebd79076SLisandro Dalcin #include <dlfcn.h>
19ebd79076SLisandro Dalcin #endif
20ebd79076SLisandro Dalcin 
21ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
22ebd79076SLisandro Dalcin typedef HMODULE dlhandle_t;
236ea75d68SLisandro Dalcin typedef FARPROC dlsymbol_t;
24ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
25ebd79076SLisandro Dalcin typedef void* dlhandle_t;
266ea75d68SLisandro Dalcin typedef void* dlsymbol_t;
27ebd79076SLisandro Dalcin #else
28ebd79076SLisandro Dalcin typedef void* dlhandle_t;
296ea75d68SLisandro Dalcin typedef void* dlsymbol_t;
30ebd79076SLisandro Dalcin #endif
31ebd79076SLisandro Dalcin 
32ebd79076SLisandro Dalcin /*@C
33b235ab32SBarry Smith    PetscDLOpen - opens dynamic library
34b235ab32SBarry Smith 
35b235ab32SBarry Smith    Not Collective
36b235ab32SBarry Smith 
37b235ab32SBarry Smith    Input Parameters:
38b235ab32SBarry Smith +    name - name of library
39e4d177b5SBarry Smith -    mode - options on how to open library
40b235ab32SBarry Smith 
41b235ab32SBarry Smith    Output Parameter:
42b235ab32SBarry Smith .    handle
43b235ab32SBarry Smith 
44b235ab32SBarry Smith    Level: developer
45b235ab32SBarry Smith 
46ebd79076SLisandro Dalcin @*/
47e4d177b5SBarry Smith PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
48ebd79076SLisandro Dalcin {
498e049581SJed Brown   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
50ebd79076SLisandro Dalcin   dlhandle_t       dlhandle;
51ebd79076SLisandro Dalcin 
52ebd79076SLisandro Dalcin   PetscFunctionBegin;
53ebd79076SLisandro Dalcin   PetscValidCharPointer(name,1);
54ebd79076SLisandro Dalcin   PetscValidPointer(handle,3);
55ebd79076SLisandro Dalcin 
56be1c6ad7SLisandro Dalcin   dlflags1 = 0;
57be1c6ad7SLisandro Dalcin   dlflags2 = 0;
585673baf8SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
59be1c6ad7SLisandro Dalcin   *handle  = (PetscDLHandle) 0;
60ebd79076SLisandro Dalcin 
615673baf8SLisandro Dalcin   /*
625673baf8SLisandro Dalcin      --- LoadLibrary ---
635673baf8SLisandro Dalcin   */
64be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
65be1c6ad7SLisandro Dalcin   dlhandle = LoadLibrary(name);
66ebd79076SLisandro Dalcin   if (!dlhandle) {
67ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
68ebd79076SLisandro Dalcin     PetscErrorCode ierr;
69ebd79076SLisandro Dalcin     DWORD          erc;
70b3bb0f5eSLisandro Dalcin     char           *buff = NULL;
71ebd79076SLisandro Dalcin     erc = GetLastError();
72ebd79076SLisandro Dalcin     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
730298fd71SBarry Smith                   NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
74*fbfcfee5SBarry Smith     ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
75be1c6ad7SLisandro Dalcin                       "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,buff);
76ebd79076SLisandro Dalcin     LocalFree(buff);
77ebd79076SLisandro Dalcin     PetscFunctionReturn(ierr);
78ebd79076SLisandro Dalcin #else
79e32f2f54SBarry Smith     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,"unavailable");
80ebd79076SLisandro Dalcin #endif
81ebd79076SLisandro Dalcin   }
825673baf8SLisandro Dalcin 
835673baf8SLisandro Dalcin   /*
845673baf8SLisandro Dalcin      --- dlopen ---
855673baf8SLisandro Dalcin   */
86a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
87ebd79076SLisandro Dalcin   /*
88ebd79076SLisandro Dalcin       Mode indicates symbols required by symbol loaded with dlsym()
89ebd79076SLisandro Dalcin      are only loaded when required (not all together) also indicates
90ebd79076SLisandro Dalcin      symbols required can be contained in other libraries also opened
91ebd79076SLisandro Dalcin      with dlopen()
92ebd79076SLisandro Dalcin   */
93be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY)
94be1c6ad7SLisandro Dalcin   dlflags1 = RTLD_LAZY;
95be1c6ad7SLisandro Dalcin #endif
96ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW)
97a297a907SKarl Rupp   if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
98ebd79076SLisandro Dalcin #endif
99ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_GLOBAL)
100be1c6ad7SLisandro Dalcin   dlflags2 = RTLD_GLOBAL;
101ebd79076SLisandro Dalcin #endif
102b3bb0f5eSLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LOCAL)
103a297a907SKarl Rupp   if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
104b3bb0f5eSLisandro Dalcin #endif
105be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
106be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
107be1c6ad7SLisandro Dalcin #endif
108be1c6ad7SLisandro Dalcin   dlhandle = dlopen(name,dlflags1|dlflags2);
109ebd79076SLisandro Dalcin   if (!dlhandle) {
110ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
111ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
112ebd79076SLisandro Dalcin #else
113ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
114ebd79076SLisandro Dalcin #endif
115be015529SBarry Smith     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s\n",name,errmsg);
116ebd79076SLisandro Dalcin   }
1175673baf8SLisandro Dalcin 
1185673baf8SLisandro Dalcin   /*
1195673baf8SLisandro Dalcin      --- unimplemented ---
1205673baf8SLisandro Dalcin   */
121ebd79076SLisandro Dalcin #else
122e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
123ebd79076SLisandro Dalcin #endif
124ebd79076SLisandro Dalcin 
125ebd79076SLisandro Dalcin   *handle = (PetscDLHandle) dlhandle;
126ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
127ebd79076SLisandro Dalcin }
128ebd79076SLisandro Dalcin 
129ebd79076SLisandro Dalcin 
130ebd79076SLisandro Dalcin /*@C
131b235ab32SBarry Smith    PetscDLClose -  closes a dynamic library
132b235ab32SBarry Smith 
133b235ab32SBarry Smith    Not Collective
134b235ab32SBarry Smith 
135b235ab32SBarry Smith   Input Parameter:
136b235ab32SBarry Smith .   handle - the handle for the library obtained with PetscDLOpen()
137b235ab32SBarry Smith 
138b235ab32SBarry Smith   Level: developer
139ebd79076SLisandro Dalcin @*/
1407087cfbeSBarry Smith PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
141ebd79076SLisandro Dalcin {
142ebd79076SLisandro Dalcin 
143ebd79076SLisandro Dalcin   PetscFunctionBegin;
144ebd79076SLisandro Dalcin   PetscValidPointer(handle,1);
145ebd79076SLisandro Dalcin 
1465673baf8SLisandro Dalcin   /*
1475673baf8SLisandro Dalcin      --- FreeLibrary ---
1485673baf8SLisandro Dalcin   */
149ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
150be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY)
1518e049581SJed Brown   if (FreeLibrary((dlhandle_t)*handle) == 0) {
1525673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
153b3bb0f5eSLisandro Dalcin     char  *buff = NULL;
154a21658a3SLisandro Dalcin     DWORD erc   = GetLastError();
1550298fd71SBarry Smith     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
1565673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n",buff);
1575673baf8SLisandro Dalcin     LocalFree(buff);
1585673baf8SLisandro Dalcin #else
1595673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n","unavailable");
1605673baf8SLisandro Dalcin #endif
1615673baf8SLisandro Dalcin   }
162be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */
163ebd79076SLisandro Dalcin 
1645673baf8SLisandro Dalcin   /*
1655673baf8SLisandro Dalcin      --- dclose ---
1665673baf8SLisandro Dalcin   */
167ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
168a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE)
169be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
170be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
171be1c6ad7SLisandro Dalcin #endif
1728e049581SJed Brown   if (dlclose((dlhandle_t)*handle) < 0) {
173ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
174ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
175ebd79076SLisandro Dalcin #else
176ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
177ebd79076SLisandro Dalcin #endif
1785673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from dlclose() %s\n", errmsg);
179ebd79076SLisandro Dalcin   }
180a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */
1815673baf8SLisandro Dalcin 
1825673baf8SLisandro Dalcin   /*
1835673baf8SLisandro Dalcin      --- unimplemented ---
1845673baf8SLisandro Dalcin   */
185ebd79076SLisandro Dalcin #else
186e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
187ebd79076SLisandro Dalcin #endif
188ebd79076SLisandro Dalcin 
1890298fd71SBarry Smith   *handle = NULL;
190ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
191ebd79076SLisandro Dalcin }
192ebd79076SLisandro Dalcin 
193ebd79076SLisandro Dalcin /*@C
194b235ab32SBarry Smith    PetscDLSym - finds a symbol in a dynamic library
195b235ab32SBarry Smith 
196b235ab32SBarry Smith    Not Collective
197b235ab32SBarry Smith 
198b235ab32SBarry Smith    Input Parameters:
1990298fd71SBarry Smith +   handle - obtained with PetscDLOpen() or NULL
200b235ab32SBarry Smith -   symbol - name of symbol
201b235ab32SBarry Smith 
202b235ab32SBarry Smith    Output Parameter:
2030298fd71SBarry Smith .   value - pointer to the function, NULL if not found
204b235ab32SBarry Smith 
205b235ab32SBarry Smith    Level: developer
206b235ab32SBarry Smith 
2077c62f5d3SDmitry Karpeev   Notes:
2080298fd71SBarry Smith    If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
2097c62f5d3SDmitry Karpeev    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
2107c62f5d3SDmitry Karpeev    systems this requires platform-specific linker flags.
2117c62f5d3SDmitry Karpeev 
212ebd79076SLisandro Dalcin @*/
2137087cfbeSBarry Smith PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
214ebd79076SLisandro Dalcin {
2158e049581SJed Brown   PETSC_UNUSED dlhandle_t dlhandle;
2166ea75d68SLisandro Dalcin   dlsymbol_t              dlsymbol;
217ebd79076SLisandro Dalcin 
218ebd79076SLisandro Dalcin   PetscValidCharPointer(symbol,2);
219ebd79076SLisandro Dalcin   PetscValidPointer(value,3);
220ebd79076SLisandro Dalcin 
221be1c6ad7SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
2226ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) 0;
223a21658a3SLisandro Dalcin   *value   = (void*) 0;
224ebd79076SLisandro Dalcin 
2255673baf8SLisandro Dalcin   /*
2265673baf8SLisandro Dalcin      --- GetProcAddress ---
2275673baf8SLisandro Dalcin   */
228a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
229a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS)
230e4d177b5SBarry Smith   if (handle) dlhandle = (dlhandle_t) handle;
231e4d177b5SBarry Smith   else dlhandle = (dlhandle_t) GetCurrentProcess();
2326ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
233a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR)
234a21658a3SLisandro Dalcin   SetLastError((DWORD)0); /* clear any previous error */
235a21658a3SLisandro Dalcin #endif
236a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */
2375673baf8SLisandro Dalcin 
2385673baf8SLisandro Dalcin   /*
2395673baf8SLisandro Dalcin      --- dlsym ---
2405673baf8SLisandro Dalcin   */
241ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
242a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM)
243a297a907SKarl Rupp   if (handle) dlhandle = (dlhandle_t) handle;
244a297a907SKarl Rupp   else {
2457c62f5d3SDmitry Karpeev 
246bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
2477c62f5d3SDmitry Karpeev     /* Attempt to retrieve the main executable's dlhandle. */
2487c62f5d3SDmitry Karpeev     { int dlflags1 = 0, dlflags2 = 0;
2497c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY)
2507c62f5d3SDmitry Karpeev       dlflags1 = RTLD_LAZY;
2517c62f5d3SDmitry Karpeev #endif
2527c62f5d3SDmitry Karpeev       if (!dlflags1) {
2537c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW)
2547c62f5d3SDmitry Karpeev         dlflags1 = RTLD_NOW;
2557c62f5d3SDmitry Karpeev #endif
2567c62f5d3SDmitry Karpeev       }
2577c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL)
2587c62f5d3SDmitry Karpeev       dlflags2 = RTLD_LOCAL;
2597c62f5d3SDmitry Karpeev #endif
2607c62f5d3SDmitry Karpeev       if (!dlflags2) {
2617c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL)
2627c62f5d3SDmitry Karpeev         dlflags2 = RTLD_GLOBAL;
2637c62f5d3SDmitry Karpeev #endif
2647c62f5d3SDmitry Karpeev       }
2657c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
266cae2f346SBarry Smith       if (!(PETSC_RUNNING_ON_VALGRIND)) {
2677bb14e67SBarry Smith         dlerror(); /* clear any previous error; valgrind does not like this */
2687bb14e67SBarry Smith       }
2697bb14e67SBarry Smith #endif
2707c62f5d3SDmitry Karpeev       /* Attempt to open the main executable as a dynamic library. */
2717d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT)
2727d421530SBarry Smith       dlhandle = RTLD_DEFAULT;
2737d421530SBarry Smith #else
2747c62f5d3SDmitry Karpeev       dlhandle = dlopen(0, dlflags1|dlflags2);
2757c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
2764956914eSSatish Balay       { const char *e = (const char*) dlerror();
2777d421530SBarry Smith         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);
2787c62f5d3SDmitry Karpeev       }
2797c62f5d3SDmitry Karpeev #endif
2807d421530SBarry Smith #endif
281be1c6ad7SLisandro Dalcin     }
282be1c6ad7SLisandro Dalcin #endif
283aa2d57e9SJed Brown #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
2844956914eSSatish Balay   }
285be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
286be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
287be1c6ad7SLisandro Dalcin #endif
2886ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
2895673baf8SLisandro Dalcin   /*
2905673baf8SLisandro Dalcin      --- unimplemented ---
2915673baf8SLisandro Dalcin   */
292ebd79076SLisandro Dalcin #else
293e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
294ebd79076SLisandro Dalcin #endif
295ebd79076SLisandro Dalcin 
2966ea75d68SLisandro Dalcin   *value = *((void**)&dlsymbol);
297ebd79076SLisandro Dalcin 
2982d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
2992d53ad75SBarry Smith   if (*value) {
3002d53ad75SBarry Smith     PetscErrorCode ierr;
3012d53ad75SBarry Smith     ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
3022d53ad75SBarry Smith   }
3032d53ad75SBarry Smith #endif
3042d53ad75SBarry Smith   return(0);
305ebd79076SLisandro Dalcin }
306