Statically-linking libstdc++ on AIX
Sunday, December 10th, 2006Yesterday I spent the whole day trying to build a statically-linked binary of XSD for AIX. I have done this for numerous other platforms but on AIX the C++ exception handling stopped working once I linked libstdc++
in statically. I was lucky to detect this problem at all; the application appears to work just fine as long as there is no throw on the execution path. The fix is to also link libsupc++.a
in:
g++ -static-libgcc ... -Wl,-bstatic -lstdc++ -Wl,-bdynamic \ -lsupc++
If all you are looking for is the fix, then you can stop reading here. Read on if you want to know why we need libsupc++.a
. When your application is linked to a number of shared libraries, it is important that they all use the same exception handling runtime to allow exceptions to propagate across library boundaries. To ensure this, GCC places the exception handling runtime into a shared library called libgcc_s.so
(libgcc.a
on AIX) which is then used by all shared C++ libraries and executables, including libstdc++.so
.
The -static-libgcc
option instructs GCC to use a static equivalent of libgcc_s.so
called libgcc_eh.a
with the difference being that some of the exception handling code found in libgcc_s.so
is placed into the static libstdc++.a
(tell me if you know why). In other words, shared libstdc++.so
and static libstdc++.a
have a different amount of code in them. This fact is important to understand why things fail on AIX.
The second part of the problem is an eccentric shared library architecture implemented on AIX. In short, both shared libraries and static archives on AIX use the same file suffix—.a
. In fact, they are both archives. In such an archive there could be one or more shared object (which is just a normal XCOFF file with the SHROBJ
bit set) or normal object files. Furthermore, you can link a shared library (archive with shared objects) statically. That’s exactly what happens when you instruct g++
to link libstdc++.a
statically by using the -bstatic
linker option.
We can see the cause of the problem clearly now: we are linking shared libstdc++.a
statically but it is missing some of the exception handling code that a proper static libstdc++.a
would have. The libsupc++.a
is a subset of libstdc++.a
. It provides core language support without STL and streams. It also includes the exception handling code we need. That’s why linking this library fixes the problem.