1、指令格式

image.png
:命令
:子命令
:命令操作
:命令选项
:命令参数
例如给test函数设置断点:
(lldb) breakpoint set -n test

  1. void test()
  2. {
  3. int a = 10;
  4. int b = 20;
  5. NSLog(@"a + b = %d", a + b);
  6. }

其中breakpoint是,set是,-n是,test是

2、help

查看指令的用法。例如查看breakpoint指令用法:
(lldb) help breakpoint

  1. clear -- Delete or disable breakpoints matching the specified source
  2. file and line.
  3. command -- Commands for adding, removing and listing LLDB commands
  4. executed when a breakpoint is hit.
  5. delete -- Delete the specified breakpoint(s). If no breakpoints are
  6. specified, delete them all.
  7. disable -- Disable the specified breakpoint(s) without deleting them. If
  8. none are specified, disable all breakpoints.
  9. enable -- Enable the specified disabled breakpoint(s). If no breakpoints
  10. are specified, enable all of them.

3、expression

3.1、执行一个表达式

:命令选项
:命令选项结束符,表示所有的命令选项已经设置完毕,如果没有命令选项,—可以省略
:需要执行的表达式
例如设置view的边框宽度:
(lldb) expression self.view.layer.borderWidth = 30

3.2、打印对象信息

expression、expression —、print、p、call的效果一样,例如打印array的信息:
(lldb) p array

  1. (NSConstantArray *) $0 = 0x000000010c21f538 @"3 elements"

3.3、打印对象描述

expression-O 和指令 po 的效果一样,例如打印array的描述:
(lldb) po array

  1. <NSConstantArray 0x10c21f538>(
  2. 1,
  3. 2,
  4. 3
  5. )

4、thread

4.1、thread backtrace

打印线程的堆栈信息。和指令 bt 效果一样,比如在touchesBegan:withEvent:添加断点,执行:
(lldb) bt

  1. ...
  2. frame #0: 0x000000010c217ed6 LLDB指令`-[ViewController touchesBegan:withEvent:](self=0x00007fafb170b800, _cmd="touchesBegan:withEvent:", touches=1 element, event=0x0000600000f30300) at ViewController.m:32:5
  3. frame #1: 0x00007fff250d4f2e UIKitCore`forwardTouchMethod + 312
  4. frame #2: 0x00007fff250e5b33 UIKitCore`-[UIWindow _sendTouchesForEvent:] + 617
  5. frame #3: 0x00007fff250e7e3a UIKitCore`-[UIWindow sendEvent:] + 5312
  6. frame #4: 0x00007fff250bdeac UIKitCore`-[UIApplication sendEvent:] + 820
  7. frame #5: 0x00007fff25155f0a
  8. ...

frame:栈帧,每一帧代表一个函数调用

4.2、thread return []

让函数直接返回某个值,不会执行断点后面的代码。例如让test方法在断点处返回:

  1. void test()
  2. {
  3. int a = 10;
  4. int b = 20;
  5. NSLog(@"a + b = %d", a + b);
  6. }

(lldb) thread return
输入thread return指令后,就不会再执行NSLog打印。

4.3、frame variable []

打印当前栈帧的变量。例如打印test方法中的变量:

  1. void test()
  2. {
  3. int a = 10;
  4. int b = 20;
  5. NSLog(@"a + b = %d", a + b);
  6. }

(lldb) frame variable

  1. (int) a = 10
  2. (int) b = 20

5、流程控制

5.1、源码级别

thread continue、continue、c:程序继续运行
thread step-over、next、n:单步运行,把子函数当作一个整体一步执行
thread step-in、step、s:单步运行,遇到子函数会进入子函数
thread step-out、finish:直接执行完当前函数的所有代码,返回到上一个函数

5.2、汇编指令级别

thread step-inst-over、nexti、ni:单步运行,把子函数当作一个整体一步执行
thread step-inst、stepi、si:单步运行,遇到子函数会进入子函数
ni、si 类似于 n s ,例如在调试汇编代码时,通过si指令让汇编代码单步运行,遇到子函数会进入子函数:

  1. LLDB指令`test:
  2. 0x108a63e50 <+0>: pushq %rbp
  3. -> 0x108a63e51 <+1>: movq %rsp, %rbp
  4. 0x108a63e54 <+4>: subq $0x10, %rsp
  5. 0x108a63e58 <+8>: movl $0xa, -0x4(%rbp)
  6. ...

6、代码断点

6.1、breakpoint set

代码断点有以下设置方式:
breakpoint set -a 函数地址
breakpoint set -n 函数名
breakpoint set -r 正则表达式
breakpoint set -s 动态库 -n 函数名
例如给所有touchesBegan:withEvent:方法添加断点:
(lldb) breakpoint set -n touchesBegan:withEvent:
例如给ViewController的touchesBegan:withEvent:添加断点:
(lldb) breakpoint set -n “-[ViewController touchesBegan:withEvent:]”
例如给所有函数名包含Began的函数添加断点:
(lldb) breakpoint set -r Began

  1. // 共添加了239处断点
  2. Breakpoint 4: 239 locations.

6.2、breakpoint list

列出所有的断点(每个断点都有自己的编号)
(lldb) breakpoint list:

  1. Current breakpoints:
  2. 1: file = '/Users/mxl/Desktop/LLDB指令/LLDB指令/ViewController.m', line = 19, exact_match = 0, locations = 1, resolved = 1, hit count = 1
  3. 1.1: where = LLDB指令`-[ViewController viewDidLoad] + 16 at ViewController.m:19:5, address = 0x0000000101a8ae20, resolved, hit count = 1
  4. 2: file = '/Users/mxl/Desktop/LLDB指令/LLDB指令/ViewController.m', line = 33, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  5. 2.1: where = LLDB指令`-[ViewController touchesBegan:withEvent:] + 105 at ViewController.m:33:5, address = 0x0000000101a8aee9, resolved, hit count = 0
  6. 3: file = '/Users/mxl/Desktop/LLDB指令/LLDB指令/ViewController.m', line = 24, exact_match = 0, locations = 1, resolved = 1, hit count = 0
  7. 3.1: where = LLDB指令`test + 8 at ViewController.m:24:9, address = 0x0000000101a8ae58, resolved, hit count = 0

6.3、编辑断点

breakpoint disable 断点编号:禁用断点
breakpoint enable 断点编号:启用断点
breakpoint delete 断点编号:删除断点
例如删除3号断点:
(lldb) breakpoint delete 3

  1. 1 breakpoints deleted; 0 breakpoint locations disabled.

7、断点命令

breakpoint command add 断点编号:给断点预先设置需要执行的命令,到触发断点时,就会按顺序执行
breakpoint command list 断点编号:查看某个断点设置的命令
breakpoint command delegate 断点编号:删除某个断点设置的命令
例如给断点添加打印信息:
(lldb) breakpoint command add 1

  1. Enter your debugger command(s). Type 'DONE' to end.
  2. > p self
  3. > po self
  4. > DONE

当执行到断点时:

  1. p self
  2. (ViewController *) $0 = 0x00007fc302808460
  3. po self
  4. <ViewController: 0x7fc302808460>

8、内存断点

内存断点会在内存数据发生改变的时候触发,常见用法有:
watchpoint set variable 变量:给变量添加一个内存断点。例如给ViewController的age属性添加一个内存断点:
(lldb) watchpoint set variable self->_age
当age的内容更新时,会触发这个内存断点

  1. Watchpoint 1 hit:
  2. old value: 0
  3. new value: 20

watchpoint set expresion 地址,通过地址添加内存断点,例如给age属性添加一个内存断点:
(lldb) watchpoint set expression 0x00007fe7d34074b0
内存断点还有其它用法:
watchpoint list
watchpoint disable 断点编号
watchpoint enable 断点编号
watchpoint delete 断点编号
watchpoint command add 断点编号
watchpoint command list 断点编号
watchpoint command delete 断点编号

9、模块查找

9.1、image lookup

image lookup -t 类型:查找某个类型的信息
image loopup -a 地址:根据内存地址查找在模块中的位置
image loopup -n 符号或者函数名:查找某个符号或者函数的位置
例如查看NSArray的信息:
(lldb) image lookup -t NSArray

  1. Best match found in /Users/mengxianliang/Library/Developer/Xcode/DerivedData/LLDB指令-gmoomcnqyjazkcgbagyhcjflphbb/Build/Products/Debug-iphonesimulator/LLDB指令.app/LLDB指令:
  2. id = {0x000002a8}, name = "NSArray", byte-size = 8, decl = NSArray.h:17, compiler_type = "@interface NSArray : NSObject
  3. @property(readonly, getter = count, setter = <null selector>) NSUInteger count;
  4. @end"

再例如找出那一句代码出错,先创建一段报错的代码:

  1. - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  2. NSArray *array = @[@1, @2, @3];
  3. array[3];
  4. }

当代码触发后,控制台会报错,并打印错误信息和代码内存地址,但并不会显示哪一行代码出错:

  1. *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSConstantArray objectAtIndexedSubscript:]: index 3 beyond bounds [0 .. 2]'
  2. *** First throw call stack:
  3. (
  4. 0 CoreFoundation 0x00007fff20405604 __exceptionPreprocess + 242
  5. 1 libobjc.A.dylib 0x00007fff201a4a45 objc_exception_throw + 48
  6. 2 CoreFoundation 0x00007fff20486c63 _CFThrowFormattedException + 200
  7. 3 CoreFoundation 0x00007fff2033d8d7 +[NSConstantArray new] + 0
  8. 4 LLDB指令 0x0000000104d02eac -[ViewController touchesBegan:withEvent:] + 108
  9. ...

(lldb) image lookup -a 0x0000000104d02eac

  1. Address: LLDB指令[0x0000000100001eec] (LLDB指令.__TEXT.__text + 220)
  2. Summary: LLDB指令`-[ViewController touchesBegan:withEvent:] + 108 at ViewController.m:41:5

打印信息包含了出错代码所在的类和行号

9.1、image list

image list:列出加载的模块信息
(lldb) image list

  1. [ 0] B0C39DEA-9596-3495-A9CE-6FF30D2F6C78 0x000000010c4bb000 /Users/mengxianliang/Library/Developer/Xcode/DerivedData/LLDB指令-gmoomcnqyjazkcgbagyhcjflphbb/Build/Products/Debug-iphonesimulator/LLDB指令.app/LLDB指令
  2. [ 1] DD9E80DE-FB3B-349B-96A4-46874AD34D11 0x00000001158ff000 /usr/lib/dyld
  3. [ 2] 7276A69B-E3B9-3F23-957F-061350A501B4 0x000000010c6d7000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
  4. [ 3] 7C8E1422-6C6B-3EC0-8143-C71B8F4FE7B8 0x00007fff6fdd1000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/libBacktraceRecording.dylib

image list -o -f:打印出模块的编译地址、全路径

image代表模块

10、Tips

  • 敲Enter会自动执行上一次的命令
  • 绝大部份指令都可以使用缩写