xref: /petsc/src/sys/dll/dlimpl.c (revision efca3c55b02548817e185e5069a2acfe20fa4458)
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>
7ebd79076SLisandro Dalcin 
8ebd79076SLisandro Dalcin /* XXX Should be done better !!!*/
9be1c6ad7SLisandro Dalcin #if !defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
10ebd79076SLisandro Dalcin #undef PETSC_HAVE_WINDOWS_H
11ebd79076SLisandro Dalcin #undef PETSC_HAVE_DLFCN_H
12ebd79076SLisandro Dalcin #endif
13ebd79076SLisandro Dalcin 
14ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
15ebd79076SLisandro Dalcin #include <windows.h>
16be1c6ad7SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
17ebd79076SLisandro Dalcin #include <dlfcn.h>
18ebd79076SLisandro Dalcin #endif
19ebd79076SLisandro Dalcin 
20ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
21ebd79076SLisandro Dalcin typedef HMODULE dlhandle_t;
226ea75d68SLisandro Dalcin typedef FARPROC dlsymbol_t;
23ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
24ebd79076SLisandro Dalcin typedef void* dlhandle_t;
256ea75d68SLisandro Dalcin typedef void* dlsymbol_t;
26ebd79076SLisandro Dalcin #else
27ebd79076SLisandro Dalcin typedef void* dlhandle_t;
286ea75d68SLisandro Dalcin typedef void* dlsymbol_t;
29ebd79076SLisandro Dalcin #endif
30ebd79076SLisandro Dalcin 
31ebd79076SLisandro Dalcin #undef __FUNCT__
32ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLOpen"
33ebd79076SLisandro Dalcin /*@C
34b235ab32SBarry Smith    PetscDLOpen - opens dynamic library
35b235ab32SBarry Smith 
36b235ab32SBarry Smith    Not Collective
37b235ab32SBarry Smith 
38b235ab32SBarry Smith    Input Parameters:
39b235ab32SBarry Smith +    name - name of library
40e4d177b5SBarry Smith -    mode - options on how to open library
41b235ab32SBarry Smith 
42b235ab32SBarry Smith    Output Parameter:
43b235ab32SBarry Smith .    handle
44b235ab32SBarry Smith 
45b235ab32SBarry Smith    Level: developer
46b235ab32SBarry Smith 
47ebd79076SLisandro Dalcin @*/
48e4d177b5SBarry Smith PetscErrorCode  PetscDLOpen(const char name[],PetscDLMode mode,PetscDLHandle *handle)
49ebd79076SLisandro Dalcin {
508e049581SJed Brown   PETSC_UNUSED int dlflags1,dlflags2; /* There are some preprocessor paths where these variables are set, but not used */
51ebd79076SLisandro Dalcin   dlhandle_t       dlhandle;
52ebd79076SLisandro Dalcin 
53ebd79076SLisandro Dalcin   PetscFunctionBegin;
54ebd79076SLisandro Dalcin   PetscValidCharPointer(name,1);
55ebd79076SLisandro Dalcin   PetscValidPointer(handle,3);
56ebd79076SLisandro Dalcin 
57be1c6ad7SLisandro Dalcin   dlflags1 = 0;
58be1c6ad7SLisandro Dalcin   dlflags2 = 0;
595673baf8SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
60be1c6ad7SLisandro Dalcin   *handle  = (PetscDLHandle) 0;
61ebd79076SLisandro Dalcin 
625673baf8SLisandro Dalcin   /*
635673baf8SLisandro Dalcin      --- LoadLibrary ---
645673baf8SLisandro Dalcin   */
65be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) && defined(PETSC_HAVE_LOADLIBRARY)
66be1c6ad7SLisandro Dalcin   dlhandle = LoadLibrary(name);
67ebd79076SLisandro Dalcin   if (!dlhandle) {
68ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
69ebd79076SLisandro Dalcin     PetscErrorCode ierr;
70ebd79076SLisandro Dalcin     DWORD          erc;
71b3bb0f5eSLisandro Dalcin     char           *buff = NULL;
72ebd79076SLisandro Dalcin     erc = GetLastError();
73ebd79076SLisandro Dalcin     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
740298fd71SBarry Smith                   NULL,erc,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),(LPSTR)&buff,0,NULL);
75*efca3c55SSatish Balay     ierr = PetscError(PETSC_COMM_SELF,__LINE__,__FUNCT__,__FILE__,PETSC_ERR_FILE_OPEN,PETSC_ERROR_REPEAT,
76be1c6ad7SLisandro Dalcin                       "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n",name,buff);
77ebd79076SLisandro Dalcin     LocalFree(buff);
78ebd79076SLisandro Dalcin     PetscFunctionReturn(ierr);
79ebd79076SLisandro Dalcin #else
80e32f2f54SBarry 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");
81ebd79076SLisandro Dalcin #endif
82ebd79076SLisandro Dalcin   }
835673baf8SLisandro Dalcin 
845673baf8SLisandro Dalcin   /*
855673baf8SLisandro Dalcin      --- dlopen ---
865673baf8SLisandro Dalcin   */
87a21658a3SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
88ebd79076SLisandro Dalcin   /*
89ebd79076SLisandro Dalcin       Mode indicates symbols required by symbol loaded with dlsym()
90ebd79076SLisandro Dalcin      are only loaded when required (not all together) also indicates
91ebd79076SLisandro Dalcin      symbols required can be contained in other libraries also opened
92ebd79076SLisandro Dalcin      with dlopen()
93ebd79076SLisandro Dalcin   */
94be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LAZY)
95be1c6ad7SLisandro Dalcin   dlflags1 = RTLD_LAZY;
96be1c6ad7SLisandro Dalcin #endif
97ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_NOW)
98a297a907SKarl Rupp   if (mode & PETSC_DL_NOW) dlflags1 = RTLD_NOW;
99ebd79076SLisandro Dalcin #endif
100ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_RTLD_GLOBAL)
101be1c6ad7SLisandro Dalcin   dlflags2 = RTLD_GLOBAL;
102ebd79076SLisandro Dalcin #endif
103b3bb0f5eSLisandro Dalcin #if defined(PETSC_HAVE_RTLD_LOCAL)
104a297a907SKarl Rupp   if (mode & PETSC_DL_LOCAL) dlflags2 = RTLD_LOCAL;
105b3bb0f5eSLisandro Dalcin #endif
106be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
107be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
108be1c6ad7SLisandro Dalcin #endif
109be1c6ad7SLisandro Dalcin   dlhandle = dlopen(name,dlflags1|dlflags2);
110ebd79076SLisandro Dalcin   if (!dlhandle) {
111ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
112ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
113ebd79076SLisandro Dalcin #else
114ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
115ebd79076SLisandro Dalcin #endif
116be015529SBarry 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);
117ebd79076SLisandro Dalcin   }
1185673baf8SLisandro Dalcin 
1195673baf8SLisandro Dalcin   /*
1205673baf8SLisandro Dalcin      --- unimplemented ---
1215673baf8SLisandro Dalcin   */
122ebd79076SLisandro Dalcin #else
123e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
124ebd79076SLisandro Dalcin #endif
125ebd79076SLisandro Dalcin 
126ebd79076SLisandro Dalcin   *handle = (PetscDLHandle) dlhandle;
127ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
128ebd79076SLisandro Dalcin }
129ebd79076SLisandro Dalcin 
130ebd79076SLisandro Dalcin 
131ebd79076SLisandro Dalcin #undef __FUNCT__
132ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLClose"
133ebd79076SLisandro Dalcin /*@C
134b235ab32SBarry Smith    PetscDLClose -  closes a dynamic library
135b235ab32SBarry Smith 
136b235ab32SBarry Smith    Not Collective
137b235ab32SBarry Smith 
138b235ab32SBarry Smith   Input Parameter:
139b235ab32SBarry Smith .   handle - the handle for the library obtained with PetscDLOpen()
140b235ab32SBarry Smith 
141b235ab32SBarry Smith   Level: developer
142ebd79076SLisandro Dalcin @*/
1437087cfbeSBarry Smith PetscErrorCode  PetscDLClose(PetscDLHandle *handle)
144ebd79076SLisandro Dalcin {
145ebd79076SLisandro Dalcin 
146ebd79076SLisandro Dalcin   PetscFunctionBegin;
147ebd79076SLisandro Dalcin   PetscValidPointer(handle,1);
148ebd79076SLisandro Dalcin 
1495673baf8SLisandro Dalcin   /*
1505673baf8SLisandro Dalcin      --- FreeLibrary ---
1515673baf8SLisandro Dalcin   */
152ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
153be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_FREELIBRARY)
1548e049581SJed Brown   if (FreeLibrary((dlhandle_t)*handle) == 0) {
1555673baf8SLisandro Dalcin #if defined(PETSC_HAVE_GETLASTERROR)
156b3bb0f5eSLisandro Dalcin     char  *buff = NULL;
157a21658a3SLisandro Dalcin     DWORD erc   = GetLastError();
1580298fd71SBarry 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);
1595673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n",buff);
1605673baf8SLisandro Dalcin     LocalFree(buff);
1615673baf8SLisandro Dalcin #else
1625673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n","unavailable");
1635673baf8SLisandro Dalcin #endif
1645673baf8SLisandro Dalcin   }
165be1c6ad7SLisandro Dalcin #endif /* !PETSC_HAVE_FREELIBRARY */
166ebd79076SLisandro Dalcin 
1675673baf8SLisandro Dalcin   /*
1685673baf8SLisandro Dalcin      --- dclose ---
1695673baf8SLisandro Dalcin   */
170ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
171a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLCLOSE)
172be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
173be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
174be1c6ad7SLisandro Dalcin #endif
1758e049581SJed Brown   if (dlclose((dlhandle_t)*handle) < 0) {
176ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
177ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
178ebd79076SLisandro Dalcin #else
179ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
180ebd79076SLisandro Dalcin #endif
1815673baf8SLisandro Dalcin     PetscErrorPrintf("Error closing dynamic library:\n  Error message from dlclose() %s\n", errmsg);
182ebd79076SLisandro Dalcin   }
183a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_DLCLOSE */
1845673baf8SLisandro Dalcin 
1855673baf8SLisandro Dalcin   /*
1865673baf8SLisandro Dalcin      --- unimplemented ---
1875673baf8SLisandro Dalcin   */
188ebd79076SLisandro Dalcin #else
189e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
190ebd79076SLisandro Dalcin #endif
191ebd79076SLisandro Dalcin 
1920298fd71SBarry Smith   *handle = NULL;
193ebd79076SLisandro Dalcin   PetscFunctionReturn(0);
194ebd79076SLisandro Dalcin }
195ebd79076SLisandro Dalcin 
196ebd79076SLisandro Dalcin #undef __FUNCT__
197ebd79076SLisandro Dalcin #define __FUNCT__ "PetscDLSym"
198ebd79076SLisandro Dalcin /*@C
199b235ab32SBarry Smith    PetscDLSym - finds a symbol in a dynamic library
200b235ab32SBarry Smith 
201b235ab32SBarry Smith    Not Collective
202b235ab32SBarry Smith 
203b235ab32SBarry Smith    Input Parameters:
2040298fd71SBarry Smith +   handle - obtained with PetscDLOpen() or NULL
205b235ab32SBarry Smith -   symbol - name of symbol
206b235ab32SBarry Smith 
207b235ab32SBarry Smith    Output Parameter:
2080298fd71SBarry Smith .   value - pointer to the function, NULL if not found
209b235ab32SBarry Smith 
210b235ab32SBarry Smith    Level: developer
211b235ab32SBarry Smith 
2127c62f5d3SDmitry Karpeev   Notes:
2130298fd71SBarry Smith    If handle is NULL, the symbol is looked for in the main executable's dynamic symbol table.
2147c62f5d3SDmitry Karpeev    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
2157c62f5d3SDmitry Karpeev    systems this requires platform-specific linker flags.
2167c62f5d3SDmitry Karpeev 
217ebd79076SLisandro Dalcin @*/
2187087cfbeSBarry Smith PetscErrorCode  PetscDLSym(PetscDLHandle handle,const char symbol[],void **value)
219ebd79076SLisandro Dalcin {
2208e049581SJed Brown   PETSC_UNUSED dlhandle_t dlhandle;
2216ea75d68SLisandro Dalcin   dlsymbol_t              dlsymbol;
222ebd79076SLisandro Dalcin 
223ebd79076SLisandro Dalcin   PetscValidCharPointer(symbol,2);
224ebd79076SLisandro Dalcin   PetscValidPointer(value,3);
225ebd79076SLisandro Dalcin 
226be1c6ad7SLisandro Dalcin   dlhandle = (dlhandle_t) 0;
2276ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) 0;
228a21658a3SLisandro Dalcin   *value   = (void*) 0;
229ebd79076SLisandro Dalcin 
2305673baf8SLisandro Dalcin   /*
2315673baf8SLisandro Dalcin      --- GetProcAddress ---
2325673baf8SLisandro Dalcin   */
233a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
234a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_GETPROCADDRESS)
235e4d177b5SBarry Smith   if (handle) dlhandle = (dlhandle_t) handle;
236e4d177b5SBarry Smith   else dlhandle = (dlhandle_t) GetCurrentProcess();
2376ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) GetProcAddress(dlhandle,symbol);
238a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_SETLASTERROR)
239a21658a3SLisandro Dalcin   SetLastError((DWORD)0); /* clear any previous error */
240a21658a3SLisandro Dalcin #endif
241a21658a3SLisandro Dalcin #endif /* !PETSC_HAVE_GETPROCADDRESS */
2425673baf8SLisandro Dalcin 
2435673baf8SLisandro Dalcin   /*
2445673baf8SLisandro Dalcin      --- dlsym ---
2455673baf8SLisandro Dalcin   */
246ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
247a21658a3SLisandro Dalcin #if defined(PETSC_HAVE_DLSYM)
248a297a907SKarl Rupp   if (handle) dlhandle = (dlhandle_t) handle;
249a297a907SKarl Rupp   else {
2507c62f5d3SDmitry Karpeev 
251bfef2c86SBarry Smith #if defined(PETSC_HAVE_DLOPEN) && defined(PETSC_HAVE_DYNAMIC_LIBRARIES)
2527c62f5d3SDmitry Karpeev     /* Attempt to retrieve the main executable's dlhandle. */
2537c62f5d3SDmitry Karpeev     { int dlflags1 = 0, dlflags2 = 0;
2547c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LAZY)
2557c62f5d3SDmitry Karpeev       dlflags1 = RTLD_LAZY;
2567c62f5d3SDmitry Karpeev #endif
2577c62f5d3SDmitry Karpeev       if (!dlflags1) {
2587c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_NOW)
2597c62f5d3SDmitry Karpeev         dlflags1 = RTLD_NOW;
2607c62f5d3SDmitry Karpeev #endif
2617c62f5d3SDmitry Karpeev       }
2627c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_LOCAL)
2637c62f5d3SDmitry Karpeev       dlflags2 = RTLD_LOCAL;
2647c62f5d3SDmitry Karpeev #endif
2657c62f5d3SDmitry Karpeev       if (!dlflags2) {
2667c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_RTLD_GLOBAL)
2677c62f5d3SDmitry Karpeev         dlflags2 = RTLD_GLOBAL;
2687c62f5d3SDmitry Karpeev #endif
2697c62f5d3SDmitry Karpeev       }
2707c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
271cae2f346SBarry Smith       if (!(PETSC_RUNNING_ON_VALGRIND)) {
2727bb14e67SBarry Smith         dlerror(); /* clear any previous error; valgrind does not like this */
2737bb14e67SBarry Smith       }
2747bb14e67SBarry Smith #endif
2757c62f5d3SDmitry Karpeev       /* Attempt to open the main executable as a dynamic library. */
2767d421530SBarry Smith #if defined(PETSC_HAVE_RTDL_DEFAULT)
2777d421530SBarry Smith       dlhandle = RTLD_DEFAULT;
2787d421530SBarry Smith #else
2797c62f5d3SDmitry Karpeev       dlhandle = dlopen(0, dlflags1|dlflags2);
2807c62f5d3SDmitry Karpeev #if defined(PETSC_HAVE_DLERROR)
2814956914eSSatish Balay       { const char *e = (const char*) dlerror();
2827d421530SBarry 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);
2837c62f5d3SDmitry Karpeev       }
2847c62f5d3SDmitry Karpeev #endif
2857d421530SBarry Smith #endif
286be1c6ad7SLisandro Dalcin     }
287be1c6ad7SLisandro Dalcin #endif
288aa2d57e9SJed Brown #endif /* PETSC_HAVE_DLOPEN && PETSC_HAVE_DYNAMIC_LIBRARIES */
2894956914eSSatish Balay   }
290be1c6ad7SLisandro Dalcin #if defined(PETSC_HAVE_DLERROR)
291be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
292be1c6ad7SLisandro Dalcin #endif
2936ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t) dlsym(dlhandle,symbol);
2945673baf8SLisandro Dalcin   /*
2955673baf8SLisandro Dalcin      --- unimplemented ---
2965673baf8SLisandro Dalcin   */
297ebd79076SLisandro Dalcin #else
298e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
299ebd79076SLisandro Dalcin #endif
300ebd79076SLisandro Dalcin 
3016ea75d68SLisandro Dalcin   *value = *((void**)&dlsymbol);
302ebd79076SLisandro Dalcin 
3032d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3042d53ad75SBarry Smith   if (*value) {
3052d53ad75SBarry Smith     PetscErrorCode ierr;
3062d53ad75SBarry Smith     ierr = PetscFPTAdd(*value,symbol);CHKERRQ(ierr);
3072d53ad75SBarry Smith   }
3082d53ad75SBarry Smith #endif
3092d53ad75SBarry Smith   return(0);
310ebd79076SLisandro Dalcin }
311