Is there an LLDB command that can cast a raw address into a usable Swift class?
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?
Under Xcode 8.2.1 and Swift 3, the lldb command po or p won't work with the typed variable. You will need to use the swift command print to examine the properties of the typed object instance. (Thanks to cbowns's answer !) Eg:
expr -l Swift -- import UIKit
expr -l Swift -- let $pin = unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
expr -l Swift -- print($pin.alpha)
You can use Swift's unsafeBitCast
function to cast an address to an object instance:
(lldb) e let $pin = unsafeBitCast(0x7df67c50, MKPinAnnotationView.self)
(lldb) po $pin
Then you can work with $pin
as usual – access properties, call methods, etc.
Check out this article for more information: Swift Memory Dumping .
The lldb format for expression
seems to have changed in Xcode 7.3. The following got me started:
(lldb) expr -l Swift -- import UIKit
(lldb) expr -l Swift -- let $view = unsafeBitCast(0x7fb75d8349c0, UIView.self)
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)
As of Xcode 8/Swift 3, here's what worked for me. (This is based off @sfaxon's answer .)
(lldb) expr -l Swift -- import UIKit
(lldb) expr -l Swift -- let $nav = unsafeBitCast(0x1030ff000, to: UINavigationController.self)
Objective-C 版本
po ((MKPinAnnotationView *)0x7df67c50).alpha
Thanks to all the answers above, unsafeBitCast also works well with 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.
It is likely to happen when the application was paused by clicking a Pause button or stopped with an exception. By choosing a stack frame accordingly, let lldb infer a proper programing language.
@Xi Chen's answer works perfectly when your LLDB session was started in a Swift context. However, in some cases you might have stopped in a breakpoint outside a 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).
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:
e MKPinAnnotationView *$pin = (MKPinAnnotationView *)0x7df67c50
and now you can use $pin
as you would.
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
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
expr -l Swift -- import <YOUR PROJECT NAME>
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)
expr -l Swift -- print($vc.<PROPERTY NAME>)
Example:
expr -l Swift -- import Football
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: Football.Ball.self)
expr -l Swift -- print($vc.velocity)
最简单的方法,swift 4
expr unsafeBitCast(0x7df67c50, to: MKPinAnnotationView.self)
po
is an alias, which means it can be overridden. You can override po
by handling hex addresses using 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) settings set interpreter.expand-regex-aliases true
Also I have created https://github.com/kastiglione/swift_po , which is a substitute po
for Swift. It handles object addresses, and has a few other improvements too.
When in Swift lldb context and dealing with NSObject
subclass such as MKPinAnnotationView
it's arguably easier to deliberately switch back to obj-c lldb context using this 1-liner:
e -O -l objc -- 0x7df67c50
where e -O --
is equivalent to po
in lldb when in obj-c context.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.