19

I have previously, here, been shown that C++ functions aren't easily represented in assembly. Now I am interested in reading them one way or another because Callgrind, part of Valgrind, show them demangled while in assembly they are shown mangled.

So I would like to either mangle the Valgrind function output or demangle the assembly names of functions. Anyone ever tried something like that? I was looking at a website and found out the following:

Code to implement demangling is part of the GNU Binutils package; 
see libiberty/cplus-dem.c and include/demangle.h.

Has anyone ever tried something like that? I want to demangle/mangle in C.

My compiler is gcc 4.x.

Roberto Caboni
  • 7,252
  • 10
  • 25
  • 39
Syntax_Error
  • 5,964
  • 15
  • 53
  • 73
  • 3
    I don't understand your question - you already posted your own answer, use the code from binutils. There are similar libraries / code snippets for other toolchains, so where is the problem? – Jim Brissom Feb 08 '11 at 23:22
  • 3
    IIRC then valgrind already has a --demangle=yes option to demangle C++ symbols on output. Callgrind can be called as `valgrind --tool=callgrind --demangle=yes` then, can't it? – Nordic Mainframe Feb 08 '11 at 23:28
  • @Luther: I had opened another forum to check if I demangle vallgrind http://stackoverflow.com/questions/4846411/de-mangeling-in-callgrind but noone replied. I looked at the linux manual to demangle it didnt provide anything! your suggestion worked. thnks – Syntax_Error Feb 09 '11 at 00:47
  • The answers below only cover the demangle case. The mangle case is [c++ - Is it possible to mangle typename at runtime? - Stack Overflow](https://stackoverflow.com/questions/68109629/is-it-possible-to-mangle-typename-at-runtime) (**note** see the question linked from this question, and the question linked from *that* question too) – user202729 Dec 07 '21 at 01:24
  • For Python see https://stackoverflow.com/questions/6526500/c-name-mangling-library-for-python – user202729 Dec 13 '21 at 04:39

3 Answers3

28

Use the c++filt command line tool to demangle the name.

Eugen Constantin Dinca
  • 8,994
  • 2
  • 34
  • 51
  • 3
    Yes, that works on the command line. I believe the asker was looking for library functions that could be called from within the code. – Dave Aug 06 '14 at 03:19
  • It's the accepted the answer, so I think that answers the question about what the asker was looking for. – Eugen Constantin Dinca Aug 07 '14 at 03:48
  • 3
    It's all good, in fact I learned something new when I read your answer, so I certainly appreciate it. I added the 'from code' version below anyhow since that's what I came looking for based on the title of the question. I'm sure both answers will help someone. :) – Dave Aug 11 '14 at 02:43
  • I use, `sed -n a,bp file_name | c++filt` where `a` to `b` are the lines I want to demangle from `file_name` – Debashish Jul 21 '22 at 08:46
21

Here is my C++11 implementation, derived from the following page: http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html

#include <cxxabi.h>  // needed for abi::__cxa_demangle

std::shared_ptr<char> cppDemangle(const char *abiName)
{
  int status;    
  char *ret = abi::__cxa_demangle(abiName, 0, 0, &status);  

  /* NOTE: must free() the returned char when done with it! */
  std::shared_ptr<char> retval;
  retval.reset( (char *)ret, [](char *mem) { if (mem) free((void*)mem); } );
  return retval;
}

To make the memory management easy on the returned (char *), I'm using a std::shared_ptr with a custom lambda 'deleter' function that calls free() on the returned memory. Because of this, I don't ever have to worry about deleting the memory on my own, I just use it as needed, and when the shared_ptr goes out of scope, the memory will be free'd.

Here's the macro I use to access the demangled type name as a (const char *). Note that you must have RTTI turned on to have access to 'typeid'

#define CLASS_NAME(somePointer) ((const char *) cppDemangle(typeid(*somePointer).name()).get() )

So, from within a C++ class I can say:

printf("I am inside of a %s\n",CLASS_NAME(this));
Dave
  • 2,653
  • 4
  • 20
  • 22
  • 3
    Not bad. Could have made it `unique_ptr` though, or just construct a `std::string` of it and free() immediately. – sehe Sep 25 '14 at 07:44
  • 2
    Thanks sehe. :) I'll have to take a look at unique_ptr (haven't used them yet). I purposely didn't use the std::string / immediate free() approach so as to avoid the extra copy. That said, the performance hit probably wouldn't matter much -- I'm typically only using this for debug-printing, as opposed to any kind of speed-critical application. Anyhow, hopefully there's enough there for someone to customize the function to their own needs. – Dave Oct 01 '14 at 18:51
  • 2
    Thanks Dave. I just wanted to point out that if boost is available, there's a cleaner option via `boost/core/demangle.hpp`, as shown here: https://stackoverflow.com/a/34916852/1797414 – arr_sea Oct 29 '19 at 17:57
0

This is a slight variation on Dave's version above. This is a unique_ptr version with a little bit of checking on the return type, though it looks like you could just ignore that, but somehow that just seems unclean.

auto cppDemangle (const char *abiName)
{
    //
    // This function allocates and returns storage in ret
    //
    int status;
    char *ret = abi::__cxa_demangle(abiName, 0 /* output buffer */, 0 /* length */, &status);

    auto deallocator = ( [](char *mem) { if (mem) free((void*)mem); } );

    if (status) {
        // 0: The demangling operation succeeded.
        // -1: A memory allocation failure occurred.
        // -2: mangled_name is not a valid name under the C++ ABI mangling rules.
        // -3: One of the arguments is invalid.
        std::unique_ptr<char, decltype(deallocator) > retval(nullptr, deallocator);
        return retval;
    }

    //
    // Create a unique pointer to take ownership of the returned string so it
    // is freed when that pointers goes out of scope
    //
    std::unique_ptr<char, decltype(deallocator) > retval(ret, deallocator);
    return retval;
}
Goblinhack
  • 2,859
  • 1
  • 26
  • 26