What is __gxx_personality_v0 for?
Asked Answered
D

6

114

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?

Drunkometer answered 30/11, 2008 at 16:53 Comment(1)
With the msys2 msys version of clang++, I tried defining this symbol in main.cpp and it did not resolve the problem - it lead to a different error: clang++: error: clang frontend command failed due to signal (use -v to see invocation).Vinavinaceous
F
105

It is used in the stack unwiding tables, which you can see for instance in the assembly output of my answer to another question. As mentioned on that answer, its use is defined by the Itanium C++ ABI, where it is called the 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.

Frustum answered 30/11, 2008 at 19:0 Comment(1)
Thanks for the tip about -fno-exceptions. I added CPPFLAGS += -fno-exceptions to my makefile, and that solved the error.Landward
N
13

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).

Novelize answered 30/11, 2008 at 17:27 Comment(0)
F
13

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.

Freemasonry answered 30/11, 2008 at 18:28 Comment(2)
I always thought compiling with g++ was only needed when you specifically wanted to tell the compiler that the code was C++ (for example- missing extension). Now it seems that compiling C++ code with gcc misses inclusion of come libraries. Apart from missing some libraries, are there some other "side-effects" of compiling my file.cpp with gcc instead of g++?Objection
@eSkay as far as i know, the linking of libstdc++ is the only difference between the two.Freemasonry
N
7

A quick grep of the libstd++ code base revealed the following two usages of __gxx_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.

Nilson answered 30/11, 2008 at 17:35 Comment(5)
Not necessarily jump to 0; the global is uninitialized so it could be any value, really.Erectile
strager, globals are zero initialized if the programmer doesn't initialize themFreemasonry
@litb: this is only true if the kernel implements zeroing the bss section :-P. But yes, they should be 0 initialized for sanity sake.Hallucinate
@Evan Teran: No, a conforming C implementation will always initialize globals to 0. See §5.1.2 and §6.7.8 paragraph 10 of the C99 standard.Nilson
Do you have a github/sourceforge link for the codebase?Vinavinaceous
F
6

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.

Faustinafaustine answered 16/7, 2014 at 7:36 Comment(0)
B
2

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.

Bevus answered 3/3, 2018 at 21:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.