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.