添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

breakpoint set

使用 breakpoint 的子命令 set 设置断点

具体信息可以通过 help breakpoint set 查询所有可选的选项(options)以及参数(arguments).

下面使用之前的可执行文件 Greeter 介绍一些常用的方法:

  • 按方法名称设置--name(-n):
  • (lldb) breakpoint set -n greet
    Breakpoint 2: where = Greeter`Greeter.Greeter.greet(personNamed: Swift.String) -> () + 127 at Greeter.swift:9:12, address = 0x00000001000034cf
    
  • 按行数设置--line(-l):
  • (lldb) breakpoint set -l 18
    Breakpoint 3: where = Greeter`main + 14 at Greeter.swift:18:15, address = 0x000000010000315e
    
  • 按文件设置--file(-l):
  • (lldb) breakpoint set -f Greeter.swift -l 20
    Breakpoint 6: where = Greeter`main + 34 at Greeter.swift:20:1, address = 0x0000000100003172
    
  • 根据语言捕获异常--language-exception(-E):
  • (lldb) breakpoint set -E Objc
    Breakpoint 7: no locations (pending).
    

    可以通过--exception-typename(-O) 指定要捕获的异常类型:

    (lldb)  breakpoint set -E Swift -O EnumErrorType
    Breakpoint 8: no locations (pending).
    

    获取断点列表:

    breakpoint list

    (lldb) breakpoint list
    Current breakpoints:
    1: name = 'sayHello', locations = 0 (pending)
    2: name = 'greet', locations = 1
      2.1: where = Greeter`Greeter.Greeter.greet(personNamed: Swift.String) -> () + 127 at Greeter.swift:9:12, address = Greeter[0x00000001000034cf], unresolved, hit count = 0
    3: file = '/Users/jackli/Desktop/Roborock/Greeter.swift', line = 18, exact_match = 0, locations = 1
      3.1: where = Greeter`main + 14 at Greeter.swift:18:15, address = Greeter[0x000000010000315e], unresolved, hit count = 0
    4: file = 'main.swift', line = 20, exact_match = 0, locations = 0 (pending)
    5: file = 'Greet.swift', line = 20, exact_match = 0, locations = 0 (pending)
    6: file = 'Greeter.swift', line = 20, exact_match = 0, locations = 1
      6.1: where = Greeter`main + 34 at Greeter.swift:20:1, address = Greeter[0x0000000100003172], unresolved, hit count = 0
    7: Exception breakpoint (catch: off throw: on) the correct runtime exception handler will be determined when you run
    8: Swift Error breakpoint the correct runtime exception handler will be determined when you run
    

    需要注意的是: 设置断点其实是设置了逻辑断点, 可能会对应一个或多个位置断点(location).

    每个逻辑断点都有一个按照顺序从1开始分配的整型ID. 每一个位置断点又有一个自己的位置ID, 与逻辑断点的ID之间以.分隔, 用于定位位置断点. 示例如下:

    2: name = 'greet', locations = 1
      2.1: where = Greeter`Greeter.Greeter.greet(personNamed: Swift.String) -> () + 127 at Greeter.swift:9:12, address = Greeter[0x00000001000034cf], unresolved, hit count = 0
    

    逻辑断点是动态的, 如果程序载入了新的代码, 会自动载入新的位置断点.

    修改断点:

    breakpoint modify

    使用这个命令修改逻辑断点或者位置断点, 需要传递逻辑断点或者位置断点的ID 作为参数, 具体参数可以通过help breakpoint modify 查看.

    部分常用选项如下:

  • --condition(-c) 传入表达式参数, 只有表达式判断为true 才会执行断点.
  • ignore-count(-i) 指定跳过断点的次数, 在该断点处跳过指定次数后, 才会执行该断点.
  • --one-shot(-o) 执行断点一次后移除该断点.
  • --queue-name(-q) 指定队列名称, 该断点只有在指定队列上才会执行.
  • --thread-name(-T) 指定线程名称, 该断点只有在指定的线程上才会执行.
  • --thread-id(-t) 指定线程ID(TID), 该断点只有在指定的线程上才会执行.
  • --thread-index(-x) 指定线程index, 该断点只有在指定的线程上才会执行.
  • 如下示例修改了断点ID为1的断点, 指定其在执行后,自动移除.

    (lldb) breakpoint modify --one-shot 1
    

    很多选项在breakpoint set 中就可以被指定的, 通过modify 可以重新修改选项.

    在断点处执行命令

    我们都知道, 当程序抵达断点处时, 程序会暂停执行, 此时可以执行lldb命令.

    我们也可以通过执行breakpoint command add 命令, 让程序每次抵达断点处时, 自动执行我们添加的命令. 如:

    在位置断点1.1处添加指令, 每行可以添加一个指令, Enter 跳转至下一指令, 输入DONE结束添加.

    (lldb) breakpoint command add 1.1
    Enter your debugger command(s). Type 'DONE' to end.
    > thread backtrace
    

    可以将process continue 作为最后一个指令, 那么调试器就会在执行指令后, 自动继续执行程序, 这在记录Log的场景下使用是非常方便的.

    (lldb) target create "Greeter"
    Current executable set to (x86_64).
    (lldb) breakpoint list
    No breakpoints currently set.
    (lldb) breakpoint set -n greet
    Breakpoint 1: where = Greeter`Greeter.Greeter.greet(personNamed: Swift.String) -> () + 127 at Greeter.swift:9:12, address = 0x00000001000034cf
    (lldb) breakpoint command add 1
    Enter your debugger command(s).  Type 'DONE' to end.
    > frame variable
    > process continue
    (lldb) process launch
    Process 5997 launched: (x86_64)
    // 下面的frame variable 和 process continue 都是自动执行的.
    (lldb)  frame variable
    (String) name = "Anton"
    (Greeter.Greeter) self = 0x0000000100304540 {
      acquaintances = 0 values {}
    (lldb)  process continue
    Process 5997 resuming
    Command #2 'process continue' continued the target.
    Hello, Anton. Nice to meet you!
    (lldb)  frame variable
    (String) name = "Mei"
    (Greeter.Greeter) self = 0x0000000100304540 {
      acquaintances = 1 value {
        [0] = "Anton"
    (lldb)  process continue
    Process 5997 resuming
    Command #2 'process continue' continued the target.
    Hello, Mei. Nice to meet you!
    (lldb)  frame variable
    (String) name = "Anton"
    (Greeter.Greeter) self = 0x0000000100304540 {
      acquaintances = 2 values {
        [0] = "Anton"
        [1] = "Mei"
    (lldb)  process continue
    Process 5997 resuming
    Command #2 'process continue' continued the target.
    Hello again, Anton!
    Process 5997 exited with status = 0 (0x00000000)
    

    设置断点可用状态(Diable/Enable)

    禁用断点: breakpoint disable

    启用断点: breakpoint enable

    以上命令都需要指定断点ID参数(支持通配符).

    当逻辑断点设置为diable时, 它下方的所有位置断点都将不再生效.

    (lldb) breakpoint disable 1
    1 breakpoints disabled.
    (lldb) breakpoint disable 2.1
    1 breakpoints disabled.
    
    (lldb) breakpoint enable 1
    1 breakpoints enabled.
    (lldb) breakpoint enable 2.1
    1 breakpoints enabled.
    

    还可用通配符*指定断点.

    如下示例先是禁用了逻辑断点1下的所有位置断点, 而后启用了位置断点1.1

    (lldb) breakpoint disable 1.*
    2 breakpoint disabled*
    (lldb) breakpoint enable 1.1
    1 breakpoint enabled.
    
    (lldb) breakpoint delete 1
    1 breakpoints deleted; 2 breakpoint locations disabled.
    

    设置监视点(Watchpoint)

    监视点(Watchpoint) 是一种设置在地址或者变量上的断点. 每次地址或变量被访问时就会执行.

    监视点的数量收到硬件寄存器数量的显示.

    可以通过watchpoint set variable 设置变量断点, 或者通过watchpoint set expression

    传入返回地址的表达式参数设置地址断点.

    (lldb) watchpoint set variable places
    Watchpoint created: Watchpoint 1: addr = 0x100004a40 size = 8 state = enabled type = w
        declare @ 'main.swift:7'
        watchpoint spec = 'places'
        new value: 1 value
    (lldb) watchpoint set expression -- (int *)$places + 8
    Watchpoint created: Watchpoint 2: addr = 0x100005f33 size = 8 state = enabled type = w
        new value: 0x0000000000000000
    

    获取监视点列表

    watchpoint list

    (lldb) watchpoint list
    Current watchpoints:
    Watchpoint 1: addr = 0x100004a50 size = 8 state = disabled type = w
        declare @ 'main.swift:7'
        watchpoint spec = 'places'
    

    修改监视点

    watchpoint modifybreakpoint modify 类似, 修改监视点的信息.

    (lldb) watchpoint modify --condition !places.isEmpty
    1 watchpoints modified.
    

    在监视点处执行命令

    watchpoint command addbreakpoint command add 类似, 在监视点出添加需要执行的命令.

    (lldb) watchpoint command add 1
    Enter your debugger command(s).  Type 'DONE' to end.
    

    删除监视点

    由于监视点数量受到硬件条件限制, 在不再需要它的时候将其删除是很重要的.

    (lldb) watchpoint delete 1
    1 watchpoints deleted.
    

    参考资料: Managing Breakpoints