xref: /petsc/src/sys/dll/demangle.c (revision a28344a5144139f565b3604164979954db19997e)
1 #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for and RTLD_* */
2 #include <petsc/private/petscimpl.h>
3 
4 #if defined(PETSC_HAVE_DLFCN_H)
5   #include <dlfcn.h>
6 #endif
7 
8 #if defined(__cplusplus) && defined(PETSC_HAVE_CXXABI_H)
9   #include <cxxabi.h>
10 #endif
11 
PetscDemangleSymbol(const char mangledName[],char ** name)12 PetscErrorCode PetscDemangleSymbol(const char mangledName[], char **name)
13 {
14   char *(*cxa_demangle)(const char *, char *, size_t *, int *) = PETSC_NULLPTR;
15   char *newname;
16   int   status;
17 
18   PetscFunctionBegin;
19   if (mangledName) PetscAssertPointer(mangledName, 1);
20   PetscAssertPointer(name, 2);
21 
22   *name = PETSC_NULLPTR;
23   if (!mangledName) PetscFunctionReturn(PETSC_SUCCESS);
24 
25 #if defined(__cplusplus) && defined(PETSC_HAVE_CXXABI_H)
26   cxa_demangle = __cxxabiv1::__cxa_demangle;
27 #endif
28 
29 #if defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
30   if (!cxa_demangle) {
31     void *symbol = PETSC_NULLPTR;
32   #if defined(PETSC_HAVE_RTLD_DEFAULT)
33     symbol = dlsym(RTLD_DEFAULT, "__cxa_demangle");
34   #endif
35     if (!symbol) {
36       int   mode   = 0;
37       void *handle = PETSC_NULLPTR;
38   #if defined(PETSC_HAVE_RTLD_LAZY)
39       mode |= RTLD_LAZY;
40   #endif
41   #if defined(PETSC_HAVE_RTLD_LOCAL)
42       mode |= RTLD_LOCAL;
43   #endif
44   #if defined(PETSC_HAVE_RTLD_NOLOAD)
45       mode |= RTLD_NOLOAD;
46   #endif
47   #ifdef __APPLE__
48       if (!handle) handle = dlopen("libc++.1.dylib", mode);
49   #else
50       if (!handle) handle = dlopen("libstdc++.so.6", mode);
51   #endif
52       if (handle) {
53         symbol = dlsym(handle, "__cxa_demangle");
54         dlclose(handle);
55       }
56     }
57     *(void **)(&cxa_demangle) = symbol;
58   }
59 #endif
60 
61   if (!cxa_demangle) {
62     PetscCall(PetscStrallocpy(mangledName, name));
63     PetscFunctionReturn(PETSC_SUCCESS);
64   }
65 
66   newname = cxa_demangle(mangledName, PETSC_NULLPTR, PETSC_NULLPTR, &status);
67   if (status) {
68     PetscCheck(status != -1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate memory for symbol %s", mangledName);
69     PetscCheck(status == -2, PETSC_COMM_SELF, PETSC_ERR_LIB, "Demangling failed for symbol %s", mangledName);
70     /* Mangled name is not a valid name under the C++ ABI mangling rules */
71     PetscCall(PetscStrallocpy(mangledName, name));
72     PetscFunctionReturn(PETSC_SUCCESS);
73   }
74   PetscCall(PetscStrallocpy(newname, name));
75   free(newname);
76   PetscFunctionReturn(PETSC_SUCCESS);
77 }
78