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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29441418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:29:37  来源:igfitidea点击:

LLDB (Swift): Casting Raw Address into Usable Type

iosswiftlldb

提问by jarrodparkes

Is there an LLDB command that can cast a raw address into a usable Swift class?

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

For example:

例如:

(lldb) po 0x7df67c50 as MKPinAnnotationView

I know that this address points to a MKPinAnnotationView, but it is not in a frame that I can select. But, I want to cast the raw address into a MKPinAnnotationView so that I can examine its properties. Is this possible?

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

回答by Xi Chen

Under Xcode 8.2.1 and Swift 3, the lldb command poor pwon't work with the typed variable. You will need to use the swift command printto examine the properties of the typed object instance. (Thanks to cbowns's answer!) E.g.:

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

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

回答by gregheo

You can use Swift's unsafeBitCastfunction to cast an address to an object instance:

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

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

Then you can work with $pinas usual –?access properties, call methods, etc.

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

Check out this article for more information: Swift Memory Dumping.

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

回答by sfaxon

The lldb format for expressionseems to have changed in Xcode 7.3. The following got me started:

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

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

回答by afinlayson

For Custom Classes you need to import your project

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

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

回答by cbowns

As of Xcode 8/Swift 3, here's what worked for me. (This is based off @sfaxon's answer.)

从 Xcode 8/Swift 3 开始,这对我有用。(这是基于@sfaxon 的回答。)

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

回答by rockhard

Objective-C version

Objective-C 版本

po ((MKPinAnnotationView *)0x7df67c50).alpha

回答by Tora

Thanks to all the answers above, unsafeBitCastalso works well with Xcode 8.3.2 / Swift 3 / macOS / Cocoa Application.

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

Memorize an address of current instance

记住当前实例的地址

(lldb) p tabView.controlTint
(NSControlTint) $R10 = defaultControlTint

(lldb) p self
(LearningStoryboard.NSTabViewController) $R11 = 0x00006080000e2280 {
.....

Later, examine them

稍后,检查它们

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

(lldb) p $R11.tabView.controlTint
(NSControlTint) $R21 = graphiteControlTint

If something like this happens

如果发生这样的事情

(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'

make sure that choose one of the stack frames of Swift source code rather than assembler one.

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

It is likely to happen when the application was paused by clicking a Pausebutton or stopped with an exception. By choosing a stack frame accordingly, let lldbinfer a proper programing language.

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

回答by Gobe

@Xi Chen's answerworks perfectly when your LLDB session was started in a Swift context. However, in some cases you might have stopped in a breakpoint outsidea Swift context; for example, when it's a symbolic breakpoint to Objective-C API, or when in Debug View Hierarchy mode (at least as of Xcode 11.4).

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

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

In that case, you'll need to do it the old way using Objective-C:

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

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

and now you can use $pinas you would.

现在您可以随意使用了$pin

回答by Bartosz Kunat

It took me longer to figure out that I'd like to admit. It's similar to @afinlayson answer, but with better explanation (I hope!) and fixed syntax

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

If you want to check properties of an objects using Xcode's view hierarchy debugger then this will work: You're in objc context by default so you'll have to switch it to Swift context

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

  1. First import your project (if you want to use some of the classes defined there)
  1. 首先导入你的项目(如果你想使用那里定义的一些类)

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

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

  1. Cast object using it's memory address to whatever class you want
  1. 使用它的内存地址将对象转换为你想要的任何类

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

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

  1. Access any value you want from the object
  1. 从对象访问您想要的任何值

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

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

Example:

例子:

expr -l Swift -- import Football

expr -l Swift -- import Football

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

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

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

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

回答by Dave Lee

pois an alias, which means it can be overridden. You can override poby handling hex addresses using objc:

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

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

To see what effect this has, you can tell lldb to expand these aliases:

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

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

Also I have created https://github.com/kastiglione/swift_po, which is a substitute pofor Swift. It handles object addresses, and has a few other improvements too.

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