lldb inspection of swift variables within dynamic framework - ios

I am unable to inspect variable state within dynamic frameworks in the lldb debugging console. I am able to inspect the same code when I add it to the main application. Why is this? Is there a workaround? Any ideas?
(lldb) po URLSessionDataTask
error: <EXPR>:1:1: error: use of unresolved identifier 'URLSessionDataTask'
URLSessionDataTask
^

I had the same situation. I could create a class instant of anything in the main app but nothing in the dynamic libraries, when it was Swift code.
(lldb) exp let $a = RustyAppInfo() //class from framework
error: <EXPR>:3:10: error: use of unresolved identifier 'RustyAppInfo'
Fix for me:
(lldb) expr -- import rusty_nails //framework name
(lldb) exp let $a = RustyAppInfo()
My lldb version: 902.0.79.7. Notice, lldb knew I was trying to write swift code. In an iOS app, where you have Swift and Objective-C code, I always find it useful to type:
(lldb) settings set target.language swift
Answer was inspired by LLDB (Swift): Casting Raw Address into Usable Type

Related

Xcode po is not printing output in debugging area

Xcode is not giving expected results when i try to print any object. I am using Xcode 12.4 .. In another mac its working fine.
Ex: When i try to print the text inside the UITextField getting below
error
(lldb) po emailTextField.text
expression produced error: error:
/var/folders/5q/9vj8df5s0xs_2splf1fbwgzh0000gn/T/expr39-7ad9b9..swift:1:51:
error: cannot specialize a non-generic definition
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Swift.Optional<Swift.String>>(bitPattern:
0x10ba5a660)!.pointee)
^
/var/folders/5q/9vj8df5s0xs_2splf1fbwgzh0000gn/T/expr39-7ad9b9..swift:1:64:
note: while parsing this '<' as a type parameter bracket
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<Swift.Optional<Swift.String>>(bitPattern:
0x10ba5a660)!.pointee)
^
(lldb)
I have tried all the options given in the App Dev answers and tried changing the xcode, still no luck
Spammers stay and Don't spam with your unrelated answers

call methods on WKWebView from lldb

As I debug my app to find why the webview dowsn't receive my messages, I found out that another WkWebview (let's call it B) was created on top of my existing webview (A). Since I only have reference to A, I'm trying to evaluate js directly on B using it's memory address.
what is the correct way to do that in lldb?
Based on this answer, I've tried:
settings set target.language swift
e -- import WKWebview
e -- let $webView = unsafeBitCast(0x13299e400, to:WKWebview.self)
in order to call webView.evaluateJavaScript,
but lldb says:
let $webView = unsafeBitCast(0x13299e400, to:WKWebview.self)
^
error: <EXPR>:3:46: error: cannot convert value of type 'module<WKWebview>' to expected argument type 'U.Type'
let $webView = unsafeBitCast(0x13299e400, to:WKWebview.self)```
Thanks to #Kamil.S I managed to get it right.
The complete steps were:
(lldb) e #import <WKWebview.h>
(lldb) e NSString *$js = <my javascript to evaluate>
(lldb) e (void)[(id)0x10504ea00 evaluateJavaScript:$js completionHandler:nil]

How can I cast, inspect pointers given back from the view debug hierarchy? [duplicate]

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!) E.g.:
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)
Objective-C version
po ((MKPinAnnotationView *)0x7df67c50).alpha
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)
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.
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
First import your project (if you want to use some of the classes defined there)
expr -l Swift -- import <YOUR PROJECT NAME>
Cast object using it’s memory address to whatever class you want
expr -l Swift -- let $vc = unsafeBitCast(0x7fb7c51cb270, to: <YOUR PROJECT NAME>.<YOUR CUSTOM CLASS NAME>.self)
Access any value you want from the object
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)
#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.
The easiest way, 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.

Cannot inspect variables with "po" in my Swift 2 project using Xcode 7.3.1 - error loading helper function

When I run my Swift app in Xcode 7.3.1 (with standard Swift 2 compiler) and execution pauses at a breakpoint, I cannot inspect variables with po command. The first time I run po exists (exists is a non-optional Bool variable in current scope) I get a long error message (see below). From the second time I run the same command onwards, I receive error loading helper function: (null) message.
The app is compiled and run on the debug scheme, with no "deployment post processing" and None [-O0] optimization.
Variable contents appear correctly in the variable inspector panel of Xcode.
Same error appears with po self or any other variable both running on device and iOS simulator.
If I run a new clean project, debugging with po works correctly.
In current scope:
var exists: Bool = self.canRemoveAttachmentForEpisode(episode)
NSLog("Exists is now \(exists)") // Breakpoint is set here
This is what happens in the debugger panel:
po exists
error loading helper function: <EXPR>:141:9: warning: '--' is deprecated: it will be removed in Swift 3
--maxItemCounter
^~
-= 1
<EXPR>:237:14: warning: '++' is deprecated: it will be removed in Swift 3
i++
^~
+= 1
<EXPR>:267:19: warning: 'init(start:end:)' is deprecated: it will be removed in Swift 3. Use the '..<' operator.
let rng = Range(start: si, end: ei.advancedBy(-1))
^
<EXPR>:280:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
var $__lldb_error_result = __lldb_tmp_error
~~~~^~~~~~~~~~~~~~~~~~~~
_
<EXPR>:89:41: error: 'CustomStringConvertible' is ambiguous for type lookup in this context
if let csc = (x as? CustomStringConvertible) {
^~~~~~~~~~~~~~~~~~~~~~~
Swift.CustomStringConvertible:13:17: note: found this candidate
public protocol CustomStringConvertible {
^
Castamatic.CustomStringConvertible:1:17: note: found this candidate
public protocol CustomStringConvertible {
^
<EXPR>:101:41: error: 'CustomStringConvertible' is ambiguous for type lookup in this context
if let csc = (x as? CustomStringConvertible) {
^~~~~~~~~~~~~~~~~~~~~~~
Swift.CustomStringConvertible:13:17: note: found this candidate
public protocol CustomStringConvertible {
^
Castamatic.CustomStringConvertible:1:17: note: found this candidate
public protocol CustomStringConvertible {
^
(lldb)
(lldb) po exists
error loading helper function: (null)
(lldb)
I solved the issue. The problem was I was redefining an existing protocol:
protocol MyCustomStringConvertible {}
extension MyCustomStringConvertible where Self: RawRepresentable, Self.RawValue == String {
..
}
I redefined CustomStringConvertible protocol, or maybe Apple's CustomStringConvertible didn't exist when I wrote my own version of it. Probably the protocol is only used by po when debugging, so the error never came out at runtime.
My only doubt is this: shouldn't the compiler alert me for redefining an existing protocol?

Debugging with Swift & Xcode 6.4?

Why po returns these strange errors? (with Xcode 6.4 & Swift)
I try to debug with p / po:
NSDictionary, String and NSNumber all getting similar kind of errors all the time.
For now, I use println() but I am curious what could be the reason?
error: A fatal parse error has occurred. LLDB may become unstable; please restart your debug session as soon as possible.
error: <EXPR>:1:11: error: use of undeclared type '$__lldb_context'
extension $__lldb_context {
^~~~~~~~~~~~~~~
<EXPR>:11:5: error: use of unresolved identifier '$__lldb_injected_self'
$__lldb_injected_self.$__lldb_wrapped_expr_7(
^
For swift language use println() method.For debugging in console you have to keep in mind that you can only get debug info for swift's variables, but can't get it for swift's constants. So change let someVariable to var someVariable.
then in debugger do po someVarible. It will work.
If it doesn't work for arrays & dictionary ,for arrays do something like po print(myArray). Same goes for dictionary.

Resources