summaryrefslogtreecommitdiff
path: root/src/typeinfo.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/typeinfo.cc')
-rw-r--r--src/typeinfo.cc51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/typeinfo.cc b/src/typeinfo.cc
index bd12a00..b0deb8b 100644
--- a/src/typeinfo.cc
+++ b/src/typeinfo.cc
@@ -43,3 +43,54 @@ ABI_NAMESPACE::__pbase_type_info::~__pbase_type_info() {}
ABI_NAMESPACE::__pointer_type_info::~__pointer_type_info() {}
ABI_NAMESPACE::__pointer_to_member_type_info::~__pointer_to_member_type_info() {}
+// From libelftc
+extern "C" char *__cxa_demangle_gnu3(const char *);
+
+/**
+ * Demangles a C++ symbol or type name. The buffer, if non-NULL, must be
+ * allocated with malloc() and must be *n bytes or more long. This function
+ * may call realloc() on the value pointed to by buf, and will return the
+ * length of the string via *n.
+ *
+ * The value pointed to by status is set to one of the following:
+ *
+ * 0: success
+ * -1: memory allocation failure
+ * -2: invalid mangled name
+ * -3: invalid arguments
+ */
+extern "C" char* __cxa_demangle(const char* mangled_name,
+ char* buf,
+ size_t* n,
+ int* status)
+{
+ // TODO: We should probably just be linking against libelf-tc, rather than
+ // copying their code. This requires them to do an actual release,
+ // however, and for our changes to be pushed upstream. We also need to
+ // call a different demangling function here depending on the ABI (e.g.
+ // ARM).
+ char *demangled = __cxa_demangle_gnu3(mangled_name);
+ if (NULL != demangled)
+ {
+ size_t len = strlen(demangled);
+ buf = (char*)realloc(buf, len+1);
+ if (0 != buf)
+ {
+ memcpy(buf, demangled, len);
+ buf[len] = 0;
+ *n = len;
+ *status = 0;
+ }
+ else
+ {
+ *status = -1;
+ }
+ free(demangled);
+ }
+ else
+ {
+ *status = -2;
+ return NULL;
+ }
+ return buf;
+}