3

I want to programmatically mangle the name of a C++ function or variable - to get the symbol name which would appear in a compiled object file. I'm using Linux and GCC.

Now, why is this not trivial? e.g. typeid(foo).name()? Because that doesn't do what you want: Consider the following program:

#include <iostream>

extern int foo(int x) { return 0; }
extern double bar(int x) { return 1.0; }

int main()
{
    std::cout << typeid(foo).name() << std::endl;
    std::cout << typeid(bar).name() << std::endl;
}

Let's see what that gives us:

$ g++ -o a.o -O0 -c a.cpp
$ objdump  -t a.o | egrep "(bar|foo)"
00000000000000dd l     F .text  0000000000000015 _GLOBAL__sub_I__Z3fooi
0000000000000000 g     F .text  000000000000000e _Z3fooi
000000000000000e g     F .text  000000000000001b _Z3bari
$ ./a
FiiE
FiiE

Not at all the same thing.

Notes:

  • Were you thinking of namespace abi? So was I. The source doesn't seem to do mangling, only demangling.
  • Solutions for the same problem on other platform+compiler combinations are also interesting, and if you have them I'll expand the question scope.
  • Motivation: I want to dlsym() a non-extern-C function or a variable.
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    Looks like a solution to another issue you are having (like linking to some other code). What is that problem? C++ api's are not really that great for linking, for various reasons. So most of the times you're just better of by giving a C++ library an "C" or R interface which is more maintainable – Pepijn Kramer Jun 04 '22 at 07:46
  • @PepijnKramer: See added note on the motivation. The point is that the source code of what goes into the object file is not under my control, so it won't be extern-C'ed. – einpoklum Jun 04 '22 at 07:50
  • There is no requirement in the standard that `typeid()` give a mangled name - it is only specified that `typeid(x)` and `typeid(y)` compare equal if they are the same type (or expressions that result in the same type) - otherwise the result (e.g. of `typeid().name()`) is implementation-defined. Similarly, the mangling scheme is implementation-defined. For g++ in particular (versions that support the Itanium IA64 ABI specification) have a look at https://stackoverflow.com/questions/41524956/gcc-c-name-mangling-reference – Peter Jun 04 '22 at 08:02
  • @Peter: Indeed, if the standard required it, `typeid()` would work. It doesn't, so it doesn't. But - what _can_ I do, instead? – einpoklum Jun 04 '22 at 08:17
  • The only solution is to inspect the exported name(s) and hardcode the value. Note that there is no ABI compatibility across different compilers. For different versions of the same compiler you need to check the vendors documentation for ABI compatibility. – Richard Critten Jun 04 '22 at 08:21
  • You've got a way of getting the mangled names; You got a way of converting the mangled name into an unmangled name. If no other option presents itself, you could just add a tool that just demangles every symbol and generates a header containing the information about the mangled names for those functions you're interested in to your build script... – fabian Jun 04 '22 at 08:25
  • Your two options are to either write suitable `extern "C"` wrappers for functions in your library (which does away with worrying about name mangling, but does rely on compatibility your compiler offers with C naming and call conventions - but fortunately, such compatibility is common in practice on each platform) or [more difficult] emulate your compiler's mangling scheme (answers to the question I linked previously offer a start to that - for some versions of g++ at least). I suggest the `extern "C"` wrapper is less complicated. – Peter Jun 04 '22 at 08:28
  • @RichardCritten: 1. The question is about specific platform+compiler combinations, of course this is ABI specific. 2. I'm not sure what you mean about "inspecting exported names". Can you elaborate in an answer? – einpoklum Jun 04 '22 at 08:28
  • @Peter: I don't have source code, I have a compiled object. – einpoklum Jun 04 '22 at 08:30
  • @einpoklum there are online name demanglers (I suspect they use standard tools with a simple web interface) that will give you the function definition. – Richard Critten Jun 04 '22 at 08:37
  • @einpoklum Then you need the `extern "C"` wrapper route - write a set of `extern "C"` functions that provide an external interface, and the implementation of those functions handles the mapping of arguments and return types to/from functions in your compiled object. The wrapper code will need to be built with the same compiler (preferably the same compiler version, but same ABI is enough) as your compiled object. So your program (presumably) that needs functionality of your compiled object only ever calls functions in your wrapper. – Peter Jun 04 '22 at 08:40
  • @Peter: Again, this is not my code. I don't even know apriori which DLL is going to be loaded. If I did, I could just hard-code a symbol names map or something. – einpoklum Jun 04 '22 at 09:04
  • Are the names (and declarations) of functions-in-question known iin compile-time? If yes, you don't need dlsym, just `extern foobar(someparams)` and the linker will solve the rest. – Lorinczy Zsigmond Jun 04 '22 at 09:37
  • @LorinczyZsigmond: Well, the declarations _are_ known at compile time, but the linker works before the program starts running while the library is only loaded _after_ the program has started running. – einpoklum Jun 04 '22 at 17:10

0 Answers0