So you want to know how the runtime handles exceptions?
Get ready for disappointment.
Because it is not. ObjC does not have an ABI exception handler, only the SPI you already found. Undoubtedly, you also found that the ABF Objective-C exception is actually the same as the C ++ handling of ABI exceptions . To this end, let's start with the code.
#include <Foundation/Foundation.h> int main(int argc, char **argv) { @try { @throw [NSException exceptionWithName:@"ExceptionalCircumstances" reason:@"Drunk on power" userInfo:nil]; } @catch(...) { NSLog(@"Catch"); } @finally { NSLog(@"Finally"); } }
Run clang with -ObjC -O3 (and lose the disgusting amount of debugging information), we get the following:
_main:
If you compile it with ObjC ++, nothing will change. (Well, thatβs not entirely true. The last _objc_terminate turns into a clang personal ___clang_call_terminate ). In any case, this code can be divided into 3 important sections. The first is from _main to the start of LBB0_2 or where our try block occurs. As we scream and throw an exception and catch it in our try block, the compiler went ahead and removed the branch around LBB0_2 and went straight to catch handlers. At the moment, Objective-C, or rather, CoreFoundation, set up an exception object for us, and lib ++ began to search for an exception handler during the necessary unwinding phase.
The second important block of code is from LBB0_2 to the end of LBB0_11 , where our catch and finally blocks live. Because everything is in order, all the code below this is dead (and, I hope, he is being deprived of his freedom), but imagine that this is not so.
The third part is from LBB0_8 until the compiler LBB0_2 transition from NSLog to LBB0_2 , if we did something stupid, for example, try not to catch our exception. This handler instead flips a bit after a call to objc_begin_catch , which forces us to turn around ret and go to objc_exception_rethrow() , which tells the turn handler that we dropped the ball and continue to search for handlers elsewhere.Of course, we are the main ones, therefore there are no other handlers, and std::terminate is called upon exit.
All this to say that you will have a bad time if you want to try to write this material manually. All __cxa_* and ObjC SPI functions throw exception objects in ways you cannot rely on, and (quite pessimistic many) handlers are thrown in very tight order to make sure that the C ++ ABI contract is executed, because if it's not mandates std::terminate specifications are invoked. If you want to take an active listening role, you can override the exception handling material with your own functions and Objective-C has objc_setUncaughtExceptionHandler , objc_setExceptionMatcher objc_setExceptionPreprocessor .