动态调试
debugserver是Xcode自带的工具,默认放在/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/14.4/DeveloperDiskImage.dmg/usr/bin/debugserver
通过Xcode连接真机后,自动拷贝debugserver到越狱手机的/Developer/usr/bin/debugserver
(此处是只读权限),一般情况下只能调试通过Xcode安装的App
默认只能调试Xcode安装的应用,需要给debugserver附上权限重新签名后可调试手机上的任意App。
对debugserver赋予权限
- 由于手机里的Developer目录是只读的权限无法直接操作debugserver,需要把debugserver拷贝到电脑上操作。
- 通过ldid命令导出原有的权限
ldid -e debugserver > debugserver.entitlements
- 修改debugserver.entitlements文件新增
get-task-allow
和task_for_pid-allow
两个权限。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.springboard.debugapplications</key>
<true/>
<key>get-task-allow</key>
<true/>
<key>task_for_pid-allow</key>
<true/>
</dict>
</plist>
- 通过ldid命令进行重签名赋予权限
ldid -Sdebugserver.entitlements debugserver
或者通过codesign命令
//查看权限
$ codesign -d --entitlements - debugserver
//重签名
$ codesign -f -s - --entitlemetns debugserver.entitlements debugserver
//或者简写:
$ codesign -fs - --entitlemetns debugserver.entitlements debugserver
- 将处理过的debugserver放到手机
/usr/bin/
目录下
如果遇到 Permission denied
执行
chmod +x /usr/bin/debugserver
增加运行权限
使用debugserver
- 将debugserver附加到某App进程上
$ debugserver *:端口号 -a 进程
- 端口号:使用iPhone的某个端口启动debugserver服务
- 进程:App的进程信息(进程ID或进程名称)
- Mac上启动LLDB服务远程连接到iPhone上的debugserver
- 启动LLDB:lldb
- 连接debugserver服务:process connect connect://手机局域网IP:debugserver服务端口号
- 使用LLDB的c命令让程序继续运行
iPhone上
$ debugserver localhost:8888 -a HelloWorld
debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-900.3.106
for arm64.
Attaching to process HelloWorld...
Listening to port 8888 for a connection from localhost...
Waiting for debugger instructions for process 0.
Mac上
$ lldb
(lldb) process connect connect://localhost:10020
Process 2147 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
frame #0: 0x0000000198594198 libsystem_kernel.dylib`mach_msg_trap + 8
libsystem_kernel.dylib`mach_msg_trap:
-> 0x198594198 <+8>: ret
libsystem_kernel.dylib`mach_msg_overwrite_trap:
0x19859419c <+0>: mov x16, #-0x20
0x1985941a0 <+4>: svc #0x80
0x1985941a4 <+8>: ret
Target 0: (HelloWorld) stopped.
(lldb) c
Process 2147 resuming
也可以通过
debugserver -x auto *:端口号 App可执行文件路径
:通过debugserver启动App
$ debugserver -x auto localhost:8888 /var/containers/Bundle/Application/A8673B49-C454-42EA-8D9D-357AAB67B8E7/HelloWorld.app/HelloWorld
debugserver-@(#)PROGRAM:LLDB PROJECT:lldb-900.3.106
for arm64.
Listening to port 8888 for a connection from localhost...
如果遇到下面的错误:
failed to attach to process named: "" unable to start the exception thread
或
Failed to get connection from a remote gdb process.
解决方案:检查权限文件里包含的权限是否正确。
遇到报错:
error: rejecting incoming connection from ::ffff:127.0.0.1 (expecting ::1)
解决方案:debugserver *:端口号 -a 进程
改为debugserver localhost:端口号 -a 进程
LLDB
指令格式
<command> [<subcommand> [<subcommand>...]] <action> [-options [option-value]] [argument [argument...]]
- command:命令
- subcommand:子命令
- action:命令操作
- options:命令选项
- arguments:命令参数
例如:给test函数设置断点
breakpoint set -n test
breakpoint是command;set是action;-n是options;test是arguments。
help <command>
可查看命令帮助文档。
例如help breakpoint
help breakpoint
Commands for operating on breakpoints (see 'help b' for shorthand.)
Syntax: breakpoint <subcommand> [<command-options>]
The following subcommands are supported:
clear -- Delete or disable breakpoints matching the specified source
file and line.
command -- Commands for adding, removing and listing LLDB commands
executed when a breakpoint is hit.
delete -- Delete the specified breakpoint(s). If no breakpoints are
specified, delete them all.
disable -- Disable the specified breakpoint(s) without deleting them. If
none are specified, disable all breakpoints.
enable -- Enable the specified disabled breakpoint(s). If no breakpoints
are specified, enable all of them.
list -- List some or all breakpoints at configurable levels of detail.
modify -- Modify the options on a breakpoint or set of breakpoints in
the executable. If no breakpoint is specified, acts on the
last created breakpoint. With the exception of -e, -d and -i,
passing an empty argument clears the modification.
name -- Commands to manage name tags for breakpoints
read -- Read and set the breakpoints previously saved to a file with
"breakpoint write".
set -- Sets a breakpoint or set of breakpoints in the executable.
write -- Write the breakpoints listed to a file that can be read in
with "breakpoint read". If given no arguments, writes all
breakpoints.
For more help on any particular subcommand, type 'help <command> <subcommand>'.
expression <cmd-options> -- <expr>
执行表达式
:命令选项 - --:命令选项结束符,代表所有的命令选项都已设置完毕,如果没有命令选项可忽略。
:需要执行的表达式 expression self.view.backgroundColor = [UIColor redColor]
expression
和expression --
与指令print
、p
、call
效果一样
expression -O --
和po
效果一样
thread backtrace
打印堆栈信息,和bt
效果一样
thread return <expr>
让函数直接返回某个值,不会执行断点之后的代码
frame variable [<variable-name>]
打印当前栈帧的变量
thread continue
continue
c
让程序继续运行
thread step-over
next
n
单步运行,把子函数当做一步运行
thread step-in
step
s
单步运行,遇到子函数进入子函数内部
thread step-out
finish
直接执行完当前函数的代码,返回到上一个函数
thread step-inst-over
nexti
ni
thread step-inst
stepi
si
si ni
与s n
类似 si ni是汇编指令级别 s n是源码级别
breakpoint set -n 函数名
breakpoint set -a 函数地址
breakpoint set -n test
breakpoint set -n test:some
breakpoint set "[someClass test]"
breakpoint set -r 正则表达式
breakpoint set -r tes
假如有两个函数:test和testNext,由于函数名都包含tes,所以两个函数都被设置上断点
breakpoint set -s 动态库 -n 函数名
breakpoint list
:列出所有的断点,每个断点都有编号
breakpoint disable 断点编号
:禁用断点
breakpoint enable 断点编号
:启用断点
breakpoint delete 断点编号
:删除断点
breakpoint command add 断点编号
:给断点预先设置需要执行的命令,触发断点时就会按顺序执行。
$ breakpoint command add 2
Enter your debugger command(s). Type 'DONE' to end.
> po self
> p self.view.backgroundColor = [UIColor redColor]
> DONE
breakpoint command list 断点编号
:查看断点设置的命令
breakpoint command delect 断点编号
:删除断点下的命令
内存断点
watchpoint set variable 变量
watchpoint set expression 地址
:内存数据发生改变的时候触发
watchpoint set variable self->_age
watchpoint set expression &(self->_age)
watchpoint set variable self->_age
Watchpoint created: Watchpoint 1: addr = 0x7f8fff904c28 size = 8 state = enabled type = w
watchpoint spec = 'self->_age'
new value: 0
(lldb) c
Process 34409 resuming
2021-06-17 23:43:50.157314+0800 testlib[34409:7153831] screen parameters are unexpected: MGScreenClass1125x2436x3x495 SCREEN_TYPE(1125,2436,3,495)
Watchpoint 1 hit:
old value: 0
new value: 100
watchpoint list
watchpoint disable 断点编号
watchpoint enable 断点编号
watchpoint delect 断点编号
watchpoint command add 断点编号
watchpoint command list 断点编号
watchpoint command delect 断点编号
image lookup -t 类型
:查找某个类型的信息
(lldb) image lookup -t NSString
Best match found in /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib:
id = {0x7fffffff000005a3}, name = "NSString", byte-size = 8, decl = NSString.h:99, compiler_type = "@interface NSString : NSObject
@property(readonly, getter = length, setter = <null selector>) NSUInteger length;
@end"
image lookup -a 地址
:根据内存地址查找在模块里的信息
在viewController的touchesBegan:withEvent:
方法里写入数组越界崩溃代码
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
NSArray *someArray = @[];
someArray[1];
}
程序报错信息如下所示:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArray0 objectAtIndex:]: index 1 beyond bounds for empty NSArray'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff20421af6 __exceptionPreprocess + 242
1 libobjc.A.dylib 0x00007fff20177e78 objc_exception_throw + 48
2 CoreFoundation 0x00007fff20312243 -[__NSArray0 objectEnumerator] + 0
3 testlib 0x000000010fb507f5 -[ViewController touchesBegan:withEvent:] + 197
4 UIKitCore 0x00007fff246ca70f forwardTouchMethod + 321
5 UIKitCore 0x00007fff246ca5bd -[UIResponder touchesBegan:withEvent:] + 49
6 UIKitCore 0x00007fff246d95b5 -[UIWindow _sendTouchesForEvent:] + 622
7 UIKitCore 0x00007fff246db6c7 -[UIWindow sendEvent:] + 4774
8 UIKitCore 0x00007fff246b5466 -[UIApplication sendEvent:] + 633
9 UIKitCore 0x00007fff24745f04 __processEventQueue + 13895
10 UIKitCore 0x00007fff2473c877 __eventFetcherSourceCallback + 104
11 CoreFoundation 0x00007fff2039038a __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
12 CoreFoundation 0x00007fff20390282 __CFRunLoopDoSource0 + 180
13 CoreFoundation 0x00007fff2038f764 __CFRunLoopDoSources0 + 248
14 CoreFoundation 0x00007fff20389f2f __CFRunLoopRun + 878
15 CoreFoundation 0x00007fff203896d6 CFRunLoopRunSpecific + 567
16 GraphicsServices 0x00007fff2c257db3 GSEventRunModal + 139
17 UIKitCore 0x00007fff24696cf7 -[UIApplication _run] + 912
18 UIKitCore 0x00007fff2469bba8 UIApplicationMain + 101
19 testlib 0x000000010fb51002 main + 114
20 libdyld.dylib 0x00007fff2025a3e9 start + 1
)
利用LLDB查看具体报错代码在ViewController类中的详细信息
(lldb) image lookup -a 0x000000010fb507f5
Address: testlib[0x00000001000017f5] (testlib.__TEXT.__text + 261)
Summary: testlib`-[ViewController touchesBegan:withEvent:] + 197 at ViewController.m:14:5
可以看到ViewController.m中的第14行代码报错导致。
image lookup -n 符号或函数名
:查找某个符号或函数的位置
(lldb) image lookup -n touchesBegan:withEvent:
1 match found in /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib:
Address: testlib[0x0000000100001800] (testlib.__TEXT.__text + 64)
Summary: testlib`-[ViewController touchesBegan:withEvent:] at ViewController.m:12
86 matches found in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore:
Address: UIKitCore[0x000000000002bec2] (UIKitCore.__TEXT.__text + 168786)
Summary: UIKitCore`-[UIInterfaceActionGroupView touchesBegan:withEvent:] Address: UIKitCore[0x000000000003280e] (UIKitCore.__TEXT.__text + 195742)
image list
:列出所加载的模块信息
(lldb) image list
[ 0] B6671BA2-2011-342C-8DD0-B99756A4416F 0x000000010be28000 /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib
[ 1] DEA51514-B4E8-3368-979B-89D0F8397ABC 0x000000011162d000 /usr/lib/dyld
image list -o -f
:打印所加载模块的偏移地址、全路径
(lldb) image list -o -f
[ 0] 0x000000000be28000 /Users/CC/Library/Developer/Xcode/DerivedData/testlib-dxolpnclkjwmjrgulkxqzmskrnlm/Build/Products/Debug-iphonesimulator/testlib.app/testlib
[ 1] 0x000000011162d000 /usr/lib/dyld
tips
敲Enter键会自动执行上一条指令
文章评论