What is __gxx_personality_v0 for?

C++GccLinkerKernel

C++ Problem Overview


This is a second-hand question from an OS development site, but it made me curious since I couldn't find a decent explanation anywhere.

When compiling and linking a free-standing C++ program using gcc, sometimes a linker error like this occurs:

out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'

This is apparently because this symbol is defined in libstdc++, which is missing in a free-standing environment. Fixing the problem simply requires defining this symbol somewhere:

void *__gxx_personality_v0;

Which is nice, but I don't like things that just magically work... So the question is, what is the purpose of this symbol?

C++ Solutions


Solution 1 - C++

It is used in the stack unwiding tables, which you can see for instance in the assembly output of https://stackoverflow.com/questions/307610/how-do-exceptions-work-behind-the-scenes-in-c#307716">my answer to another question. As mentioned on that answer, its use is defined by the https://itanium-cxx-abi.github.io/cxx-abi">Itanium C++ ABI, where it is called the https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base-personality">Personality Routine.

The reason it "works" by defining it as a global NULL void pointer is probably because nothing is throwing an exception. When something tries to throw an exception, then you will see it misbehave.

Of course, if nothing is using exceptions, you can disable them with -fno-exceptions (and if nothing is using RTTI, you can also add -fno-rtti). If you are using them, you have to (as other answers already noted) link with g++ instead of gcc, which will add -lstdc++ for you.

Solution 2 - C++

It's part of the exception handling. The gcc EH mechanism allows to mix various EH models, and a personality routine is invoked to determine if an exception match, what finalization to invoke, etc. This specific personality routine is for C++ exception handling (as opposed to, say, gcj/Java exception handling).

Solution 3 - C++

Exception handling is included in free standing implementations.

The reason of this is that you possibly use gcc to compile your code. If you compile with the option -### you will notice it is missing the linker-option -lstdc++ when it invokes the linker process . Compiling with g++ will include that library, and thus the symbols defined in it.

Solution 4 - C++

A quick grep of the libstd++ code base revealed the following two usages of __gx_personality_v0:

In libsupc++/unwind-cxx.h

// GNU C++ personality routine, Version 0.                                      
extern "C" _Unwind_Reason_Code __gxx_personality_v0
     (int, _Unwind_Action, _Unwind_Exception_Class,
      struct _Unwind_Exception *, struct _Unwind_Context *);

In libsupc++/eh_personality.cc

#define PERSONALITY_FUNCTION    __gxx_personality_v0
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
                      _Unwind_Action actions,
                      _Unwind_Exception_Class exception_class,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
{
  // ... code to handle exceptions and stuff ...
}

(Note: it's actually a little more complicated than that; there's some conditional compilation that can change some details).

So, as long as your code isn't actually using exception handling, defining the symbol as void* won't affect anything, but as soon as it does, you're going to crash - __gxx_personality_v0 is a function, not some global object, so trying to call the function is going to jump to address 0 and cause a segfault.

Solution 5 - C++

I had this error once and I found out the origin:

I was using a gcc compiler and my file was called CLIENT.C despite I was doing a C program and not a C++ program.

gcc recognizes the .C extension as C++ program and .c extension as C program (be careful to the small c and big C).

So I renamed my file CLIENT.c program and it worked.

Solution 6 - C++

The answers above are correct: it is used in exception handling. The manual for GCC version 6 has more information (which is no longer present in the version 7 manual). The error can arise when linking an external function that - unknown to GCC - throws Java exceptions.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBruce JohnstonView Question on Stackoverflow
Solution 1 - C++CesarBView Answer on Stackoverflow
Solution 2 - C++Martin v. LöwisView Answer on Stackoverflow
Solution 3 - C++Johannes Schaub - litbView Answer on Stackoverflow
Solution 4 - C++Adam RosenfieldView Answer on Stackoverflow
Solution 5 - C++jlguenegoView Answer on Stackoverflow
Solution 6 - C++sagittaView Answer on Stackoverflow