xref: /petsc/src/sys/dll/dlimpl.c (revision b8e43d2243e0f88213426470dd4ac5701e5aa8c2)
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 
4621532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLSym()`, `PetscDLAddr()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
4721532e8aSBarry 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;
554f572ea9SToby Isaac   PetscAssertPointer(name, 1);
564f572ea9SToby Isaac   PetscAssertPointer(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;
1434f572ea9SToby Isaac   PetscAssertPointer(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:
20021532e8aSBarry Smith + handle - obtained with `PetscDLOpen()` or `NULL`
201b235ab32SBarry Smith - symbol - name of symbol
202b235ab32SBarry Smith 
203b235ab32SBarry Smith   Output Parameter:
20421532e8aSBarry Smith . value - pointer to the function, `NULL` if not found
205b235ab32SBarry Smith 
206b235ab32SBarry Smith   Level: developer
207b235ab32SBarry Smith 
208811af0c4SBarry Smith   Note:
20921532e8aSBarry 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 
21321532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLOpen()`, `PetscDLAddr()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
21421532e8aSBarry 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;
2224f572ea9SToby Isaac   PetscAssertPointer(symbol, 2);
2234f572ea9SToby Isaac   PetscAssertPointer(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           {
252*b8e43d22SPierre Jolivet             #if !defined(PETSC_HAVE_RTLD_DEFAULT)
2539371c9d4SSatish Balay             int dlflags1 = 0, dlflags2 = 0;
2547c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_RTLD_LAZY)
2557c62f5d3SDmitry Karpeev               dlflags1 = RTLD_LAZY;
256accbd18bSBarry Smith               #endif /* PETSC_HAVE_RTLD_LAZY */
2577c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_RTLD_NOW)
258accbd18bSBarry Smith               if (!dlflags1) {
2597c62f5d3SDmitry Karpeev                 dlflags1 = RTLD_NOW;
2607c62f5d3SDmitry Karpeev               }
261accbd18bSBarry Smith               #endif /* PETSC_HAVE_RTLD_NOW */
2627c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_RTLD_LOCAL)
2637c62f5d3SDmitry Karpeev               dlflags2 = RTLD_LOCAL;
264accbd18bSBarry Smith               #endif /* PETSC_HAVE_RTLD_LOCAL */
2657c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_RTLD_GLOBAL)
266accbd18bSBarry Smith               if (!dlflags2) {
2677c62f5d3SDmitry Karpeev                 dlflags2 = RTLD_GLOBAL;
2687c62f5d3SDmitry Karpeev               }
269accbd18bSBarry Smith               #endif /* PETSC_HAVE_RTLD_GLOBAL */
270*b8e43d22SPierre Jolivet             #endif /* !PETSC_HAVE_RTLD_DEFAULT */
2717c62f5d3SDmitry Karpeev             #if defined(PETSC_HAVE_DLERROR)
2729371c9d4SSatish Balay               if (!(PETSC_RUNNING_ON_VALGRIND)) { dlerror(); /* clear any previous error; valgrind does not like this */ }
273accbd18bSBarry Smith             #endif /* PETSC_HAVE_DLERROR */
274618dc07dSPierre Jolivet             #if defined(PETSC_HAVE_RTLD_DEFAULT)
2757d421530SBarry Smith               dlhandle = RTLD_DEFAULT;
276d1408c41SPierre Jolivet             #else /* PETSC_HAVE_RTLD_DEFAULT */
277accbd18bSBarry Smith               /* Attempt to open the main executable as a dynamic library. */
27802c9f0b5SLisandro Dalcin               dlhandle = dlopen(NULL, dlflags1 | dlflags2);
2797c62f5d3SDmitry Karpeev               #if defined(PETSC_HAVE_DLERROR)
2809371c9d4SSatish Balay                 {
2819371c9d4SSatish Balay                   const char *e = (const char *)dlerror();
28228b400f6SJacob 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);
2837c62f5d3SDmitry Karpeev                 }
284accbd18bSBarry Smith               #endif /* PETSC_HAVE_DLERROR */
285*b8e43d22SPierre Jolivet             #endif /* !PETSC_HAVE_RTLD_DEFAULT */
2867c62f5d3SDmitry Karpeev           }
287accbd18bSBarry Smith         #endif /* PETSC_HAVE_DLOPEN */
2884956914eSSatish Balay       }
289be1c6ad7SLisandro Dalcin       #if defined(PETSC_HAVE_DLERROR)
290be1c6ad7SLisandro Dalcin         dlerror(); /* clear any previous error */
291accbd18bSBarry Smith       #endif /* PETSC_HAVE_DLERROR */
2926ea75d68SLisandro Dalcin       dlsymbol = (dlsymbol_t)dlsym(dlhandle, symbol);
293accbd18bSBarry Smith     #else /* PETSC_HAVE_DLSYM */
294e32f2f54SBarry Smith       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
295accbd18bSBarry Smith     #endif /* PETSC_HAVE_DLSYM */
296accbd18bSBarry Smith   #else /* PETSC_HAVE_DLFCN_H */
297accbd18bSBarry Smith     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot use dynamic libraries on this platform");
298accbd18bSBarry Smith   #endif /* PETSC_HAVE_WINDOWS_H */
299accbd18bSBarry Smith   // clang-format on
300ebd79076SLisandro Dalcin 
3016ea75d68SLisandro Dalcin   *value = *((void **)&dlsymbol);
302ebd79076SLisandro Dalcin 
3032d53ad75SBarry Smith #if defined(PETSC_SERIALIZE_FUNCTIONS)
3049566063dSJacob Faibussowitsch   if (*value) PetscCall(PetscFPTAdd(*value, symbol));
305accbd18bSBarry Smith #endif /* PETSC_SERIALIZE_FUNCTIONS */
3063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
307ebd79076SLisandro Dalcin }
308184ce1a2SMatthew G. Knepley 
309184ce1a2SMatthew G. Knepley /*@C
310184ce1a2SMatthew G. Knepley   PetscDLAddr - find the name of a symbol in a dynamic library
311184ce1a2SMatthew G. Knepley 
312184ce1a2SMatthew G. Knepley   Not Collective
313184ce1a2SMatthew G. Knepley 
314184ce1a2SMatthew G. Knepley   Input Parameters:
31510450e9eSJacob Faibussowitsch . func - pointer to the function, `NULL` if not found
316184ce1a2SMatthew G. Knepley 
317184ce1a2SMatthew G. Knepley   Output Parameter:
31821532e8aSBarry Smith . name - name of symbol, or `NULL` if name lookup is not supported.
319184ce1a2SMatthew G. Knepley 
320184ce1a2SMatthew G. Knepley   Level: developer
321184ce1a2SMatthew G. Knepley 
322184ce1a2SMatthew G. Knepley   Notes:
32304c51a94SMatthew G. Knepley   The caller must free the returned name.
324258ec3d2SMatthew G. Knepley 
325184ce1a2SMatthew G. Knepley   In order to be dynamically loadable, the symbol has to be exported as such.  On many UNIX-like
326184ce1a2SMatthew G. Knepley   systems this requires platform-specific linker flags.
32710699b91SBarry Smith 
32821532e8aSBarry Smith .seealso: `PetscDLClose()`, `PetscDLSym()`, `PetscDLOpen()`, `PetscDLLibrary`, `PetscLoadDynamicLibrary()`, `PetscDLLibraryAppend()`,
32921532e8aSBarry Smith           `PetscDLLibraryRetrieve()`, `PetscDLLibraryOpen()`, `PetscDLLibraryClose()`, `PetscDLLibrarySym()`
330184ce1a2SMatthew G. Knepley @*/
331d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDLAddr(void (*func)(void), char **name)
332d71ae5a4SJacob Faibussowitsch {
333184ce1a2SMatthew G. Knepley   PetscFunctionBegin;
3344f572ea9SToby Isaac   PetscAssertPointer(name, 2);
335184ce1a2SMatthew G. Knepley   *name = NULL;
336e8953f01SSatish Balay #if defined(PETSC_HAVE_DLADDR) && !(defined(__cray__) && defined(__clang__))
337184ce1a2SMatthew G. Knepley   dlerror(); /* clear any previous error */
338184ce1a2SMatthew G. Knepley   {
339184ce1a2SMatthew G. Knepley     Dl_info info;
340184ce1a2SMatthew G. Knepley 
3415f80ce2aSJacob Faibussowitsch     PetscCheck(dladdr(*(void **)&func, &info), PETSC_COMM_SELF, PETSC_ERR_LIB, "Failed to lookup symbol: %s", dlerror());
342258ec3d2SMatthew G. Knepley   #ifdef PETSC_HAVE_CXX
3439566063dSJacob Faibussowitsch     PetscCall(PetscDemangleSymbol(info.dli_sname, name));
344258ec3d2SMatthew G. Knepley   #else
3459566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(info.dli_sname, name));
346258ec3d2SMatthew G. Knepley   #endif
347184ce1a2SMatthew G. Knepley   }
348184ce1a2SMatthew G. Knepley #endif
3493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
350184ce1a2SMatthew G. Knepley }
351