Opened 12 years ago

Closed 10 years ago

Last modified 5 years ago

#4594 closed Patches (fixed)

Boost exception classes do not have GCC default visibility

Reported by: Jonathan Jones <jonathan.jones@…> Owned by: Emil Dotchevski
Milestone: To Be Determined Component: exception
Version: Boost 1.47.0 Severity: Showstopper
Keywords: Cc: ejt@…

Description

All of the boost exception classes, including but not necessarily limited to:

  • boost::exception
  • boost::unknown_exception
  • boost::exception_detail::clone_base

do not have visibility attributes associated with them. This means that, when files are built using GCC with -fvisibility=hidden, classes derived from these types become uncatchable as these types when thrown across library boundaries.

Attachments (4)

boost_visibility.tar (10.0 KB ) - added by Jonathan Jones <jonathan.jones@…> 12 years ago.
Isolated reproduction code.
exception.patch (514 bytes ) - added by Dimitrij Drus <dadrus@…> 11 years ago.
Patch for boost/exception/exception.hpp file
boost_visibility.2.tar (8.5 KB ) - added by Jonathan Jones <jonathan.jones@…> 11 years ago.
Updated test case, including showing the fact that error_info/get_error_info also have symbol visibility issues.
thread_visibility.diff (2.1 KB ) - added by Ethan Tira-Thompson <ejt@…> 11 years ago.
Patch to support visibility with thread module

Download all attachments as: .zip

Change History (27)

by Jonathan Jones <jonathan.jones@…>, 12 years ago

Attachment: boost_visibility.tar added

Isolated reproduction code.

comment:1 by Jonathan Jones <jonathan.jones@…>, 12 years ago

Would it be possible to get an update as to the status of this bug?

comment:2 by Vicente Botet <vicente.botet@…>, 12 years ago

Type: BugsPatches

comment:3 by Emil Dotchevski, 12 years ago

Resolution: fixed
Status: newclosed

comment:4 by Dimitrij Drus, 11 years ago

I just moved to the 1.46.1 version of boost. It still lacks the visibility support for boost::exception. The trunk has corresponding adjustments, which however are not complete. Within the exception.hpp there is a forward declaration of the exception class. Without surrounding this forward declaration with GCC visibility pragmas too, the boost::exception can't be catched if throwed across the shared lib boundaries.

The behaviour was observed on Ubuntu 10.04 with gcc version 4.4.3.

comment:5 by Emil Dotchevski, 11 years ago

Thanks for the feedback Dimitrij.

Have you verified that surrounding the forward declaration with visibility pragmas solves the problem? I don't have an easy way to test this so I'd appreciate a patch that is tested to work.

comment:6 by Dimitrij Drus <dadrus@…>, 11 years ago

Yes. Catching boost::exception thrown over the shared library boundaries is only possible after surrounding the forward declaration with the visibility pragmas. Patch is attached.

One can use the test attached by Jonathan to verify this. Jonathan, however, expects the class boost::exception_detail::clone_base be exported (surrounded with gcc visibility pragmas) too, that's why corresponding test cases fail.

Regards Dimitrij

by Dimitrij Drus <dadrus@…>, 11 years ago

Attachment: exception.patch added

Patch for boost/exception/exception.hpp file

comment:7 by Dimitrij Drus <dadrus@…>, 11 years ago

If one has troubles launching Jonathan's test, one should add -Wl,-rpath,'$ORIGIN' to the last line of the make file. In my case the libboost_visibility.so was not found without this modification.

I hope it is not too late to apply the path for the coming release.

Regards Dimitrij

by Jonathan Jones <jonathan.jones@…>, 11 years ago

Attachment: boost_visibility.2.tar added

Updated test case, including showing the fact that error_info/get_error_info also have symbol visibility issues.

comment:8 by Jonathan Jones <jonathan.jones@…>, 11 years ago

It's not enough to ensure that boost::exception, boost::exception_detail::clone_base, and boost::unknown_exception have default symbol visibility on GCC. It appears that boost::error_info also needs to be decorated with default visibility. Otherwise, calls to get_error_info on exceptions propagated across library boundaries will always return NULL, rendering boost::exception essentially useless.

comment:9 by Dimitrij Drus <dadrus@…>, 11 years ago

Why should one be interested in catching boost::exception_detail::clone_base? Its just an internal detail. Either one want catch an own exception or the boost one.

comment:10 by Jonathan Jones <jonathan.jones@…>, 11 years ago

You aren't interested in catching it directly. However, the implementation of boost::current_exception re-throws the exception and catches it as exception_detail::clone_base to determine if it's "cloneable". If exception_detail::clone_base doesn't have default visibility, boost::current_exception doesn't work if the exception originated from a different library.

comment:11 by mark.schisler@…, 11 years ago

This bug is actually causing X-Code 4.01 and LLVM/GCC 4.2 to not link Boost 1.46.1 correctly with or without symbols hidden. I ended up with the following linker error.

ld: bad codegen, pointer diff in boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error> >::rethrow() constto global weak symbol vtable for boost::exceptionfor architecture i386
collect2: ld returned 1 exit status

I'm not sure if it's a minimal solution or not, but I was able to resolve the problem by applying a fix similar to what was suggested by Jonathan. I enclosed exception/exception.hpp and exception/detail/exception_ptr.hpp in the following guards:

#if defined(__GNUC__) 
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 
#  pragma GCC visibility push (default) 
# endif
#endif

#if defined(__GNUC__) 
# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) 
#  pragma GCC visibility pop 
# endif
#endif

comment:12 by Ethan Tira-Thompson <ejt@…>, 11 years ago

Cc: ejt@… added
Resolution: fixed
Status: closedreopened
Version: Boost 1.40.0Boost 1.47.0

I confirm Mark's error, I see the same error also with Boost 1.47 (building Ogre3D on Xcode 4, gcc 4.2.1).

I notice some visibility stuff was added to exception.hpp, but this is not enough. Apparently, error_info_injector and clone_impl (in exception/exception.hpp) both need to be wrapped with visibility pragmas in order to fix that error.

Further, thread/exceptions.hpp also needs to be wrapped with visibility, or you will get:

ld: bad codegen, pointer diff in boost::thread_exception::thread_exception()to global weak symbol vtable for boost::thread_exceptionfor architecture i386

by Ethan Tira-Thompson <ejt@…>, 11 years ago

Attachment: thread_visibility.diff added

Patch to support visibility with thread module

comment:13 by Ethan Tira-Thompson <ejt@…>, 11 years ago

Also, I'm not confident about the current visibility settings in exception. Will there be further linkage issues for other projects which use different features of boost?

Perhaps the visibility pragmas should be wrapped around the all of the header contents for exception.hpp and exception_ptr.hpp as Mark suggested to ensure this isn't an ongoing issue. (This doesn't look to be an excessive amount of additional visible symbols, worth the margin of safety?)

comment:14 by Emil Dotchevski, 11 years ago

I am against making all classes visible. There aren't that many types that need to be visible. The first thing we need is a formal test in libs/exception/test. Can someone help writing this, so I can see all failures that need to be fixed on various platforms?

comment:15 by ian.esten@…, 11 years ago

I was having this problem with a dylib using boost::thread that linked to another dylib using boost::thread. The thread_visibility.diff patch solved the problem for me.

in reply to:  15 comment:16 by Emil Dotchevski, 11 years ago

I've committed only the Boost Exception part of thread_visibility.diff patch (that is, without the Boost Thread part of it.) Out of curiosity, do we really need the error_info_injector type to be visible? I don't understand why it is needed, but I haven't tested.

Anyone care to add a test program to verify that visibility settings work across different platforms?

comment:17 by shreyas.bme@…, 11 years ago

Hi,

I am getting following error. Please guide me.

Boost version: 1_45_0

/ERROR LOGS/

ld: bad codegen, pointer diff in boost::signals::connection::connection(boost::signals::connection const&)to global weak symbol boost::detail::spinlock_pool<1>::pool_ for architecture armv7 collect2: ld returned 1 exit status Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/g++-4.2 failed with exit code 1

comment:18 by Emil Dotchevski, 11 years ago

Um, this doesn't seem to have anything to do with ticket 4594?

comment:19 by shreyas.bme@…, 11 years ago

Nope. Do you know solution? Please let me know.

comment:20 by Emil Dotchevski, 10 years ago

Resolution: fixed
Status: reopenedclosed

I'm closing this, please reopen if visibility on some platform(s) is a problem.

comment:21 by anonymous_but_0X, 8 years ago

Hello everyone,

hope you had a good weekend, I am afraid the problem is back, moving from LLVM xcode 4.4.1 to Apple LLVM 6.0 (10.9), I got it again, but I think I am not the only one.

"boost::exception_detail::error_info_injector <boost::gregorian::bad_month>::error_info_injector(boost::exception_detail::error_info_injector<boost::gregorian::bad_month> const&) to global weak symbol vtable for boost::exception_detail::error_info_injector<boost::gregorian::bad_month> means the weak symbol cannot be overridden at runtime. This was likely caused by different translation units being compiled with different visibility settings."

the mysterious thin, and I think I need to question Ted Kremenek, because with the previous LD/compiler everything was fine according to their static analyzer, moving to the next version tool makes it incompatible, weak symbols that's just a convention how you stored them, Kremenek should use its magic wand and give solution.r

comment:22 by logens dou <logens@…>, 5 years ago

Hi:

i worked with boost1_58_0,it accors some error by compiled.please give me some suggest,thanks.

errors:

boost/asio/handler_type.hpp:20 boost/asio/detail/push_options.hpp:71:11: error :'pragma' is not allowed here

#pragma GCC visibility push(default)

boost/asio/detail/pop_options.hpp:71:11: error :expected decalration before end of line

comment:23 by Emil Dotchevski, 5 years ago

Which compiler?

Note: See TracTickets for help on using tickets.