Added zombie tracking (user controllable).
Added notable address section to the standard report.
Added stack dump to the standard report.
Minor code cleanup.


Zombie Tracking:

KSCrash can now track zombies in the wild, in a limited way. When zombies are enabled, it swizzles -[NSObject dealloc], adding two function calls, a few minor instructions, and an Objective-C call to the real dealloc. The additional overhead is quite minor.
The accuracy of the zombie tracker is user-controllable. The more memory you give it, the more accurate it becomes. It won't, however, track anything that does not ultimately call -[NSObject dealloc]. A potential zombie will be mentioned in the "notable_addresses" section of the report as "last_deallocated_obj".


Notable Addresses:

KSCrash will now examine registers and the stack for anything interesting. Currently, it will record any address that is:

* An Objective-C object or class
* A C-style null-terminated string (UTF-8) (selectors are basically C-strings, which is handy)
* A potential zombie (an object once lived there)
* The beginning of an allocation block according to malloc_size()

Here's some example crash report data from a crash in CrashTester:

    "backtrace": [
        {
            "instruction_addr": 922865528,
            "object_addr": 922849280,
            "object_name": "libobjc.A.dylib",
            "symbol_addr": 922865512,
            "symbol_name": "objc_msgSend"
        },
    ...

    "notable_addresses": {
        "r0": {
            "address": 1947488,
            "contents": "unknown",
            "last_deallocated_obj": "MyClass",
            "malloc_size": 0
        },
        "r1": {
            "address": 885003510,
            "contents": "string",
            "malloc_size": 0,
            "value": "respondsToSelector:"
        },
        "r2": {
            "address": 889900245,
            "contents": "string",
            "malloc_size": 0,
            "value": "descriptionWithLocale:"
        },
    ...

r0-r3 in the ARM ABI are used for passing parameters to subroutines. In this case, it passed 1947488 (0x001db760) in r0 as the first param to objc_msgSend(), which didn't modify the value prior to crashing. The second param ("respondsToSelector:", in r1) is the selector being called, and the third param ("descriptionWithLocale:", in r2) is the first param that objc_msgSend() must pass in when invoking the method on the specified object. Invoking "descriptionWithLocale:" is consistent with the behavior of NSLog(), and the full backtrace (not shown) bears this out.

The first param (in r0) is not a valid object. However, that address did once contain an instance of MyClass, which was deallocated prior to the crash.

From this information, we can infer that +[Crasher accessDeallocatedPtr] tried to print a deallocated object (zombie) of type "MyClass" using NSLog(), which is indeed the case in Crasher.m, line 120.



Stack Dump:

The crash report will now include a small stack dump like the following:

    "stack": {
        "contents": "0000000002000000F4DEDF2FC9ED013700DFDF2FFF4CFA34FFFFFFFF0000000000000000C3DFDF2FFFFFFFFF60B71D00000000000000000028DFDF2F14EEDF2F7549033501000000000000000CDFDF2F00000000000000000000000028E4DF2FF094203F0400000004000000010000007BE4DF2F10000000",
        "dump_end": 803200860,
        "dump_start": 803200740,
        "grow_direction": "-",
        "stack_pointer": 803200780
    }

dump_start is the start address of the memory dump, and dump_end is the end. grow_direction specifies in which direction the stack grows (+ or -).