C++ exceptions and the .eh_frame ELF section

戏子无情 提交于 2019-12-02 22:27:51

问题


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:

  1. My zzz.so shared library has try-catch blocks:

    try {
        throw Exc();
    } catch (const Exc &e) {
        LOG("ok " << e.what());
    } catch (...) {
        LOG("all");
    }
    
  2. An executable which loads the zzz.so (using ldopen). It call a function in the zzz.so

  3. All the exceptions thrown in the zzz.so are successfully caught inside zzz.so and dumped into my log file
  4. There is another aaa.so that is loaded into another binary. That another aaa.so is loading my zzz.so.
  5. 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:

  1. On any platform other than i386, you would have to build your own copy of libstdc++.a and libgcc.a with -fPIC before you can link them into your zzz.so. Normally these libraries are built without -fPIC, and can't be statically linked into any .so.

  2. Static linking of libstdc++.a into your zzz.so may make it a derived work, and subject to GPL (consult your lawyer).

  3. Even when there is a _Unwind_RaiseException exported from zzz.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 link zzz.so with -Bsymbolic, or with a special linker script to make all calls to _Unwind_RaiseException (and everything else from libgcc.a) internal.

  4. Your workaround may fix the problem for zzz.so, but may cause a problem for unrelated yyy.so that is loaded even later, and that wants the system-provided _Unwind_RaiseException, not the one from zzz.so. This is another argument for hiding all libgcc.a symbols and making them internal to zzz.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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!