xref: /petsc/src/sys/dll/dlimpl.c (revision 21532e8a5a1a1e7911222ee0f2ed1e65b4f3f1d8)
1ebd79076SLisandro Dalcin /*
2ebd79076SLisandro Dalcin    Low-level routines for managing dynamic link libraries (DLLs).
3ebd79076SLisandro Dalcin */
4ebd79076SLisandro Dalcin 
5184ce1a2SMatthew G. Knepley #include <petscconf.h>
6184ce1a2SMatthew G. Knepley #if defined(PETSC__GNU_SOURCE)
7184ce1a2SMatthew G. Knepley   #if !defined(_GNU_SOURCE)
8184ce1a2SMatthew G. Knepley     #define _GNU_SOURCE 1
9184ce1a2SMatthew G. Knepley   #endif
10184ce1a2SMatthew G. Knepley #endif
11184ce1a2SMatthew G. Knepley 
12af0996ceSBarry Smith #include <petsc/private/petscimpl.h>
13ebd79076SLisandro Dalcin 
14ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
15ebd79076SLisandro Dalcin   #include <windows.h>
16184ce1a2SMatthew G. Knepley #endif
17184ce1a2SMatthew G. Knepley #if 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
33811af0c4SBarry Smith    PetscDLOpen - opens a 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:
42811af0c4SBarry Smith .    handle - opaque pointer to be used with `PetscDLSym()`
43b235ab32SBarry Smith 
44b235ab32SBarry Smith    Level: developer
45b235ab32SBarry Smith 
46*21532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLSym()`, `PetscDLAddr()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
47*21532e8aSBarry Smith           `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryClose()`, `PetscDLLibrarySym()`
48ebd79076SLisandro Dalcin @*/
49d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLOpen(const char name[], PetscDLMode mode, PetscDLHandle *handle)
50d71ae5a4SJacob Faibussowitsch {
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) {
69d0609cedSBarry Smith     /* TODO: Seem to need fixing, why not just return with an error with SETERRQ() */
70ebd79076SLisandro Dalcin   #if defined(PETSC_HAVE_GETLASTERROR)
71ebd79076SLisandro Dalcin     DWORD erc;
72b3bb0f5eSLisandro Dalcin     char *buff = NULL;
73ebd79076SLisandro Dalcin     erc        = GetLastError();
749371c9d4SSatish Balay     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, erc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buff, 0, NULL);
759371c9d4SSatish Balay     PetscCall(PetscError(PETSC_COMM_SELF, __LINE__, PETSC_FUNCTION_NAME, __FILE__, PETSC_ERR_FILE_OPEN, PETSC_ERROR_REPEAT, "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s\n", name, buff));
76ebd79076SLisandro Dalcin     LocalFree(buff);
773ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
78ebd79076SLisandro Dalcin   #else
7998921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open dynamic library:\n  %s\n  Error message from LoadLibrary() %s", 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
11598921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open dynamic library:\n  %s\n  Error message from dlopen() %s", name, errmsg);
116ebd79076SLisandro Dalcin   }
1175673baf8SLisandro Dalcin   /*
1185673baf8SLisandro Dalcin      --- unimplemented ---
1195673baf8SLisandro Dalcin   */
120ebd79076SLisandro Dalcin #else
121e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
122ebd79076SLisandro Dalcin #endif
123ebd79076SLisandro Dalcin 
124ebd79076SLisandro Dalcin   *handle = (PetscDLHandle)dlhandle;
1253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
126ebd79076SLisandro Dalcin }
127ebd79076SLisandro Dalcin 
128ebd79076SLisandro Dalcin /*@C
129b235ab32SBarry Smith    PetscDLClose -  closes a dynamic library
130b235ab32SBarry Smith 
131b235ab32SBarry Smith    Not Collective
132b235ab32SBarry Smith 
133b235ab32SBarry Smith   Input Parameter:
134811af0c4SBarry Smith .   handle - the handle for the library obtained with `PetscDLOpen()`
135b235ab32SBarry Smith 
136b235ab32SBarry Smith   Level: developer
13710699b91SBarry Smith 
138db781477SPatrick Sanan .seealso: `PetscDLOpen()`, `PetscDLSym()`, `PetscDLAddr()`
139ebd79076SLisandro Dalcin @*/
140d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLClose(PetscDLHandle *handle)
141d71ae5a4SJacob Faibussowitsch {
142ebd79076SLisandro Dalcin   PetscFunctionBegin;
143ebd79076SLisandro Dalcin   PetscValidPointer(handle, 1);
144ebd79076SLisandro Dalcin 
1455673baf8SLisandro Dalcin   /*
1465673baf8SLisandro Dalcin      --- FreeLibrary ---
1475673baf8SLisandro Dalcin   */
148ebd79076SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
149be1c6ad7SLisandro Dalcin   #if defined(PETSC_HAVE_FREELIBRARY)
1508e049581SJed Brown   if (FreeLibrary((dlhandle_t)*handle) == 0) {
1515673baf8SLisandro Dalcin     #if defined(PETSC_HAVE_GETLASTERROR)
152b3bb0f5eSLisandro Dalcin     char *buff = NULL;
153a21658a3SLisandro Dalcin     DWORD erc  = GetLastError();
1540298fd71SBarry 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);
1553ba16761SJacob Faibussowitsch     PetscCall(PetscErrorPrintf("Error closing dynamic library:\n  Error message from FreeLibrary() %s\n", buff));
1565673baf8SLisandro Dalcin     LocalFree(buff);
1575673baf8SLisandro Dalcin     #else
1583ba16761SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error closing dynamic library:\n  Error message from FreeLibrary() %s", "unavailable");
1595673baf8SLisandro Dalcin     #endif
1605673baf8SLisandro Dalcin   }
161be1c6ad7SLisandro Dalcin   #endif /* !PETSC_HAVE_FREELIBRARY */
162ebd79076SLisandro Dalcin 
1635673baf8SLisandro Dalcin   /*
1645673baf8SLisandro Dalcin      --- dclose ---
1655673baf8SLisandro Dalcin   */
166ebd79076SLisandro Dalcin #elif defined(PETSC_HAVE_DLFCN_H)
167a21658a3SLisandro Dalcin   #if defined(PETSC_HAVE_DLCLOSE)
168be1c6ad7SLisandro Dalcin     #if defined(PETSC_HAVE_DLERROR)
169be1c6ad7SLisandro Dalcin   dlerror(); /* clear any previous error */
170be1c6ad7SLisandro Dalcin     #endif
1718e049581SJed Brown   if (dlclose((dlhandle_t)*handle) < 0) {
172ebd79076SLisandro Dalcin     #if defined(PETSC_HAVE_DLERROR)
173ebd79076SLisandro Dalcin     const char *errmsg = dlerror();
174ebd79076SLisandro Dalcin     #else
175ebd79076SLisandro Dalcin     const char *errmsg = "unavailable";
176ebd79076SLisandro Dalcin     #endif
1773ba16761SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Error closing dynamic library:\n  Error message from dlclose() %s", errmsg);
178ebd79076SLisandro Dalcin   }
179a21658a3SLisandro Dalcin   #endif /* !PETSC_HAVE_DLCLOSE */
1805673baf8SLisandro Dalcin 
1815673baf8SLisandro Dalcin   /*
1825673baf8SLisandro Dalcin      --- unimplemented ---
1835673baf8SLisandro Dalcin   */
184ebd79076SLisandro Dalcin #else
185e32f2f54SBarry Smith   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
186ebd79076SLisandro Dalcin #endif
187ebd79076SLisandro Dalcin 
1880298fd71SBarry Smith   *handle = NULL;
1893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
190ebd79076SLisandro Dalcin }
191ebd79076SLisandro Dalcin 
192accbd18bSBarry Smith // clang-format off
193accbd18bSBarry Smith 
194ebd79076SLisandro Dalcin /*@C
195b235ab32SBarry Smith    PetscDLSym - finds a symbol in a dynamic library
196b235ab32SBarry Smith 
197b235ab32SBarry Smith    Not Collective
198b235ab32SBarry Smith 
199b235ab32SBarry Smith    Input Parameters:
200*21532e8aSBarry Smith +   handle - obtained with `PetscDLOpen()` or `NULL`
201b235ab32SBarry Smith -   symbol - name of symbol
202b235ab32SBarry Smith 
203b235ab32SBarry Smith    Output Parameter:
204*21532e8aSBarry Smith .   value - pointer to the function, `NULL` if not found
205b235ab32SBarry Smith 
206b235ab32SBarry Smith    Level: developer
207b235ab32SBarry Smith 
208811af0c4SBarry Smith   Note:
209*21532e8aSBarry Smith    If handle is `NULL`, the symbol is looked for in the main executable's dynamic symbol table.
2107c62f5d3SDmitry Karpeev    In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
2117c62f5d3SDmitry Karpeev    systems this requires platform-specific linker flags.
2127c62f5d3SDmitry Karpeev 
213*21532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLOpen()`, `PetscDLAddr()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
214*21532e8aSBarry Smith           `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryClose()`, `PetscDLLibrarySym()`
215ebd79076SLisandro Dalcin @*/
216d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLSym(PetscDLHandle handle, const char symbol[], void **value)
217d71ae5a4SJacob Faibussowitsch {
2188e049581SJed Brown   PETSC_UNUSED dlhandle_t dlhandle;
2196ea75d68SLisandro Dalcin   dlsymbol_t              dlsymbol;
220ebd79076SLisandro Dalcin 
2213ba16761SJacob Faibussowitsch   PetscFunctionBegin;
222ebd79076SLisandro Dalcin   PetscValidCharPointer(symbol, 2);
223ebd79076SLisandro Dalcin   PetscValidPointer(value, 3);
224ebd79076SLisandro Dalcin 
225be1c6ad7SLisandro Dalcin   dlhandle = (dlhandle_t)0;
2266ea75d68SLisandro Dalcin   dlsymbol = (dlsymbol_t)0;
227a21658a3SLisandro Dalcin   *value   = (void *)0;
228ebd79076SLisandro Dalcin 
2295673baf8SLisandro Dalcin   /*
2305673baf8SLisandro Dalcin      --- GetProcAddress ---
2315673baf8SLisandro Dalcin   */
232a21658a3SLisandro Dalcin   #if defined(PETSC_HAVE_WINDOWS_H)
233a21658a3SLisandro Dalcin     #if defined(PETSC_HAVE_GETPROCADDRESS)
234e4d177b5SBarry Smith       if (handle) dlhandle = (dlhandle_t)handle;
235e4d177b5SBarry Smith       else dlhandle = (dlhandle_t)GetCurrentProcess();
2366ea75d68SLisandro Dalcin       dlsymbol = (dlsymbol_t)GetProcAddress(dlhandle, symbol);
237a21658a3SLisandro Dalcin       #if defined(PETSC_HAVE_SETLASTERROR)
238a21658a3SLisandro Dalcin         SetLastError((DWORD)0); /* clear any previous error */
239accbd18bSBarry Smith       #endif /* PETSC_HAVE_SETLASTERROR */
240a21658a3SLisandro Dalcin     #endif /* !PETSC_HAVE_GETPROCADDRESS */
2415673baf8SLisandro Dalcin 
2425673baf8SLisandro Dalcin   /*
2435673baf8SLisandro Dalcin      --- dlsym ---
2445673baf8SLisandro Dalcin   */
245accbd18bSBarry Smith   #elif defined(PETSC_HAVE_DLFCN_H) /* PETSC_HAVE_WINDOWS_H */
246a21658a3SLisandro Dalcin     #if defined(PETSC_HAVE_DLSYM)
247a297a907SKarl Rupp       if (handle) dlhandle = (dlhandle_t)handle;
248a297a907SKarl Rupp       else {
2495617e356SJunchao Zhang         #if defined(PETSC_HAVE_DLOPEN)
2507c62f5d3SDmitry Karpeev           /* Attempt to retrieve the main executable's dlhandle. */
2519371c9d4SSatish Balay           {
2529371c9d4SSatish Balay             int dlflags1 = 0, dlflags2 = 0;
2537c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_RTLD_LAZY)
2547c62f5d3SDmitry Karpeev               dlflags1 = RTLD_LAZY;
255accbd18bSBarry Smith             #endif /* PETSC_HAVE_RTLD_LAZY */
2567c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_RTLD_NOW)
257accbd18bSBarry Smith               if (!dlflags1) {
2587c62f5d3SDmitry Karpeev                 dlflags1 = RTLD_NOW;
2597c62f5d3SDmitry Karpeev               }
260accbd18bSBarry Smith             #endif /* PETSC_HAVE_RTLD_NOW */
2617c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_RTLD_LOCAL)
2627c62f5d3SDmitry Karpeev               dlflags2 = RTLD_LOCAL;
263accbd18bSBarry Smith             #endif /* PETSC_HAVE_RTLD_LOCAL */
2647c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_RTLD_GLOBAL)
265accbd18bSBarry Smith               if (!dlflags2) {
2667c62f5d3SDmitry Karpeev                 dlflags2 = RTLD_GLOBAL;
2677c62f5d3SDmitry Karpeev               }
268accbd18bSBarry Smith             #endif /* PETSC_HAVE_RTLD_GLOBAL */
2697c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_DLERROR)
2709371c9d4SSatish Balay               if (!(PETSC_RUNNING_ON_VALGRIND)) { dlerror(); /* clear any previous error; valgrind does not like this */ }
271accbd18bSBarry Smith             #endif /* PETSC_HAVE_DLERROR */
272618dc07dSPierre Jolivet             #if defined(PETSC_HAVE_RTLD_DEFAULT)
2737d421530SBarry Smith               dlhandle = RTLD_DEFAULT;
274d1408c41SPierre Jolivet             #else /* PETSC_HAVE_RTLD_DEFAULT */
275accbd18bSBarry Smith               /* Attempt to open the main executable as a dynamic library. */
27602c9f0b5SLisandro Dalcin               dlhandle = dlopen(NULL, dlflags1 | dlflags2);
2777c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_DLERROR)
2789371c9d4SSatish Balay                 {
2799371c9d4SSatish Balay                   const char *e = (const char *)dlerror();
28028b400f6SJacob Faibussowitsch                   PetscCheck(!e, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error opening main executable as a dynamic library:\n  Error message from dlopen(): '%s'", e);
2817c62f5d3SDmitry Karpeev                 }
282accbd18bSBarry Smith               #endif /* PETSC_HAVE_DLERROR */
283d1408c41SPierre Jolivet             #endif /* PETSC_HAVE_RTLD_DEFAULT */
2847c62f5d3SDmitry Karpeev           }
285accbd18bSBarry Smith         #endif /* PETSC_HAVE_DLOPEN */
2864956914eSSatish Balay       }
287be1c6ad7SLisandro Dalcin       #if defined(PETSC_HAVE_DLERROR)
288be1c6ad7SLisandro Dalcin         dlerror(); /* clear any previous error */
289accbd18bSBarry Smith       #endif /* PETSC_HAVE_DLERROR */
2906ea75d68SLisandro Dalcin       dlsymbol = (dlsymbol_t)dlsym(dlhandle, symbol);
291accbd18bSBarry Smith     #else /* PETSC_HAVE_DLSYM */
292e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
293accbd18bSBarry Smith     #endif /* PETSC_HAVE_DLSYM */
294accbd18bSBarry Smith   #else /* PETSC_HAVE_DLFCN_H */
295accbd18bSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
296accbd18bSBarry Smith   #endif /* PETSC_HAVE_WINDOWS_H */
297accbd18bSBarry Smith   // clang-format on
298ebd79076SLisandro Dalcin 
2996ea75d68SLisandro Dalcin   *value = *((void **)&dlsymbol);
300ebd79076SLisandro Dalcin 
3012d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3029566063dSJacob Faibussowitsch   if (*value) PetscCall(PetscFPTAdd(*value, symbol));
303accbd18bSBarry Smith #endif /* PETSC_SERIALIZE_FUNCTIONS */
3043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
305ebd79076SLisandro Dalcin }
306184ce1a2SMatthew G. Knepley 
307184ce1a2SMatthew G. Knepley /*@C
308184ce1a2SMatthew G. Knepley   PetscDLAddr - find the name of a symbol in a dynamic library
309184ce1a2SMatthew G. Knepley 
310184ce1a2SMatthew G. Knepley   Not Collective
311184ce1a2SMatthew G. Knepley 
312184ce1a2SMatthew G. Knepley   Input Parameters:
313*21532e8aSBarry Smith + handle - obtained with `PetscDLOpen()` or `NULL`
314*21532e8aSBarry Smith - func   - pointer to the function, `NULL` if not found
315184ce1a2SMatthew G. Knepley 
316184ce1a2SMatthew G. Knepley   Output Parameter:
317*21532e8aSBarry Smith . name   - name of symbol, or `NULL` if name lookup is not supported.
318184ce1a2SMatthew G. Knepley 
319184ce1a2SMatthew G. Knepley   Level: developer
320184ce1a2SMatthew G. Knepley 
321184ce1a2SMatthew G. Knepley   Notes:
32204c51a94SMatthew G. Knepley   The caller must free the returned name.
323258ec3d2SMatthew G. Knepley 
324184ce1a2SMatthew G. Knepley   In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
325184ce1a2SMatthew G. Knepley   systems this requires platform-specific linker flags.
32610699b91SBarry Smith 
327*21532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLSym()`, `PetscDLOpen()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
328*21532e8aSBarry Smith           `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryClose()`, `PetscDLLibrarySym()`
329184ce1a2SMatthew G. Knepley @*/
330d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
331d71ae5a4SJacob Faibussowitsch {
332184ce1a2SMatthew G. Knepley   PetscFunctionBegin;
333dadcf809SJacob Faibussowitsch   PetscValidPointer(name, 2);
334184ce1a2SMatthew G. Knepley   *name = NULL;
335e8953f01SSatish Balay #if defined(PETSC_HAVE_DLADDR) && !(defined(__cray__) && defined(__clang__))
336184ce1a2SMatthew G. Knepley   dlerror(); /* clear any previous error */
337184ce1a2SMatthew G. Knepley   {
338184ce1a2SMatthew G. Knepley     Dl_info info;
339184ce1a2SMatthew G. Knepley 
3405f80ce2aSJacob Faibussowitsch     PetscCheck(dladdr(*(void **)&func, &info), PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
341258ec3d2SMatthew G. Knepley   #ifdef PETSC_HAVE_CXX
3429566063dSJacob Faibussowitsch     PetscCall(PetscDemangleSymbol(info.dli_sname, name));
343258ec3d2SMatthew G. Knepley   #else
3449566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(info.dli_sname, name));
345258ec3d2SMatthew G. Knepley   #endif
346184ce1a2SMatthew G. Knepley   }
347184ce1a2SMatthew G. Knepley #endif
3483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
349184ce1a2SMatthew G. Knepley }
350