首页
社区
课程
招聘
[原创]gdb 调试 objc
发表于: 2012-12-6 10:20 18671

[原创]gdb 调试 objc

2012-12-6 10:20
18671

1. 在有symbols 的情况下,断点 objc method , 这个比较方便

b [UIView init];

然后敲 c 运行到 断点处:

objc 的 method 方法的原型,大概是这样:

id __UIView_init(id self, SEL sel, args ...)

所以 $r2  才是第一个参数。。而这里的init 不带参数的

2. 由于 ios的 程序 是arm架构,参数 传递 先按 r0 - r4 传递, 之后的参数 压栈处理, 返回值也在 r0 里面, 所以 在没有 symbols的是有, 想要 查看具体参数的信息, 可以试试:

po $r0
po $r1

po 会发一个objc消息, 然后打印出 objc 对象的 实际内容, 类似 NSLog

3. 在没有 symbols的情况下,想要下断 objc method 或者 private framework 里面的 method 就比较麻烦点:

一种可以通过 class-dump 加参数 -A 导出没有 impl 的 相对地址, 然后用gdb info shared
获取 每个模块的 加载基址, 来算出实际 地址, 下断 , 不过这种方法 我算到现在 还没精确断成功过, = =

还有一种 比较简单有效, 可以通过 objc_getClass 和 class_getInstanceMethod获取 私有类的 实例, 然后通过 method_getImplementation, 获取指定 impl 的 地址, 然后下断:

b *((long)method_getImplementation((long)class_getInstanceMethod((long)objc_getClass((char*)"UIApplication"), @selector(deactivate))))

为了方便使用, 可以定义成命令, 放到 .gdbinit 中, 例如:

define bo
b *((long)method_getImplementation((long)class_getInstanceMethod((long)objc_getClass((char*)"$arg0"), @selector($arg1))))
end

之后只需要:

bo UIApplication deactivate
bo SBIconView  touchesBegan:withEvent:

就行了。。

4. trace objc 的 调用过程

由于ios的大部分调用,都在objc_msgSend上, 所以先下断 objc_msgSend, 然后c 到断点处

此时 r0 指向 object , r1 为 selector 名, 可以同通过 object_getClassName 来获取类名

printf "[%s %s]\n", (char*)object_getClassName($r0), (char*)$r1

打印如下:

[__NSCFTimer retain]

然后把这些过程 封成命令就行了:

define to
b objc_msgSend
c
set $__i = 0
while ($__i < $arg0)
printf "%d: [%s %s]\n", $__i, (char*)object_getClassName($r0), (char*)$r1
set $__i++
c
end
end

之后 跑到 你想要看流程的时候, 断下来直接敲:

to 100

就可以 trace 100 条调用过程:

0x3165f004 in mach_msg_trap ()
Breakpoint 1 at 0x351b7f72

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
0: [__NSCFTimer retain]

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
1: [HomeViewController retain]

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
2: [HomeViewController timerHandler:]

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
3: [__NSArrayM count]

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
4: [__NSArrayM count]

Breakpoint 1, 0x351b7f72 in objc_msgSend ()
5: [HomeViewController changePage:]
d

不过这个方法试下来, ui基本就卡住了, 没法继续响应操作,而且有时候时不时 中间会中断, 所以可用性 还不是很好

大家如果觉得可以有改进和完善的地方,可以互相交流下。。

附件附上, ios 专用 gdb 以及 我自己配的 gdbinit 扩展了那几个命令, 大家有需要的 可以下下来用用。。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 6
支持
分享
最新回复 (8)
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
2
站位,顶一个。是不是今天在群上讨论的东西啊?
2012-12-6 13:12
0
雪    币: 183
活跃值: (563)
能力值: ( LV9,RANK:150 )
在线值:
发帖
回帖
粉丝
3
是的 呵呵。。
2012-12-6 13:25
0
雪    币: 2559
活跃值: (176)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
谢谢楼主分享。
2012-12-10 13:35
0
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
不多,感谢分享,有时间测试一下。
2012-12-17 10:57
0
雪    币: 234
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
什么群,求加.
2014-5-15 09:19
0
雪    币: 14
活跃值: (46)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
7
我记得crypt还是哪个工具也可以直接打印出所有调用过的类名来着 ,以前打印过,忘了什么工具了
2014-5-15 19:59
0
雪    币: 220
活跃值: (33)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
gdb
-sh: /usr/bin/gdb: Bad CPU type in executable   这是不支持么?
2020-7-22 10:39
0
雪    币: 183
活跃值: (563)
能力值: ( LV9,RANK:150 )
在线值:
发帖
回帖
粉丝
9
biock gdb -sh: /usr/bin/gdb: Bad CPU type in executable 这是不支持么?
都是多少年前的了 能支持就怪了 自己对下arch
2020-7-24 09:08
0
游客
登录 | 注册 方可回帖
返回
//