【问题标题】:LLDB (Swift): Casting Raw Address into Usable TypeLLDB (Swift):将原始地址转换为可用类型
【发布时间】:2015-06-09 02:07:20
【问题描述】:

是否有可以将原始地址转换为可用 Swift 类的 LLDB 命令?

例如:

(lldb) po 0x7df67c50 as MKPinAnnotationView

我知道这个地址指向一个 MKPinAnnotationView,但它不在我可以选择的框架中。但是,我想将原始地址转换为 MKPinAnnotationView 以便我可以检查它的属性。这可能吗?

【问题讨论】:

    标签: ios swift lldb


    【解决方案1】:

    在 Xcode 8.2.1 和 Swift 3 下,lldb 命令 pop 将不起作用与类型变量。您将需要使用快速命令 print 来检查类型化对象实例的属性。 (感谢cbowns's answer!)例如:

    expr -l Swift -- import UIKit
    expr -l Swift -- let $pin = unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
    expr -l Swift -- print($pin.alpha)
    

    【讨论】:

    • 这真的不应该这么难
    • 这有点违反直觉。我以为我不需要在控制台中输入(lldb)。但没有它就行不通。
    • 有没有办法在objective-c中做到这一点?
    • 我一直在回复这个问题。我可能应该为expr -l Swift -- .. 创建一个 lldb 别名
    【解决方案2】:

    您可以使用 Swift 的 unsafeBitCast 函数将地址转换为对象实例:

    (lldb) e let $pin = unsafeBitCast(0x7df67c50, MKPinAnnotationView.self)
    (lldb) po $pin
    

    然后你可以像往常一样使用$pin——访问属性、调用方法等。

    查看这篇文章了解更多信息:Swift Memory Dumping

    【讨论】:

    • 对于第一个语句,我认为您忘记了“expr”或“表达式”。否则它工作得很好!
    • 我在 Xcode 7.2 中收到“错误:使用未声明的标识符 'unsafeBitCast'”。
    • 除了那个错误 (@devios) 之外,它在 7.3.1 中还显示了另一个错误:“错误:未知类型名称 'let'”
    • 请注意,根据上下文,您可能需要先使用 (lldb) settings set target.language swift 将 lldb 切换到 Swift 模式。此外,在某些情况下(例如,在从应用程序转换为类型时中断应用程序模块时),您可能需要使用 e import MyApp
    【解决方案3】:

    expression 的 lldb 格式似乎在 Xcode 7.3 中发生了变化。以下让我开始:

    (lldb) expr -l Swift -- import UIKit
    (lldb) expr -l Swift -- let $view = unsafeBitCast(0x7fb75d8349c0, UIView.self)
    

    【讨论】:

      【解决方案4】:

      对于自定义类,您需要导入您的项目

      expr -l Swift -- import MyTestProject
      expr -l Swift --  let $vc = unsafeBitCast(0x7fad22c066d0, ViewController.self)
      expr -l Swift -- print($vc.view)
      

      【讨论】:

      • 我收到错误:没有这样的模块“MyProjectName”。有什么想法可以解决这个问题吗?
      • @AlexanderStepanishin 尝试设置线程/堆栈路径,例如:“MyApp > Thread 1 > 12 main”
      【解决方案5】:

      Objective-C 版本

      po ((MKPinAnnotationView *)0x7df67c50).alpha
      

      【讨论】:

      • 这对我来说非常有效。在我的例子中,我在Debug View Hierarchy 视图中,右键单击一个视图,然后选择Print description of...。这给了我一个内存地址和类型,我可以放入上面的代码中。很高兴知道可视化调试器将控制台放入 Obj-C 框架中。
      【解决方案6】:

      从 Xcode 8/Swift 3 开始,这对我有用。 (这是基于@sfaxon's answer。)

      (lldb) expr -l Swift -- import UIKit
      (lldb) expr -l Swift -- let $nav = unsafeBitCast(0x1030ff000, to: UINavigationController.self)
      

      【讨论】:

        【解决方案7】:

        感谢以上所有答案,unsafeBitCast 也适用于 Xcode 8.3.2 / Swift 3 / macOS / Cocoa 应用程序。

        记住当前实例的地址

        (lldb) p tabView.controlTint
        (NSControlTint) $R10 = defaultControlTint
        
        (lldb) p self
        (LearningStoryboard.NSTabViewController) $R11 = 0x00006080000e2280 {
        .....
        

        稍后,检查它们

        (lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint
        (NSControlTint) $R20 = graphiteControlTint
        
        (lldb) p $R11.tabView.controlTint
        (NSControlTint) $R21 = graphiteControlTint
        

        如果发生这种情况

        (lldb) p unsafeBitCast(0x00006080000e2280, to: NSTabViewController.self).tabView.controlTint
        error: use of undeclared identifier 'to'
        
        (lldb) p $R11.tabView.controlTint 
        error: use of undeclared identifier '$R11'
        

        确保选择 Swift 源代码的堆栈框架之一,而不是汇编器之一。

        当应用程序通过单击暂停按钮暂停或因异常而停止时,可能会发生这种情况。通过相应地选择堆栈帧,让 lldb 推断出合适的编程语言。

        【讨论】:

          【解决方案8】:

          我花了更长的时间才弄清楚我愿意承认。它类似于@afinlayson 的答案,但有更好的解释(我希望!)和固定的语法

          如果您想使用 Xcode 的视图层次调试器检查对象的属性,那么这将起作用: 默认情况下,您在 objc 上下文中,因此您必须将其切换到 Swift 上下文

          1. 首先导入你的项目(如果你想使用那里定义的一些类)

          expr -l Swift -- import <YOUR PROJECT NAME>

          1. 使用它的内存地址将对象转换为你想要的任何类

          expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)

          1. 从对象中获取任何你想要的值

          expr -l Swift -- print($vc.<PROPERTY NAME>)

          示例:

          expr -l Swift -- import Football

          expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: Football.Ball.self)

          expr -l Swift -- print($vc.velocity)

          【讨论】:

            【解决方案9】:

            @Xi Chen's answer 在您的 LLDB 会话在 Swift 上下文中启动时完美运行。但是,在某些情况下,您可能会在 Swift 上下文外部的断点处停止;例如,当它是 Objective-C API 的符号断点时,或者处于 Debug View Hierarchy 模式时(至少从 Xcode 11.4 开始)。

            error: unknown type name 'let'
            error: use of undeclared identifier 'unsafeBitCast'
            

            在这种情况下,您需要使用 Objective-C 以旧方式进行:

            e MKPinAnnotationView *$pin = (MKPinAnnotationView *)0x7df67c50
            

            现在您可以随意使用$pin

            【讨论】:

              【解决方案10】:

              最简单的方法,swift 4

              expr unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
              

              【讨论】:

                【解决方案11】:

                po 是一个别名,这意味着它可以被覆盖。您可以通过使用 objc 处理十六进制地址来覆盖 po

                command regex po
                s/(0x[[:xdigit:]]+)/expression -l objc -O -- %1/
                s/(.+)/expression -O -- %1/
                

                要查看这有什么影响,您可以告诉 lldb 扩展这些别名:

                (lldb) settings set interpreter.expand-regex-aliases true
                

                我还创建了https://github.com/kastiglione/swift_po,它是 Swift 的替代 po。它处理对象地址,并且还有一些其他改进。

                【讨论】:

                • 从你的链接中,expression -l objc -O -- 0x76543210 只是对我的回应,它不需要从地址知道变量类!
                【解决方案12】:

                当在 Swift lldb 上下文中并处理 NSObject 子类(例如 MKPinAnnotationView)时,可以说使用这个 1-liner 故意切换回 obj-c lldb 上下文更容易:

                e -O -l objc -- 0x7df67c50
                

                在 obj-c 上下文中,e -O -- 等同于 lldb 中的 po

                【讨论】:

                  猜你喜欢
                  • 2018-02-23
                  • 1970-01-01
                  • 2017-04-16
                  • 2013-06-19
                  • 2022-07-07
                  • 2011-02-13
                  • 2013-01-12
                  • 1970-01-01
                  相关资源
                  最近更新 更多