问题
Is it that the absence or damage of the .eh_frame ELF section is the cause of exceptions in my C++ code stopped working? Any exception that previously was caught successfully is now calling std::terminate().
My situation:
My zzz.so shared library has try-catch blocks:
try { throw Exc(); } catch (const Exc &e) { LOG("ok " << e.what()); } catch (...) { LOG("all"); }
An executable which loads the zzz.so (using ldopen). It call a function in the zzz.so
- All the exceptions thrown in the zzz.so are successfully caught inside zzz.so and dumped into my log file
- There is another aaa.so that is loaded into another binary. That another aaa.so is loading my zzz.so.
- All the same exceptions thrown in the zzz.so lead to call std::terminate().
How is that possible?
update
I don't know HOW is that possible still, but Clang 3.3 (FreeBSD clang version 3.3 (tags/RELEASE_33/final 183502) 20130610) solved the problem.
回答1:
How is that possible?
When an exception is thrown, control passes to __cxa_throw
routine (usually in libstdc++.so
), which is then responsible for finding the catch
clause and calling destructors along the way, or calling std::terminate
if no catch
is found.
The answer then is most likely that the first executable (the one where exceptions work) uses libstdc++.so
that is capable of decoding .eh_frame
in your library, while the second application (the one where exceptions do not work), either uses an older (incompatible) version of libstdc++.so
, or links against libstdc++.a
, or something along these lines.
Note: the actual work of raising the exception is done by _Unwind_RaiseException
in libgcc_s.so.1
, so even if both applications use the same libstdc++.so
, they may still use different libgcc
.
Update:
Will I benefit from static linking libstdc++ and libgcc into my .so library?
Maybe. TL;DR: it's complicated.
There are a few things to consider:
On any platform other than i386, you would have to build your own copy of
libstdc++.a
andlibgcc.a
with-fPIC
before you can link them into yourzzz.so
. Normally these libraries are built without-fPIC
, and can't be statically linked into any.so
.Static linking of
libstdc++.a
into yourzzz.so
may make it a derived work, and subject to GPL (consult your lawyer).Even when there is a
_Unwind_RaiseException
exported fromzzz.so
, normally there will already be another instance of_Unwind_RaiseException
defined in (loaded earlier)libgcc_s.so
, and that earlier instance is the one that will be called, rendering your workaround ineffective. To make sure that your copy of_Unwind_RaiseException
is called, you would need to linkzzz.so
with-Bsymbolic
, or with a special linker script to make all calls to_Unwind_RaiseException
(and everything else fromlibgcc.a
) internal.Your workaround may fix the problem for
zzz.so
, but may cause a problem for unrelatedyyy.so
that is loaded even later, and that wants the system-provided_Unwind_RaiseException
, not the one fromzzz.so
. This is another argument for hiding alllibgcc.a
symbols and making them internal tozzz.so
.
So the short answer is: such workaround is somewhat likely to cause you a lot of pain.
来源:https://stackoverflow.com/questions/33035051/c-exceptions-and-the-eh-frame-elf-section