Actual source code: demangle.c

  1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for and RTLD_* */
  2: #include <petsc/private/petscimpl.h>

  4: #if defined(PETSC_HAVE_DLFCN_H)
  5:   #include <dlfcn.h>
  6: #endif

  8: #if defined(__cplusplus) && defined(PETSC_HAVE_CXXABI_H)
  9:   #include <cxxabi.h>
 10: #endif

 12: /*@C
 13:   PetscDemangleSymbol - Convert a C++-mangled symbol name to its human-readable form using `abi::__cxa_demangle()` when available

 15:   Not Collective

 17:   Input Parameter:
 18: . mangledName - the mangled symbol name (typically obtained from `dladdr()`)

 20:   Output Parameter:
 21: . name - newly-allocated, null-terminated demangled name; caller must `PetscFree()` it

 23:   Level: developer

 25:   Note:
 26:   When no demangler is available (or when `mangledName` is `NULL`), `name` is set to `NULL`.

 28: .seealso: `PetscStackView()`, `PetscStackPrint()`
 29: @*/
 30: PetscErrorCode PetscDemangleSymbol(const char mangledName[], char **name)
 31: {
 32:   char *(*cxa_demangle)(const char *, char *, size_t *, int *) = PETSC_NULLPTR;
 33:   char *newname;
 34:   int   status;

 36:   PetscFunctionBegin;
 37:   if (mangledName) PetscAssertPointer(mangledName, 1);
 38:   PetscAssertPointer(name, 2);

 40:   *name = PETSC_NULLPTR;
 41:   if (!mangledName) PetscFunctionReturn(PETSC_SUCCESS);

 43: #if defined(__cplusplus) && defined(PETSC_HAVE_CXXABI_H)
 44:   cxa_demangle = __cxxabiv1::__cxa_demangle;
 45: #endif

 47: #if defined(PETSC_HAVE_DLFCN_H) && defined(PETSC_HAVE_DLOPEN)
 48:   if (!cxa_demangle) {
 49:     void *symbol = PETSC_NULLPTR;
 50:   #if defined(PETSC_HAVE_RTLD_DEFAULT)
 51:     symbol = dlsym(RTLD_DEFAULT, "__cxa_demangle");
 52:   #endif
 53:     if (!symbol) {
 54:       int   mode   = 0;
 55:       void *handle = PETSC_NULLPTR;
 56:   #if defined(PETSC_HAVE_RTLD_LAZY)
 57:       mode |= RTLD_LAZY;
 58:   #endif
 59:   #if defined(PETSC_HAVE_RTLD_LOCAL)
 60:       mode |= RTLD_LOCAL;
 61:   #endif
 62:   #if defined(PETSC_HAVE_RTLD_NOLOAD)
 63:       mode |= RTLD_NOLOAD;
 64:   #endif
 65:   #ifdef __APPLE__
 66:       if (!handle) handle = dlopen("libc++.1.dylib", mode);
 67:   #else
 68:       if (!handle) handle = dlopen("libstdc++.so.6", mode);
 69:   #endif
 70:       if (handle) {
 71:         symbol = dlsym(handle, "__cxa_demangle");
 72:         dlclose(handle);
 73:       }
 74:     }
 75:     *(void **)(&cxa_demangle) = symbol;
 76:   }
 77: #endif

 79:   if (!cxa_demangle) {
 80:     PetscCall(PetscStrallocpy(mangledName, name));
 81:     PetscFunctionReturn(PETSC_SUCCESS);
 82:   }

 84:   newname = cxa_demangle(mangledName, PETSC_NULLPTR, PETSC_NULLPTR, &status);
 85:   if (status) {
 86:     PetscCheck(status != -1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate memory for symbol %s", mangledName);
 87:     PetscCheck(status == -2, PETSC_COMM_SELF, PETSC_ERR_LIB, "Demangling failed for symbol %s", mangledName);
 88:     /* Mangled name is not a valid name under the C++ ABI mangling rules */
 89:     PetscCall(PetscStrallocpy(mangledName, name));
 90:     PetscFunctionReturn(PETSC_SUCCESS);
 91:   }
 92:   PetscCall(PetscStrallocpy(newname, name));
 93:   free(newname);
 94:   PetscFunctionReturn(PETSC_SUCCESS);
 95: }