Reputation: 8634
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?
Upvotes: 114
Views: 117244
Reputation: 400364
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.
Upvotes: 7
Reputation: 21
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.
Upvotes: 2
Reputation: 45565
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.
Upvotes: 105
Reputation: 1301
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.
Upvotes: 6
Reputation: 507065
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.
Upvotes: 13
Reputation: 127467
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).
Upvotes: 13