Hi
A few days ago I sent out an email talking about redoing our exception handling. The gist of this change is that when we handle Mach exceptions, we call into an exc_server method provided by LibSystem, which then upcalls into an exception-handling method we provide(catch_exception_raise(), catch_exception_raise_state(), or catch_exception_raise_state_identity() - the exact one depends on what options we've called task_set_exception_port() with). This upwards dependency by libSystem on the main excecutable works fine but, according to Apple, some changes to crt1.o in Leopard regarding the visibility of these methods can cause breakage if the catch* methods are located inside a dylib loaded by the main process rather than the main process executable itself.
You might have noticed this if, when processing an exception, you see another crash in the exception handler with a stack trace like the following:
Thread 1 Crashed:
0 ??? 0x00005000 catch_exception_raise + 0
1 libSystem.B_debug.dylib 0x0040f618 _Xexception_raise + 150
2 libSystem.B_debug.dylib 0x0040ee28 exc_server + 200
3 com.Google.BreakpadFramework 0x0008d15d google_breakpad::ExceptionHandler::WaitForMessage(void*) + 1051 (exception_handler.cc:447)
4 libSystem.B_debug.dylib 0x0036bf83 _pthread_start + 427
5 libSystem.B_debug.dylib 0x0036bdd6 thread_start + 34 (thread_start.s:41)
Although it's easy to miss because the crash handling code might have written the dump already and you'd only notice the crash in the exception handling from the Apple Crash Reporter log.
Anyways, the recommended solution is to generate a MIG implementation from exc.defs and compile it into our framework, and that's what this change does. The exact steps I did were:
- Run "mig exc.defs" on the exc.defs that comes with the xnu source(this hardly changes from kernel to kernel, but I used 10.5.2's version). By default the prefix for the exception handling methods is "catch_"'; I set it to "breakpad"
- Added the two new server/client files to Breakpad
- Implemented the breakpad_exception_raise() method which does the same thing as our old catch_exception_raise() method, and provided dummy implementations of breakpad_exception_raise_state & breakpad_exception_Raise_state_identity(), which should never get called because of how we call task_set_exception_ports().
All in all it's not a huge change but I am checking in a lot of auto-generated code from MIG so it looks larger than it is :-)
Thanks, and please let me know if you have any questions.
Neal