Debugging gdb itself with gdb
To debug gdb, copy the current gdb to gdb2 first.
Load gdb2 within gdb, and attach gdb2 to Safari.
The result should be something like this.
Set a breakpoint at objc_msgSend() and class_getName() on gdb2.
Now move to gdb that is a parent of gdb2 by pressing “ctrl” + “c”, and confirm whether we are on gdb with “I b” or “bt”.
We found some symbols (proceed, resume, macosx_child_resume) in Part 1. Set breakpoints at those functions.
Move to gdb2 with the “c” command. You need two “c” commands to get to the previous position on gdb2.
call class_getName() on gdb2. You will see gdb2 stops at each breakpoint we have set.
The backtrace data shows the same code flow we found in Part 1. When you use “call” on gdb, call_command(), hand_function_call(), proceed(), resume(), and macosx_child_resume() are called in order. Let’s verify if this code flow reaches class_getName() with the command, “c”.
After doing more research on proceed(), resume() and macosx_child_resume(), I came to a conclusion that these functions are not connected to this crash. So hand_function_call() became my next target. Exit gdb and reload gdb2 and Safari, and set breakpoints as we did before.
Move to the parent gdb by pressing “ctrl” + “c”, and set a bp at hand_function_call(). Move to gdb2 with two “c” commands.
call class_getName() and check the backtrace data.
To check how many times the function “hand_function_call()” is called, run the command “c” until you arrive at class_getName().
We have only one call before we get to class_getName(). I traced this function and found a spot making lr 0. The related function is gdbarch_push_dummy_call(). Do the same work we did before and set a breakpoint at gdbarch_push_dummy_call() when gdb2 stops at hand_function_call(), and continue.
Check the parameter values of this function with the registers.
bp_addr is a return address so it must not be zero. To validate this, let’s change its value to 0x12121212 and see lr when class_getName() is called.
Now we need to find out the reason why bp_addr is 0. I analyzed more code in hand_function_call() and found the following.
dummy_addr becomes null after an entry_point_address() call. The function, entry_point_address() returns null as symfile_objfile is null. I also traced gdbarch_convert_from_func_ptr_addr(), but the function is not related to this issue. Take a look at the following code snippet. The code just returns addr in this case.
Although I had a look at code related to symfile_objfile, I stopped doing more analysis as I was not interested in gdb itself at this moment. To me, this is an enough evidence to show gdb has a bug and hopefully, somebody will fix it soon. However I have found some solutions to work around this.
Continued on Part 3
OS: iOS 6.01
Device: jailbroken iPod 4G