Wednesday, June 8, 2011

ld: bad codegen, pointer diff in boost::detail::sp_counted_base::sp_counted_base

Trying to build an iOS project with XCode 4:

- boost built as a framework
- a static library
- the iOS app

which gives the above error. I get the same behavior no matter which compiler I select (gcc, gcc-llvm, clang), which makes a little sense since it's a linker error.

A little (lot) of googling finds a lot of suggestions to play with the compiler visibility flags. Some people say enable, others disable. The short answer is, yes, this is how I fixed things. But just messing with symbol visibility without understanding the problem rubs me the wrong way, especially when the oh-so-useful but oh-so-frightening boost is involved.


First, I gather that when the linker (ld) says "bad codegen", something has gone very wrong. This isn't your average "oops I forgot to define something" kind of error. There is no documentation of this error that I can find ... dead end.

So I did some reading on the -fvisibility option. The short version is that passing -fvisibility=hidden to gcc causes it to mark by default all symbols as "hidden" in a resulting shared library elf file (dso, dll).

I only have two static libs (boost and my own) and my app, so I think this shouldn't be related to my problem... but it is.

Taking a look at boost.sh, the script by Pete Goodliffe referenced above, I find:

/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -arch armv7 -mthumb -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS

for the iphone (device) build and

/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc-4.2 -arch i386 -fvisibility=hidden -fvisibility-inlines-hidden $EXTRA_CPPFLAGS

for the simulator build. So boost is built with symbols marked hidden by default. Checking my project configs shows that I had mixed settings for visibility. Changing these all to be the same (hidden) fixed the link errors.

My guess is that this is a linker bug. Perhaps a weak symbol defined in a static lib marked with one visibility and then again in the product or a different static lib with another visibility is confusing the linker? Other strange behavior seems to imply less than rock-solid stability here.

Several people have noticed that behavior is different for 32-bit and 64-bit builds on Mac OS. Symbol Visibility and Objective-C on apple's dev site may shed some light on that situation.


Some reading:

Visibility - GCC Wiki
Why symbol visibility is good : technovelty
C++ Runtime Environment Programming Guide: Controlling Symbol Visibility


1 comment: