On Thu, Apr 30, 2009 at 5:04 PM, Thomas McHale
<email@hidden> wrote:
On Apr 29, 2009, at 11:18 PM, John Engelhart wrote:
On Wed, Apr 29, 2009 at 8:01 PM, Thomas McHale
<email@hidden> wrote:
When the crash happens the app just goes poof and in gdb I don't get any helpful info at all.
Are there more extensive ways to configure gdb to catch stack problems?
Sorry, I should have included this in my first message.... My first post gave a dtrace script that traced everything, the output of which can be huge. If you just want to catch the tail end of something, you can use a ring buffer:
---
#!/usr/bin/dtrace -s
#pragma D option bufpolicy=ring
#pragma D option bufsize=4k
#pragma D option quiet
#pragma D option flowindent
#pragma D option zdefs
pid$target:a.out::entry { printf("\n"); }
pid$target:a.out::return { printf("\n"); }
objc$target:::entry { printf("// %s\n", probemod); }
objc$target:::return { printf("// %s\n", probemod); }
---
You can adjust the bufsize to taste, but 4k should be enough for you to catch the last gasp. Since this script uses a ring buffer, removing the 'a.out' in the pid... line becomes a possibility. This can really slow down execution time, though, since this logs every function call in every library. If you do decide to trace everything this way, you'll probably want to bump the bufsize up to something like 64k.
Thanks for that John. I see that gets entry/return at the app level. Any idea of how to extend it to the frameworks and so on.
You can replace the pid... lines with
pid$target:::entry { printf("// %s\n", probemod); }
pid$target:::return { printf("// %s\n", probemod); }
This will print the entry/return for every function call, with a // comment of the executable/library where that function is located. I would /strongly/ recommend you use this only with the ring buffer style as you can easily bring your system to its knees if you try to capture everything. Gigabytes worth of data can be generated it just a few seconds of execution time. Here's a snippet from a run I just did:
CPU FUNCTION
0 <- tiny_free_list_add_ptr // libSystem.B.dylib
0 <- szone_free // libSystem.B.dylib
0 <- free // libSystem.B.dylib
0 -> umtx_atomic_dec // libicucore.A.dylib
0 -> OSAtomicAdd32 // libSystem.B.dylib
0 <- OSAtomicAdd32 // libSystem.B.dylib
0 <- umtx_atomic_dec // libicucore.A.dylib
0 -> icu::RegexPattern::zap() // libicucore.A.dylib
The library is where that function is located. When the function is in your executable, the library name will be replaced with your executables name.
The objc... provider lines capture all objc message sends, and provides no 'simple' way to determine 'who' made the call. You can probably hack something together to extract this information so it can be pretty printed for you, but you can usually mentally reconstruct the information from the preceding/surrounding lines without much effort.
Using a ring buffer, this will give you a snapshot of the last several hundred/thousand function calls and message sends that took place just before your program crashed.