2

OK, this question is a bit complicated, so please read to the end before giving a solution.

Basically, I want to override __cxa_throw (the C++ exception handler), but also allow users of my library to also override it if they need to. And to make things even more complicated, I want to be able to do it without them needing to recompile my library.

The normal way of overriding is to just define your own __cxa_throw function, and then the linker will simply use the static version (your version) instead of the one in the C++ runtime library. But what if users of your library ALSO need to hook into the exception handler for their own purposes? Now you have two statically linked __cxa_throw implementations, which of course fails to link.

My first thought is to use the dynamic linker functions, which I can use to load the C++ runtime library and fetch __cxa_throw, but how do I update the existing linkage in the already loaded program to call MY implementation before passing it on to whatever was there before?

So we have:

  • original __cxa_throw (dynamically linked)
  • my __cxa_throw (statically linked)
  • user __cxa_throw (statically linked)

I'd want it such that it does this:

  • call my __cxa_throw (not actually called "__cxa_throw" since that would cause a collision)
  • My handler calls user __cxa_throw (if present)
  • if the user is passing through, he calls the original __cxa_throw the same same way one normally does it.

Of course, if I did manage to relink __cxa_throw to point to my implementation, the user grabbing a pointer to the "original" __cxa_throw may in fact be getting mine (not totally sure about this - I'd need to run some tests). To handle that, I can just check for re-entry and pass through to the "real" original function. The only thing I haven't been able to figure out is how to do the relinking to begin with.

I should also mention that I need this to work on Apple platforms as well, so LD_PRELOAD and --wrap are out.

Karl
  • 14,434
  • 9
  • 44
  • 61
  • You cannot just assume your code will be statically linked. Even if you don't provide a dynamically-linked version, users are free to take your static library and link their own dynamic libraries with it. Now why would you want to replace __cxa_throw? – n. m. could be an AI Apr 25 '16 at 17:15
  • 1
    My code will be statically linked because it's a static library. If someone goes and turns it into a dynamic library after the fact, it's their problem to deal with. And I need to replace __cxa_throw because I need to do a few things before the rest of the exception processing happens. – Karl Apr 25 '16 at 17:20
  • You would have to warn your users very clearly that they cannot build loadable plug-ins with your code. Loadable plug-is is the main way certain application frameworks are working, so your code would not be usable in such frameworks. – n. m. could be an AI Apr 25 '16 at 17:39
  • This question is not about what I should tell users about using my library. It's about how to allow multiple hooks of a C function. – Karl Apr 25 '16 at 17:42
  • Anyway you may want to look at [this](http://stackoverflow.com/questions/3662856/how-to-reimplement-or-wrap-a-syscall-function-in-linux). – n. m. could be an AI Apr 25 '16 at 17:42
  • As I stated in my question, I need this to work on Apple platforms, so --wrap and LD_PRELOAD are out. – Karl Apr 25 '16 at 17:44
  • As a matter of terminology, this question is **not** about overriding. Derived classes can override virtual functions in base classes. This is about **replacing** an implementation-specific function. – Pete Becker Apr 25 '16 at 17:56
  • It would seem you just want to allow your users to libRegisterCxaThrow(void (*throwCb) (void* thrown_exception, struct type_info *tinfo, void (*dest)(void*)); and in your libCxaThrow implementation checking if the Cb is registered and optionally calling it? – cleblanc Apr 25 '16 at 17:56
  • Mac OS X has DYLD_INSERT_LIBRARIES which seems to be a counterpart of LD_PRELOAD. – n. m. could be an AI Apr 25 '16 at 18:05
  • I want users to be able to use the same __cxa_throw override that they've always used, and expect it to just work. I don't want them to jump through extra hoops to get it because this is to handle the case where users are linking another library that ALSO has __cxa_throw. It's a shame that the C++ ABI uses this unwieldly procedure for overriding behavior, but it's here now and I have to make the best of it. And DYLD_INSERT_LIBRARIES is out because it won't work in iPhone, Apple TV, etc. At this point, I'm even looking into weak functions. Not ideal, but better than failed linkage. – Karl Apr 25 '16 at 18:14

0 Answers0