C ++异常和.eh_frame ELF部分 [英] C++ exceptions and the .eh_frame ELF section
问题描述
是否是.eh_frame ELF部分的缺失或损坏是我的C ++代码中的异常停止工作的原因?任何以前被成功捕获的异常现在调用std :: terminate()。
我的情况:
<
我的zzz.so共享库有try-catch块:
$ b throw Exc();
} catch(const Exc& e){
LOG(ok<< e.what());
} catch(...){
LOG(all);
}
加载zzz.so(使用ldopen)的可执行文件。它调用zzz.so中的函数
如何实现?
更新
$ b
我不知道HOW是可能的,但Clang 3.3(FreeBSD clang版本3.3(标签/ RELEASE_33 / final 183502)20130610)解决了这个问题。
如何实现?
当抛出异常时,控制传递到 __ cxa_throw
例程(通常在 libstdc ++中,因此
),负责找到 catch
子句,然后调用析构函数或调用 std :: terminate
如果没有发现 catch
。
答案很可能是第一个可执行文件异常工作)使用 libstdc ++,因此
能够解码库中的 .eh_frame
,而第二个应用程序一个其中异常不工作),使用 libstdc ++的旧版本(不兼容)。
,或者链接 libstdc ++。a
,或沿着这些行。
注意:实际提高异常的工作由 _Unwind_RaiseException
在 libgcc_s.so.1
,所以即使两个应用程序使用相同的 libstdc ++。 c>,他们可能仍然使用不同的
libgcc
。
更新: >
将libstdc ++和libgcc静态链接到我的.so库中会受益吗?
也许。
-
将
libstdc ++,a
静态链接到zzz.so $ c $
-
即使有
从zzz.so
导出的code> _Unwind_RaiseException ,通常已经有_Unwind_RaiseException
在(载入早期)libgcc_s.so
中定义,并且早期实例是将被调用的实例,使您的解决方法无效。要确保_Unwind_RaiseException
的副本被调用,您需要链接zzz.so
与-Bsymbolic
,或使用一个特殊的链接器脚本,使所有调用_Unwind_RaiseException
code> libgcc.a -
您的解决方法可能会解决
zzz .so
,但可能会导致一个问题,无关的yyy.so
即使以后加载,并且希望系统提供_Unwind_RaiseException
,而不是zzz.so
中的一个。这是隐藏所有libgcc.a
符号并使它们在zzz.so
内部的另一个参数。
$ b li>
在任何i386平台之外的平台上,您必须自己创建 libstdc ++的副本。
和 libgcc.a
与 -fPIC
,然后才能将它们链接到 zzz.so
。通常,这些库不包含 -fPIC
,并且不能静态链接到任何 .so
。
所以简单的答案是:这种解决方法有点可能会让你很痛苦。
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.
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.
这篇关于C ++异常和.eh_frame ELF部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!