Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I Define And Use An LLDB User Variable?

Tags:

swift

lldb

I am defining an lldb user variable as follows (no errors reported by lldb):

(lldb) expression -l swift -- let $servicesButton  = unsafeBitCast(0x127979670, to: UIButton.self)

When I attempt to use the variable I get:

(lldb) po $servicesButton  
error: use of undeclared identifier '$servicesButton'  
(lldb) po $servicesButton.isEnabled  
error: use of undeclared identifier '$servicesButton'

What am I doing wrong?

BTW: In case it matters, I broke into the debugger by clicking the Debug View Hierarchy button. I then printed the description of a UIButton and used the displayed memory address in the above unsafeBitCast.

Update: I am using Xcode 10. Here is another series of lldb commands that illustrate my problem:

(lldb) expression var $temp = 5
error: unknown type name 'var'
(lldb) expression -l swift -- var $temp = 5
(lldb) po $temp
error: use of undeclared identifier '$temp'
(lldb) expression int $xxx = 5
(lldb) po $xxx
5

Update 2: I seem to be getting somewhere:

(lldb)  settings set target.language swift
(lldb) expression let $yyy = 88
(lldb) po $yyy
88

Update 3: Finally! Setting the target language does the trick. I don't know why my use of the "-l swift" option was not sufficient but I'm happy to be on my way.

(lldb) settings set target.language swift
(lldb) expression
Enter expressions, then terminate with an empty line to evaluate:
1 import UIKit
2 let $button = unsafeBitCast(0x105a23e10, to: UIButton.self)
3 
(lldb) po $button
<UIButton: 0x105a23e10; frame = (134.5 3; 74 29); clipsToBounds = YES; opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x101b7b180>>

(lldb) po $button.isEnabled
false

(lldb) 
like image 723
Verticon Avatar asked Oct 02 '18 14:10

Verticon


1 Answers

The "expression" command chooses the language to use from the language of the currently selected frame. If you just interrupt the program to run the view debugger, chances are the current frame will be C, ObjC or C++, which is why you had to set the -l flag to swift. You figured that out, the one tricky interaction was:

(lldb) expression -l swift -- var $temp = 5
(lldb) po $temp
error: use of undeclared identifier '$temp'

For that you have to remember that "po" is actually an alias for:

(lldb) expr -O -- <EXPRESSION>

where the -O flag means "print the object description of the result of the provided expression." If you do help po it will tell you this at the bottom of the help text.

So po first takes the expression that you provide, runs it using the current language (you see where this is going...) and then fetches the language-specific object description method (e.g. in Swift by running the Mirror for the object) and prints that out. You correctly made $temp as a swift variable, but you tried to get the object description of a C variable called $temp, which didn't exist.

If you want to use "po" in any frame and have it apply to swift objects, you either need to force the default language to swift (which your use of the settings set command did) or you need to run:

(lldb) expr -O -l swift --

Note, btw, that you can't do:

(lldb) po -l swift

because the po alias ends with -- which is the marker that you are done providing options and all the rest of the text on the command is the expression. That's done so that:

(lldb) po -5

didn't confusingly tell you there's no option called 5...

like image 142
Jim Ingham Avatar answered Oct 21 '22 20:10

Jim Ingham