xref: /petsc/src/sys/dll/dlimpl.c (revision 022afb99c29b2dbe6df8bc6699739c6dd2eaaddc)
17d0a6c19SBarry Smith 
2ebd79076SLisandro Dalcin /*
3ebd79076SLisandro Dalcin    Low-level routines for managing dynamic link libraries (DLLs).
4ebd79076SLisandro Dalcin */
5ebd79076SLisandro Dalcin 
6afcb2eb5SJed Brown #include <petsc-private/petscimpl.h>
7*022afb99SBarry 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 #undef __FUNCT__
33ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLOpen"
34ebd79076SLisandro Dalcin /*@C
35b235ab32SBarry Smith    PetscDLOpen - opens dynamic library
36b235ab32SBarry Smith 
37b235ab32SBarry Smith    Not Collective
38b235ab32SBarry Smith 
39b235ab32SBarry Smith    Input Parameters:
40b235ab32SBarry Smith +    name - name of library
41e4d177b5SBarry Smith -    mode - options on how to open library
42b235ab32SBarry Smith 
43b235ab32SBarry Smith    Output Parameter:
44b235ab32SBarry Smith .    handle
45b235ab32SBarry Smith 
46b235ab32SBarry Smith    Level: developer
47b235ab32SBarry Smith 
48ebd79076SLisandro Dalcin @*/
49e4d177b5SBarry Smith PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
50ebd79076SLisandro Dalcin {
518e049581SJed Brown   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
52ebd79076SLisandro Dalcin   dlhandle_t       dlhandle;
53ebd79076SLisandro Dalcin 
54ebd79076SLisandro Dalcin   PetscFunctionBegin;
55ebd79076SLisandro Dalcin   PetscValidCharPointer(name,1);
56ebd79076SLisandro Dalcin   PetscValidPointer(handle,3);
57ebd79076SLisandro Dalcin 
58be1c6ad7SLisandro Dalcin   dlflags1 = 0;
59be1c6ad7SLisandro Dalcin   dlflags2 = 0;
605673baf8SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
61be1c6ad7SLisandro Dalcin   *handle  = (PetscDLHandle) 0;
62ebd79076SLisandro Dalcin 
635673baf8SLisandro Dalcin   /*
645673baf8SLisandro Dalcin      --- LoadLibrary ---
655673baf8SLisandro Dalcin   */
66be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
67be1c6ad7SLisandro Dalcin   dlhandle = LoadLibrary(name);
68ebd79076SLisandro Dalcin   if (!dlhandle) {
69ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
70ebd79076SLisandro Dalcin     PetscErrorCode ierr;
71ebd79076SLisandro Dalcin     DWORD          erc;
72b3bb0f5eSLisandro Dalcin     char           *buff = NULL;
73ebd79076SLisandro Dalcin     erc = GetLastError();
74ebd79076SLisandro Dalcin     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
750298fd71SBarry Smith                   NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
76efca3c55SSatish Balay     ierr = PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
77be1c6ad7SLisandro Dalcin                       "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,buff);
78ebd79076SLisandro Dalcin     LocalFree(buff);
79ebd79076SLisandro Dalcin     PetscFunctionReturn(ierr);
80ebd79076SLisandro Dalcin #else
81e32f2f54SBarry 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");
82ebd79076SLisandro Dalcin #endif
83ebd79076SLisandro Dalcin   }
845673baf8SLisandro Dalcin 
855673baf8SLisandro Dalcin   /*
865673baf8SLisandro Dalcin      --- dlopen ---
875673baf8SLisandro Dalcin   */
88a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
89ebd79076SLisandro Dalcin   /*
90ebd79076SLisandro Dalcin       Mode indicates symbols required by symbol loaded with dlsym()
91ebd79076SLisandro Dalcin      are only loaded when required (not all together) also indicates
92ebd79076SLisandro Dalcin      symbols required can be contained in other libraries also opened
93ebd79076SLisandro Dalcin      with dlopen()
94ebd79076SLisandro Dalcin   */
95be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY)
96be1c6ad7SLisandro Dalcin   dlflags1 = RTLD_LAZY;
97be1c6ad7SLisandro Dalcin #endif
98ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW)
99a297a907SKarl Rupp   if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
100ebd79076SLisandro Dalcin #endif
101ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_GLOBAL)
102be1c6ad7SLisandro Dalcin   dlflags2 = RTLD_GLOBAL;
103ebd79076SLisandro Dalcin #endif
104b3bb0f5eSLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LOCAL)
105a297a907SKarl Rupp   if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
106b3bb0f5eSLisandro Dalcin #endif
107be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
108be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
109be1c6ad7SLisandro Dalcin #endif
110be1c6ad7SLisandro Dalcin   dlhandle = dlopen(name,dlflags1|dlflags2);
111ebd79076SLisandro Dalcin   if (!dlhandle) {
112ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
113ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
114ebd79076SLisandro Dalcin #else
115ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
116ebd79076SLisandro Dalcin #endif
117be015529SBarry 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);
118ebd79076SLisandro Dalcin   }
1195673baf8SLisandro Dalcin 
1205673baf8SLisandro Dalcin   /*
1215673baf8SLisandro Dalcin      --- unimplemented ---
1225673baf8SLisandro Dalcin   */
123ebd79076SLisandro Dalcin #else
124e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
125ebd79076SLisandro Dalcin #endif
126ebd79076SLisandro Dalcin 
127ebd79076SLisandro Dalcin   *handle = (PetscDLHandle) dlhandle;
128ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
129ebd79076SLisandro Dalcin }
130ebd79076SLisandro Dalcin 
131ebd79076SLisandro Dalcin 
132ebd79076SLisandro Dalcin #undef __FUNCT__
133ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLClose"
134ebd79076SLisandro Dalcin /*@C
135b235ab32SBarry Smith    PetscDLClose -  closes a dynamic library
136b235ab32SBarry Smith 
137b235ab32SBarry Smith    Not Collective
138b235ab32SBarry Smith 
139b235ab32SBarry Smith   Input Parameter:
140b235ab32SBarry Smith .   handle - the handle for the library obtained with PetscDLOpen()
141b235ab32SBarry Smith 
142b235ab32SBarry Smith   Level: developer
143ebd79076SLisandro Dalcin @*/
1447087cfbeSBarry Smith PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
145ebd79076SLisandro Dalcin {
146ebd79076SLisandro Dalcin 
147ebd79076SLisandro Dalcin   PetscFunctionBegin;
148ebd79076SLisandro Dalcin   PetscValidPointer(handle,1);
149ebd79076SLisandro Dalcin 
1505673baf8SLisandro Dalcin   /*
1515673baf8SLisandro Dalcin      --- FreeLibrary ---
1525673baf8SLisandro Dalcin   */
153ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
154be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY)
1558e049581SJed Brown   if (FreeLibrary((dlhandle_t)*handle) == 0) {
1565673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
157b3bb0f5eSLisandro Dalcin     char  *buff = NULL;
158a21658a3SLisandro Dalcin     DWORD erc   = GetLastError();
1590298fd71SBarry 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);
1605673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n",buff);
1615673baf8SLisandro Dalcin     LocalFree(buff);
1625673baf8SLisandro Dalcin #else
1635673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n","unavailable");
1645673baf8SLisandro Dalcin #endif
1655673baf8SLisandro Dalcin   }
166be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */
167ebd79076SLisandro Dalcin 
1685673baf8SLisandro Dalcin   /*
1695673baf8SLisandro Dalcin      --- dclose ---
1705673baf8SLisandro Dalcin   */
171ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
172a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE)
173be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
174be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
175be1c6ad7SLisandro Dalcin #endif
1768e049581SJed Brown   if (dlclose((dlhandle_t)*handle) < 0) {
177ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
178ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
179ebd79076SLisandro Dalcin #else
180ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
181ebd79076SLisandro Dalcin #endif
1825673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from dlclose() %s\n", errmsg);
183ebd79076SLisandro Dalcin   }
184a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */
1855673baf8SLisandro Dalcin 
1865673baf8SLisandro Dalcin   /*
1875673baf8SLisandro Dalcin      --- unimplemented ---
1885673baf8SLisandro Dalcin   */
189ebd79076SLisandro Dalcin #else
190e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
191ebd79076SLisandro Dalcin #endif
192ebd79076SLisandro Dalcin 
1930298fd71SBarry Smith   *handle = NULL;
194ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
195ebd79076SLisandro Dalcin }
196ebd79076SLisandro Dalcin 
197ebd79076SLisandro Dalcin #undef __FUNCT__
198ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLSym"
199ebd79076SLisandro Dalcin /*@C
200b235ab32SBarry Smith    PetscDLSym - finds a symbol in a dynamic library
201b235ab32SBarry Smith 
202b235ab32SBarry Smith    Not Collective
203b235ab32SBarry Smith 
204b235ab32SBarry Smith    Input Parameters:
2050298fd71SBarry Smith +   handle - obtained with PetscDLOpen() or NULL
206b235ab32SBarry Smith -   symbol - name of symbol
207b235ab32SBarry Smith 
208b235ab32SBarry Smith    Output Parameter:
2090298fd71SBarry Smith .   value - pointer to the function, NULL if not found
210b235ab32SBarry Smith 
211b235ab32SBarry Smith    Level: developer
212b235ab32SBarry Smith 
2137c62f5d3SDmitry Karpeev   Notes:
2140298fd71SBarry Smith    If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
2157c62f5d3SDmitry Karpeev    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
2167c62f5d3SDmitry Karpeev    systems this requires platform-specific linker flags.
2177c62f5d3SDmitry Karpeev 
218ebd79076SLisandro Dalcin @*/
2197087cfbeSBarry Smith PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
220ebd79076SLisandro Dalcin {
2218e049581SJed Brown   PETSC_UNUSED dlhandle_t dlhandle;
2226ea75d68SLisandro Dalcin   dlsymbol_t              dlsymbol;
223ebd79076SLisandro Dalcin 
224ebd79076SLisandro Dalcin   PetscValidCharPointer(symbol,2);
225ebd79076SLisandro Dalcin   PetscValidPointer(value,3);
226ebd79076SLisandro Dalcin 
227be1c6ad7SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
2286ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) 0;
229a21658a3SLisandro Dalcin   *value   = (void*) 0;
230ebd79076SLisandro Dalcin 
2315673baf8SLisandro Dalcin   /*
2325673baf8SLisandro Dalcin      --- GetProcAddress ---
2335673baf8SLisandro Dalcin   */
234a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
235a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS)
236e4d177b5SBarry Smith   if (handle) dlhandle = (dlhandle_t) handle;
237e4d177b5SBarry Smith   else dlhandle = (dlhandle_t) GetCurrentProcess();
2386ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
239a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR)
240a21658a3SLisandro Dalcin   SetLastError((DWORD)0); /* clear any previous error */
241a21658a3SLisandro Dalcin #endif
242a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */
2435673baf8SLisandro Dalcin 
2445673baf8SLisandro Dalcin   /*
2455673baf8SLisandro Dalcin      --- dlsym ---
2465673baf8SLisandro Dalcin   */
247ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
248a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM)
249a297a907SKarl Rupp   if (handle) dlhandle = (dlhandle_t) handle;
250a297a907SKarl Rupp   else {
2517c62f5d3SDmitry Karpeev 
252bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
2537c62f5d3SDmitry Karpeev     /* Attempt to retrieve the main executable's dlhandle. */
2547c62f5d3SDmitry Karpeev     { int dlflags1 = 0, dlflags2 = 0;
2557c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY)
2567c62f5d3SDmitry Karpeev       dlflags1 = RTLD_LAZY;
2577c62f5d3SDmitry Karpeev #endif
2587c62f5d3SDmitry Karpeev       if (!dlflags1) {
2597c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW)
2607c62f5d3SDmitry Karpeev         dlflags1 = RTLD_NOW;
2617c62f5d3SDmitry Karpeev #endif
2627c62f5d3SDmitry Karpeev       }
2637c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL)
2647c62f5d3SDmitry Karpeev       dlflags2 = RTLD_LOCAL;
2657c62f5d3SDmitry Karpeev #endif
2667c62f5d3SDmitry Karpeev       if (!dlflags2) {
2677c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL)
2687c62f5d3SDmitry Karpeev         dlflags2 = RTLD_GLOBAL;
2697c62f5d3SDmitry Karpeev #endif
2707c62f5d3SDmitry Karpeev       }
2717c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
272cae2f346SBarry Smith       if (!(PETSC_RUNNING_ON_VALGRIND)) {
2737bb14e67SBarry Smith         dlerror(); /* clear any previous error; valgrind does not like this */
2747bb14e67SBarry Smith       }
2757bb14e67SBarry Smith #endif
2767c62f5d3SDmitry Karpeev       /* Attempt to open the main executable as a dynamic library. */
2777d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT)
2787d421530SBarry Smith       dlhandle = RTLD_DEFAULT;
2797d421530SBarry Smith #else
2807c62f5d3SDmitry Karpeev       dlhandle = dlopen(0, dlflags1|dlflags2);
2817c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
2824956914eSSatish Balay       { const char *e = (const char*) dlerror();
2837d421530SBarry 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);
2847c62f5d3SDmitry Karpeev       }
2857c62f5d3SDmitry Karpeev #endif
2867d421530SBarry Smith #endif
287be1c6ad7SLisandro Dalcin     }
288be1c6ad7SLisandro Dalcin #endif
289aa2d57e9SJed Brown #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
2904956914eSSatish Balay   }
291be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
292be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
293be1c6ad7SLisandro Dalcin #endif
2946ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
2955673baf8SLisandro Dalcin   /*
2965673baf8SLisandro Dalcin      --- unimplemented ---
2975673baf8SLisandro Dalcin   */
298ebd79076SLisandro Dalcin #else
299e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
300ebd79076SLisandro Dalcin #endif
301ebd79076SLisandro Dalcin 
3026ea75d68SLisandro Dalcin   *value = *((void**)&dlsymbol);
303ebd79076SLisandro Dalcin 
3042d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3052d53ad75SBarry Smith   if (*value) {
3062d53ad75SBarry Smith     PetscErrorCode ierr;
3072d53ad75SBarry Smith     ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
3082d53ad75SBarry Smith   }
3092d53ad75SBarry Smith #endif
3102d53ad75SBarry Smith   return(0);
311ebd79076SLisandro Dalcin }
312