Saturday, July 14, 2012

gcc name demangling

According to wikipedia, name mangling is a "way of encoding additional information in the name of a function, structure, class or another datatype in order to pass more semantic information from the compilers to linkers".

The need for name mangeling arises because the name of a symbol in a file is very restricted. It can not contain spaces, brackets or columns, for example. With name mangling, the linker is able to distinguish overloaded functions in C++ like
int bla();
int bla(double);
The wikipedia article and this describe name mangling quite well.

You'll see a lot of mangled names when you try
nm someexecutable

So I created a small C++ program demangles the names. Save below code in a file named mydemangle.cpp, and compile it with
g++ -o mydemangle mydemangle.cpp

Now you can try it with
mydemangle _ZN9wikipedia7article6formatEv
and the result is

But demangle can do more: It can read input from stdin. So you might try
nm someexecutable | mydemangle 

Now mydemangle demangles all names it can demangle and leaves the rest as it is.

There's a quite handy way in C++ to demangle names via the function
char * __cxa_demangle (const char *mangled_name, char *output_buffer, size_t *length, int *status);

Be aware that this will not be available for all processors/compilers.

Here's the code:


#include <iostream>
#include <cxxabi.h>
#include <stdlib.h>
#include <string>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
    int status;
    if(argc == 2)
        // we have one argument: demangle it
        char *realname = abi::__cxa_demangle(argv[1], 0, 0, &status);
            cout << "\n" << realname << "\n";
            cout << "\ncould not demangle " << argv[1] << "\n";
        // we have no argument: read from stdin
        char c, lastc=0x00;
        string s;
        while((c = getchar()) != EOF)
            // mangled names start with _ . consider only if last sign was space or tab or newline
            if(c == '_' && (lastc==' ' || lastc == '\n' || lastc == '\t'))
                s = "_";
                // add all characters to the string until space, tab or newline
                while((c = getchar()) != EOF)
                    if(c == ' ' || c == '\n' || c == '\t')
                    s += c;
                // some compilers add an additional _ in front. skip it.
                const char *p = s.c_str();
                if(s.length() > 2 && s[1] == '_') p = p+1;
                char *realname = abi::__cxa_demangle(p, 0, 0, &status);
                    cout << realname; // demangle successfull
                    cout<< s; // demangling failed, print normal string
            cout << c;
            lastc =c;
    return 0;

Of course, there is some easy way in bash to do it. This requires demangle (part of KDE Dev Kit) and is not as fast and convenient as above method.
while read LINE
    for WORD in $LINE
 echo -n $WORD | demangle

No comments:

Post a Comment