LLDB(Swift):将原始地址转换为可用类型

127

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

例如:

(lldb) po 0x7df67c50 as MKPinAnnotationView
我知道这个地址指向一个MKPinAnnotationView,但它不在我可以选择的框架中。但是,我想将原始地址转换成MKPinAnnotationView,以便我可以检查它的属性。这种可能吗?
12个回答

216

在 Xcode 8.2.1 和 Swift 3 下,lldb 命令 pop 不能用于打印已定义类型的变量。您需要使用 swift 命令 print 来检查已定义类型对象实例的属性。(感谢cbowns 的回答!)例如:

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

70
这其实不应该太难。 - Lucas van Dongen
这有点违反直觉。我以为在控制台中不需要输入(lldb)。但是如果没有它,就无法正常工作。 - mfaani
2
有没有一种在Objective-C中实现这个的方法? - p0lAris
我一直在回到这个问题。我可能应该为 expr -l Swift -- 创建一个 lldb 别名。 - Koen.
3
正如在这个问题的另一个答案中所提到的,只需一次键入“settings set target.language swift”即可避免在后续命令中使用“expr -l Swift --”。 - Max Desiatov
我只是路过,想与您分享我的小观察:print函数在那里是多余的!它将打印出 () $R0 = {},这意味着表达式已执行并返回了空值。好吧,我个人不知道它被打印在哪里,但不是在这个愚蠢的调试器中。因此,您应该只写expr -l Swift -- $pin.alpha以在下一行上查看其值。 - vlastachu

60
你可以使用 Swift 的 unsafeBitCast 函数将地址强制转换为对象实例:
(lldb) e let $pin = unsafeBitCast(0x7df67c50, MKPinAnnotationView.self)
(lldb) po $pin

然后您可以像往常一样使用$pin - 访问属性,调用方法等。

查看此文章以获取更多信息:Swift Memory Dumping


对于第一条语句,我认为你忘记了“expr”或“expression”。否则它运行得很好! - jarrodparkes
2
我在Xcode 7.2中遇到了“error: use of undeclared identifier 'unsafeBitCast'”错误。 - devios1
9
除了那个错误(@devios),7.3.1 还显示另一个错误:"error: unknown type name 'let'"。 除了@devios的错误之外,7.3.1还显示了一个错误:"error: unknown type name 'let'"。 - carlos_ms
8
请注意,根据上下文,您可能需要首先使用(lldb) settings set target.language swift将lldb切换到Swift模式。此外,在某些情况下(例如,在从应用中断时进行类型转换时),您可能需要在其中添加e import MyApp - Patrick Pijnappel
这似乎不适用于标记指针。短的NSString、NSIndexPath、NSNumber等都被实现为标记指针,其中内容是指针本身的一部分。 - Ortwin Gentz

28

Xcode 7.3 中 expression 的 lldb 格式似乎已更改。以下内容可以帮助你入门:

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

23

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

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

1
我遇到了错误:没有这个模块“我的项目名称”。有什么想法如何修复它吗? - Alexander Stepanishin
3
@AlexanderStepanishin 尝试设置线程/堆栈路径,例如:"MyApp > 线程1 > 12 main" - Juanmi
@AlexanderStepanishin 你需要打断点。如果你在xCode中按下Debug Memory Graph按钮打断流程,它是不会起作用的。 - Bogdan Razvan

22

Objective-C 版本

po ((MKPinAnnotationView *)0x7df67c50).alpha

4
这对我非常有效。在我的情况下,我在“Debug View Hierarchy”视图中右键单击了一个视图,然后选择了“打印...的描述”。这给了我一个内存地址和类型,我可以将其放入上面的代码中。很高兴知道视觉调试器将控制台放入了一个Obj-C框架中。 - Trev14

13

截至Xcode 8/Swift 3,以下是我使用过的方法。(这是基于@sfaxon的回答。)

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

11

感谢以上所有答案,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)


7
@Xi Chen的答案适用于在Swift上下文中启动LLDB会话的情况。但是,在某些情况下,您可能已经在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


3

最简单的方法,轻松4

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

答案由:https://www.kproapps.com


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接