iOS_LLDB

作者: Lin__Chuan | 来源:发表于2018-08-17 21:13 被阅读34次

    LLVM 是一个模块化和可重用的编译器和工具链技术的集合,创始人是 Chris Lattner,也是Swift之父
    LLDB 是 LLVM 的子项目,基于LLVM提供的库和Clang构建的优秀的本地调试器。

    在命令行中调试程序

    在终端中使用LLDB调试器, 需要了解以下内容.

    1. 加载程序以备调试
    2. 将一个运行的程序绑定到LLDB
    $ lldb /Projects/Sketch/build/Debug/Sketch.app 
    Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
    
    1. 设置断点和观察点

    给main.m文件中的12行设置断点

    (lldb) breakpoint set --file main.m --line 12
    

    设置观察点
    作为断点的补充, LLDB支持观察点以在不中断程序运行的情况下监测一些变量。例如,我们可以使用以下命令来监测名为global的变量的写操作,并在(global==5)为真时停止监测

    (lldb) watch set var global
    Watchpoint created: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
       declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    (lldb) watch modify -c '(global==5)'
    (lldb) watch list
    
    1. 控制程序的执行

    启动程序

    (lldb) process launch
    (lldb) run
    (lldb) r
    
    1. 在调试的程序中导航
    (lldb) thread continue
    Resuming thread 0x2c03 in process 46915
    Resuming process 46915
    
    1. 检查状态和值的变量

    查看线程状态

    (lldb) thread list
    

    查看调用栈状态

    (lldb) frame variable self
    (SKTGraphicView *) self = 0x0000000100208b40
    
    
    1. 执行替代代码

    expression命令不仅会改变调试器中的值,还改变了程序中的实际值

    (lldb) exp a = 10
    (NSInteger) $0 = 10
    (lldb) exp b = 100
    (NSInteger) $1 = 100
    2015-01-25 14:00:41.313 test[18064:71466] a + b = 110, abc
    

    在Xcode中使用LLDB调试器本质上和在命令行中调试程序一样(Xcode只是一个GUI, 图形操作界面), 以上的步骤完全一样, 相关的指令可以参考苹果官方文档.


    在Xcode中调试程序

    help命令可以列出能使用的命令列表

    (lldb) help
    

    这里介绍一些常用命令的用法

    1. print指令
    • print命令会打印出对象的类型和相关属性.
    • print命令的别名有prin, pri, p,
    • po命令对于继承自NSObject的对象,会打印出description中的内容,类似于print函数, 对于struct, 会打印出属性

    Swift中的打印

    (lldb) print a
    (Int) $R1 = 10
    (lldb) print p
    (LCCustomTools_Swift.Person) $R2 = (name = "lucy", age = 12)
    (lldb) prin a
    (Int) $R3 = 10
    (lldb) pri a
    (Int) $R4 = 10
    (lldb) p a
    (Int) $R5 = 10
    
    // 结构体
    (lldb) po p
    ▿ Person
      - name : "lucy"
      - age : 12
    
    // class
    (lldb) po p2
    <PersonClass: 0x60000044a830>
    
    (lldb) 
    

    OC中的打印

    (lldb) p a
    (int) $0 = 10
    (lldb) p person
    (Person *) $1 = 0x0000608000010780
    
    (lldb) po person
    <Person: 0x608000010780>
    
    2. 打印视图的层级结构

    OC

    (lldb) po [self.view recursiveDescription]
    

    Swift

    (lldb) po view. recursiveDescription
    
    <UIView: 0x7fec9152ce10; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0x600000032120>>
       | <UIButton: 0x7fec9152b0b0; frame = (114 76; 92 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600000031520>>
       | <UIButton: 0x7fec9152b570; frame = (130 152; 60 30); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600000031a20>>
       | <UIButton: 0x7fec9152c7d0; frame = (177.583 229; 86.3333 60); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x600000031f00>>
       |    | <UIImageView: 0x7fec9152e240; frame = (10.6667 15; 30 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x600000033920>>
       |    | <UIButtonLabel: 0x7fec91530d20; frame = (41 20; 34.6667 20.3333); text = '撸串'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x60000008ce90>>
       |    |    | <_UILabelContentLayer: 0x600000035140> (layer)
    
    3. 打印视图控制器的层级结构

    OC

    (lldb) po [UIWindow valueForKeyPath:@"keyWindow.rootViewController._printHierarchy"]
    

    Swift

    (lldb) po UIWindow.valueForKeyPath("keyWindow.rootViewController._printHierarchy")
    
    <NavigationController 0x7fcf83807a00>, state: appeared, view: <UILayoutContainerView 0x7fcf82c09900>
       | <ViewController 0x7fcf82d09900>, state: appeared, view: <UIView 0x7fcf82c0c420>
       | <Button_ViewController 0x7fcf82e02320>, state: disappeared, view: <UIView 0x7fcf82d223a0> not in the window
    
    4. 格式化输出
    // 16进制
    (lldb) p/x p2.age
    (Int) $R2 = 0x000000000000000c
    // 10进制
    (lldb) p/d p2.age
    (Int) $R3 = 12
    // 8进制
    (lldb) p/o p2.age
    (Int) $R4 = 014
    
    (lldb) p/x 0x7fcf83807a00
    (Int) $R5 = 0x00007fcf83807a00
    
    5. expression命令

    expression的简写有exp, e。可以用expression来声明新的变量,也可以改变已有变量的值。我们看到e声明的都是$开头的变量。我们在使用时也需要加上$符号。

    (lldb) e let $arr = ["a", "b", "c"] 
    (lldb) p $arr
    ([String]) $R0 = 3 values {
      [0] = "a"
      [1] = "b"
      [2] = "c"
    }
    (lldb) po $arr[0]
    "a"
    
    
    6. image命令

    image命令可以用来寻找栈地址对应的代码位置

    NSArray *arr = @[@"a", @"b"];
    NSLog(@"%@", arr[2]);
    
    *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 2 beyond bounds [0 .. 1]'
    *** First throw call stack:
    (
        0   CoreFoundation                      0x000000011045d12b __exceptionPreprocess + 171
        1   libobjc.A.dylib                     0x000000010faf1f41 objc_exception_throw + 48
        2   CoreFoundation                      0x000000011049d0cc _CFThrowFormattedException + 194
        3   CoreFoundation                      0x0000000110510890 +[__NSArrayI allocWithZone:] + 0
        4   LCCustomTools_OC                    0x000000010f1cf878 -[AppDelegate application:didFinishLaunchingWithOptions:] + 184
        5   UIKit                               0x0000000110fe5bca -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 299
        6   UIKit                               0x0000000110fe7648 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4113
        7   UIKit                               0x0000000110fecaeb -[UIApplication _runWithMainScene:transitionContext:completion:] + 1720
    ...
    

    根据以上信息, 可以知道问题出在[AppDelegate application:didFinishLaunchingWithOptions:], 但是不知道具体在哪一行.
    通过以下命令找到出错位置

    (lldb) image lookup --address 0x000000010f1cf878
          Address: LCCustomTools_OC[0x0000000100009878] (LCCustomTools_OC.__TEXT.__text + 32824)
          Summary: LCCustomTools_OC`-[AppDelegate application:didFinishLaunchingWithOptions:] + 184 at AppDelegate.m:30
    

    问题出在30行

    参考自
    深入了解GDB和LLDB
    LLDB调试器使用简介
    LLDB之基本命令使用(Swift)

    相关文章

      网友评论

        本文标题:iOS_LLDB

        本文链接:https://www.haomeiwen.com/subject/qhmzbftx.html