Debugging on iOS and Getting Crash Reports Over the Air

When debugging software on iOS, especially jailbreak tweaks, it it very useful to know how to debug them.
In this short article I am going to explain how I do it.

Getting a GDB which actually works

GDB in Cydia is broken since ~iOS4. Definitely don’t use it, you would be wasting your time. Instead, follow pod2g’s advice here. You can basically use gdb included in iOS SDK (it is a fat binary with armv7 architecture) and that one works perfectly! :)

Don’t forget that you can also attach gdb to a running process by executing “gdb /path/to/executable PID”. And you can get pid for example by “ps aux | grep SpringB”. It’s the second column.

Crash Reports Over the Air

Watching ReportCrash process writing a new crash report on disk (in better case) in syslog is helpful, but manually copying it to Mac and symbolificating it all the time is a nightmare. After ~100 crash reports processed this way I started thinking about how to speed this process up… and made a tweak for ReportCrash watching “release” method of crash instance, getting the crash report content and UDP-broadcasting it over the LAN (UPDATE: While it worked fine in the past, it doesn’t work on my new network environment – UDP packets comes out of order – which is definitely possible from how UDP works. I will soon rewrite it so that it uses UDP to find local crashd servers and then connect via TCP to it…)

On the Mac, I have a ruby script running all the time. Once a new crash happens, the ruby script receives it, processes it using the symbolificatecrash script (which you can get from iOS SDK), colorizing it, speaking the process name and creating a Mac notification.

This is much better isn’t it? You can install the tweak from my repo (it’s called RemoteCrash) and ruby script from the tweak source code here (called crashd). Make sure to install missing gems by “gem install name” (see the crashd source). It’s using “colorize” and “terminal-notifier” gems.

Disabling system watchdog

Another annoying fact when debugging iOS tweaks is, that if you freeze SpringBoard for some time (for example if you pause it in gdb), system WDT (watchdog) will force-reboot the system. It also creates a panic report saying “WDT Timeout”. But there is a solution! Just disable the dog!

For that purpose I have created a tool watchdogctl (on my repo) – inspired by a code I found online. By executing “watchdogctl 0” as root, it will be disabling the watchdog every second. When this tool is running, you can freely debug what you want. UserEventAgent process can get angry when SpringBoard is not responding for some time, aggressively trying to kill it.

I am not sure if “launchctl unload /System/Library/LaunchDaemons/com.apple.UserEventAgent-System.plist” helps here. Maybe UserEventAgent just prints that fact to syslog while some other service is trying to kill SpringBoard (let me know in comments if you know). But unloading that offending service will do the job…