什么是动态调试?
动态调试就是在我们的程序运行之时,通过下断点、打印等一系列方式查看参数、返回值、函数调用流程等等。不仅是在iOS开放中需要动态调试,在任何语言的开发过程中都需要用到动态调试
利用Xcode进行动态调试
- GCC和LLVM: Xcode最早使用的是GNU开发的GCC编译器,但是从xcode5之后开始使用自研的LLVM编译器,可以点击查看GCC和LLVM的介绍
- GDB和LLDB: Xcode调试器早期也是使用的GNU开发的GDB调试器,之后也替换成了自研的LLDB调试器,可以点击查看GDB和LLDB的介绍。
- 首先在Xcode中会自带一个叫做
debugserver的工具,存放在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/De viceSupport/xx.xx/DeveloperDiskImage.dmg/usr/bin/debugserver目录下,当我们使用Xcode在iPhone上运行我们的程序时,Xcode会将debugserver安装到我们的iPhone上,具体安装路径为/Developer/usr/bin/debugserver
- Xcode连接上手机后,通过自带的
LLDB编译器向iPhone上的debugserver传输指令,debugserver接收到指令之后将指令运行到App中,App执行指令之后将结果返回到debugserver,然后debugserver会将信息反馈给LLDB,最后LLDB会将信息打印到Xcode上。 - 但是Xcode这种调试方式有很大的局限性,因为只能调试通过Xcod安装的App
如何不通过Xcode动态调试任意App?
可以使用终端取代Xcode来对App进行动态调试
debugserver环境搭建
1. 通过ldid进行签名
- 获取到iPhone下/Developer/usr/bin/debugserver目录中的debugserver工具,复制到Mac上
- 由于通过Xcode安装的
debugserver权限不足,只能调试Xocde安装的App,所以我们要给debugserver增加更多的权限。 - 通过ldid -e指令导出
debugserver的权限信息
ldid -e debugserver > debugserver.entitlements
-
在debugserver.entitlements中增加以下两个权限
- get-task-allow
- task_for_pid-allow
-
通过ldid对
debugserver进行重新签名
ldid -Sdebugserver.entitlements debugserver
- 由于/Developer/usr/bin/目录是只读的,所以我们将重新签名过的
debugserver放在/usr/bin/下,然后对debugserver增加运行权限,就可以在终端使用debugserver了
chmod + /usr/bin/debugserver
方法二、通过codesign对debugserver进行签名
#查看权限基本信息
codesign -d --entitlements - debugserver
#签名权限
codesign -f -s - --entitlements debugserver.entitlements debugserver
#也可以简写为
codesign -fs - --entitlements debugserver.entitlements debugserver
让debugserver附加到某个进程
debugserver *:端口号 -a 进程
*:端口号:表示使用iPhone上的某个端口启动debugserver服务(注意:不能使用保留端口号) -a 进程:指定进程id或者进程名称
使用debugserver启动App
debugserver -x auto *:端口号 App可执行文件路径
在Mac上启动LLDB,远程连接iPhone上的debugserver
在之前的学习中,我们知道可以使用iPhone的ip地址来连接手机,但是这样需要保证手机和电脑在同一个wifi下,并且使用这种方式传输数据十分缓慢。所以,通常的做法是通过usb连接iPhone,将iPhone上的某个端口映射到Mac上的某个端口,然后然LLDB和Mac上的端口通信即可
debugserver attaching
- 通过以下指令对iPhone的10011进行映射
python ./usbmuxd/tcprelay.py -t 22:10010 10011:10011
此处的10011端口可以任意定义,只要不使用保留端口号即可。使用10010端口映射22端口,是为了和iPhone进行SSH通信
- 映射成功之后,使用10011端口启动
debugserver服务。让debugserver附加到App进程,如下:
debugserver *10011 -a wechat
- 如果出现以下效果,表明==debugserver==已经成功attach到了腾讯视频App上
5s:~ root# debugserver *:10011 -a wechat
debugserver-@(#)PROGRAM:debugserver PROJECT:debugserver-360.0.26.3 for arm64.
Attaching to process wechat...
Listening to port 10011 for a connection from *...
在Mac上启动LLDB,远程连接iPhone上的debugserver服务
- 首先在Mac上启动LLDB
➜ ~ lldb
(lldb)
- 通过Mac的10011端口连接
debugserve服务
(lldb) process connect connect://localhost:10011
Process 6911 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x0000000186c47224 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x186c47224 <+8>: ret
libsystem_kernel.dylib`mach_msg_overwrite_trap:
0x186c47228 <+0>: mov x16, #-0x20
0x186c4722c <+4>: svc #0x80
0x186c47230 <+8>: ret
- 由于连接上
debugserver服务之后,程序是默认在断点状态,使用LLDB的c命令让程序继续运行
(lldb) c
Process 6911 resuming