ios动态调试

575 阅读4分钟

什么是动态调试?

动态调试就是在我们的程序运行之时,通过下断点、打印等一系列方式查看参数、返回值、函数调用流程等等。不仅是在iOS开放中需要动态调试,在任何语言的开发过程中都需要用到动态调试

利用Xcode进行动态调试

  • GCC和LLVM: Xcode最早使用的是GNU开发的GCC编译器,但是从xcode5之后开始使用自研的LLVM编译器,可以点击查看GCCLLVM的介绍
  • GDB和LLDB: Xcode调试器早期也是使用的GNU开发的GDB调试器,之后也替换成了自研的LLDB调试器,可以点击查看GDBLLDB的介绍。
  1. 首先在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