首页 > 代码库 > ios下gdb调试初探
ios下gdb调试初探
一、调试平台搭建
1、GNU Debugger。首先安装ios下的gdb调试器,添加源:cydia.radare.org 。搜索 GNU Debugger,安装之。(有些源的GDB好像不能用,这个测试没问题)
2、openSSH。这个应该都会装,没装过的参考,http://www.cnblogs.com/jailbreaker/p/4142609.html
3、adv-cmds。添加源:apt.saurik.com(这个应该是默认源里的一个)。
二、附加步骤
1、首先在ios中打开你要调试的app。
2、远程ssh登陆到ios。
login as: rootroot@192.168.0.2‘s password:iPhone:~ root#
3、使用adv-cmds的工具,便利下系统中的所有进程号。
iPhone:~ root# ps -ax 366 ?? 1:50.90 /var/mobile/Containers/Bundle/Application/653EB29F-15A7-48BA-9226-69C4CF690771/sb.app/sb
前面366就是进程号。(随便找了个进程,只是举个列子而已)
4、使用gdb 附加366号进程
iPhone:~ root# gdb -p 366/usr/bin/gdb: line 55: awk: command not foundwarning: unrecognized host cpusubtype , defaulting to host==armv7.GNU gdb 6.3.50-20050815 (Apple version gdb-1708 + reverse.put.as patches v0.4) (Mon Apr 16 00:53:47 UTC 2012)Copyright 2004 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was configured as "arm-apple-darwin".
.....省略若干代码
0x38e0e4f0 in mach_msg_trap ()(gdb)
好了,附加成功。下面可以开始输入命令进行调试。
三、常用调试命令详解
首先讲一点,gdb中的命令是可以缩写的,只要包含首字母,并不引起歧义就可以使用,比如 break,可以输入b,字母必须是连续的(br可以,ba就不行)。
一些指令都是配套使用的,所以为了讲解用法,有些指令会提前简单说一下用法。
我将调试命令分为三种:
1、控制命令,包括下断、单步等命令,顾名思义就是控制代码流程的命令。
1.1 break,下断命令。
1.1.1 函数下断:已知函数名,对代码进行下断。
(gdb) b CFRunLoopRunInModeBreakpoint 3 at 0x2aef7176(gdb) i bNum Type Disp Enb Address What3 breakpoint keep y 0x2aef7176 <CFRunLoopRunInMode+14>
i b 是 info break的缩写,功能为列出当前断点列表。
1.1.2 不知道函数名,只知道在ida等反汇编引擎中的地址。
我们知道目标函数在ida中的文件偏移。
1 (gdb) info sh2 The DYLD shared library state has not yet been initialized.3 Requested State Current State4 Num Basename Type Address Reason | | Source5 | | | | | | | |6 1 sb - 0x4000 exec C C /private/var/mobile/Containers/Bundle/Application/...(太长省略)
我们得到了加载基址是0x4000,那么 将文件偏移0x190EC + 0x4000 得到的地址是当前app 我们要下断的地址0x1D0EC。
(gdb) b * 0x1d0ecBreakpoint 4 at 0x1d0ec
1.2 disable 取消断点。参数为在info b中的断点号,
(gdb) b *81080Breakpoint 1 at 0x13cb8(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00013cb8(gdb) d 1(gdb)
1.3 nexti 单步补过。当执行函数调用指令时,跳过该指令。相当于 od F8
(gdb) ni0x38e0e4f4 in mach_msg_trap ()
1.4 stepi 单步步入。当执行函数调用指令时,进入函数。相当于od F7
(gdb) si0x38e0e2e8 in mach_msg ()
1.5 Continue 继续运行,相当于OD F9
1.6 run 运行一个app,没用过,现在都是附加,以后再追加这段内容。
2、查询命令
2.1 info break 查询断点
(gdb) info bNum Type Disp Enb Address What1 breakpoint keep y 0x00013cb8
2.2 查询dylib
(gdb) info shThe DYLD shared library state has not yet been initialized.
2.3 查询当前寄存器信息
(gdb) (gdb) info regUndefined command: "". Try "help".(gdb) r0 0x10004005 268451845Undefined command: "r0". Try "help".(gdb) r1 0x7000806 117442566Undefined command: "r1". Try "help".(gdb) r2 0x0 0Undefined command: "r2". Try "help".(gdb) r3 0xc00 3072Undefined command: "r3". Try "help".(gdb) r4 0x0 0Undefined command: "r4". Try "help".(gdb) r5 0x1c03 7171Undefined command: "r5". Try "help".(gdb) r6 0x0 0Undefined command: "r6". Try "help".(gdb) r7 0x1c8df0 1871344Undefined command: "r7". Try "help".(gdb) r8 0xc00 3072Undefined command: "r8". Try "help".(gdb) r9 0x549ff237 1419768375Undefined command: "r9". Try "help".(gdb) r10 0x7000806 117442566Undefined command: "r10". Try "help".(gdb) r11 0x7000806 117442566Undefined command: "r11". Try "help".(gdb) r12 0xffffffe1 -31Undefined command: "r12". Try "help".(gdb) sp 0x1c8dc4 1871300Undefined command: "sp". Try "help".(gdb) lr 0x38e0e2e9 954262249Undefined command: "lr". Try "help".(gdb) pc 0x38e0e2e8 954262248Undefined command: "pc". Try "help".cpsr { 0x60000030, n = 0x0, z = 0x1, c = 0x1, v = 0x0, q = 0x0, j = 0x0, ge = 0x0, e = 0x0, a = 0x0, i = 0x0, f = 0x0,(gdb) cpsr {Undefined command: "cpsr". Try "help".(gdb) 0x60000030,Undefined command: "0x60000030". Try "help".(gdb) n = 0x0,A syntax error in expression, near `= 0x0,‘.(gdb) z = 0x1,Undefined command: "z". Try "help".(gdb) c = 0x1,Not stopped at any breakpoint; argument ignored.Continuing. v = 0x0, q = 0x0, j = 0x0, ge = 0x0, e = 0x0, a = 0x0, i = 0x0, f = 0x0, t = 0x1, mode = 0x10} { 0x60000030, n = 0, z = 1, c = 1, v = 0, q = 0, j = 0, ge = 0, e = 0, a = 0, i = 0, f = 0, t = 1, mode = usr}(gdb)
2.4 Backtrace 查询当前调用堆栈
(gdb) bt#0 0x38e0e4f0 in mach_msg_trap ()#1 0x38e0e2e8 in mach_msg ()#2 0x2afab31a in <redacted> ()#3 0x2afa98c0 in <redacted> ()#4 0x2aef73c0 in CFRunLoopRunSpecific ()#5 0x2aef71d2 in CFRunLoopRunInMode ()#6 0x2bc30bfc in <redacted> ()#7 0x2bc7f0bc in <redacted> ()#8 0x0007fd3e in _mh_execute_header ()#9 0x0007fb40 in _mh_execute_header ()(gdb)
2.5 disassemble 反汇编 可以dump内存,没用过
(gdb) help disassembleDisassemble a specified section of memory.Default is the function surrounding the pc of the selected frame.With a single argument, the function surrounding that address is dumped.Two arguments are taken as a range of memory to dump.
2.6 print 打印命令
可以打印变量,寄存器。
(gdb) p $r0$3 = 383366272(gdb) p/x $r1$4 = 0xb2acbc12
//打印指针,一级,二级
(gdb) info fStack level 0, frame at 0x1afaf0: pc = 0x690ec in _mh_execute_header; saved pc 0x690ec called by frame at 0x1afaf0 Arglist at 0x1afaf0, args: Locals at 0x1afaf0,
(gdb) p/x *0x1afaf0$7 = 0x387e7f41
(gdb) p/x **0x1afaf0$8 = 0xf8d0b1
2.7 info frame打印当前栈帧信息,同上 info f
2.8 x 命令,没找到全称是啥,查看内存地址中的值
(gdb) help xExamine memory: x/FMT ADDRESS.ADDRESS is an expression for the memory address to examine.FMT is a repeat count followed by a format letter and a size letter.Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char) and s(string), T(OSType), A(floating point values in hex).Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).The specified number of objects of the specified size are printedaccording to the format.Defaults for format and size letters are those previously used.Default count is 1. Default address is following last thing printedwith this command or "print".
x /nfu 0x<addr>:查看内存地址中的值。
n表示要显示的内存单元的个数
f表示显示方式, 可取如下值
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。
u表示一个地址单元的长度
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节
可以用来查看当前汇编代码:
(gdb) x/5i $pc0x690ec: 9a 90 9e 98 ldmls lr, {r1, r3, r4, r7, r12, pc}0x690f0: 03 28 26 d1 teqle r6, r3, lsl #160x690f4: 4b f2 a4 20 adccs pc, r4, r11, asr #40x690f8: c0 f2 03 00 andeq pc, r3, r0, asr #50x690fc: 78 44 00 68 stmdavs r0, {r3, r4, r5, r6, r10, lr}
错误
(gdb) x/5ih $pc0x690ec: 9a 90 str r0, [sp, #616]0x690ee: 9e 98 ldr r0, [sp, #632]0x690f0: 03 28 cmp r0, #30x690f2: 26 d1 bne.n 0x691420x690f4: 4b f2 a4 20 movw r0, #45732 ; 0xb2a4
正确。需要指定指令最小长度?
2.7 print-object (po) 打印object对象。非常有用。
(gdb) po $r0/private/var..
r0 是一个NSString
还有那些比较常用的指令还望指出。
ios下gdb调试初探