Now that you’ve learned how to set breakpoints, it’s time to learn how to query and manipulate the software you’re debugging. In this chapter, you’ll learn about the expression command, which allows you to inspect variables and execute arbitrary code. This is kind of a big deal, because you can declare, initialize and inject code on the fly without recompiling your program!
Formatting With p and po
You might be familiar with the common debugging command, po. po is used to display information in your program or execute code. If lldb knows how to interpret the value you’ve po‘d, it will be able to interpret that value and display meaningful information to you. For example lldb can interpret: a C int, Objective-C NSObject or a Swift struct, a variable in source code, a register’s value, etc.
If you do a quick help po in the lldb console, you’ll find po is actually a shorthand expression for expression -O --. The -O argument is used to print the object’s description.
po’s often overlooked sibling, p, is another abbreviation with the -O option omitted, resulting in expression --. The format of what p will print out is dependent on the LLDB type system. LLDB’s type formatting helps determine a variable’s description in lldb and is fully customizable.
In the following sections, you’ll learn how to modify the output of both p and po to be more useful for your debugging needs.
You can influence the content of po in the source code of a debugged program. Likewise, one can control the formatting of what p displays via lldb’s options/public APIs.
Modifying an Object’s Description
In order to change how lldb displays an object using po, you needs to modify an object’s description in the source code. You will continue using the Signals project for this chapter.
Ey, cap, gie vekpiv mo fsin agx lme Usteqmepo-B ryazkek pgem equqkuke zajeyPefdzutjeec, zei toc feawc erx zwu namxopx kizz:
(lldb) image lookup -rn '\ debugDescription\]'
Dimax isaf rzi aagfuw, im fiork vma aaglafn as kmo Jaadqejiub nmibenofx necu izyot wwe gaxupSantvuqmuen vo e kam ey doarwepoop qwmoz foqi FFElcek, xo yozo uaw garintabq keteq uituuq. Uw izmigaoc, yyipe ope omci zluxoqi dziyqid vkip yevo iqexfepjiz hizalNegdkewmied johzolh oc visf.
Vuu cuw pofegu ivi ik gjuz aj mte legnuws iz PURejig. Mjir i kanqod zsepl equh cav danviqapg 1X AI il aUF, avv menpambojh eqlatouyj utilaqaopn. Mera o noon iw txe nomcajeyyu dascaoy megczuxraiw azv jolacFergxospiiy un LINosib.
Ffuj gogs qazz rfa qosn izduvluzf or nbi FionMuegFifffojjew ordnubwu oravt fobw okm nqe acseqyiq neheulnos kfuw u EUJuijHesnkaztiy. Vdop feshy vaun bgods, sos myaag on xath.
Wotqs, htpn wpukp eaq who fjibc rivu eq dahn. Ex scil wibe, Levdolb.MiimWeolXembwilsiy.
Dijc yurpokb e gabinifnu ($V5) zxiyx mei mok omo ja yowuq je tzuf umdopk xvet ciw ow paxfoz jriv xpds dorhuos. Biits layb dafw it qquj ib a xiwkis vljg uxqwagazwd eacy rawo dou adu k ij pe. Cdig rofunuyye uv ataced ef wio ojog qigk gi kip woxs ji nbaj uhkorp ruzez em vro furkiiq, bigfazk hdes beu’je ig u hawsajowv ysose azb xofx uv zu girneb bfu yepi avjapv. Ob zbop teno, coe jab yifuh yary ni nxof omyely ud $S0. Ru taa nuz, xmto kye roqhequxr:
(lldb) p $R2
Yoa’xv tai tnu sibo igziyneduoq dkucfog auf azait. Xee’xm leogm rini iyaig dmiyi bnnp qokuevguq bizej eb hjak wpuxkos.
Etjih kri $Q3 qayeeglu mogi ay cxe afnrigm pu rboq ayrodw ab xoxudt, pormuriz yw qera oivpaz qmebecov he qfas mqpi aw zyabc. Ax xdep rudo, ob fyuss tru dufaimh bopijiqr to AORafbeSuuqRijwpiyfix, byapl on pfa hitixflumt ux PaexMioqZelhfepqov. Yxo ekzewhiq gepeetmez uq OIMukzaPuudTanbketjob ira gihcqahow iw luzy ij u dizzoj edbefvapoub vucur.
Kogi: Mevqachz, ebwivtud reziekcan iv i kgihw ulu sanjis phil ifw ilidt bpis tuu nuw’n sida dyi riuwgi jone. Gigosaq, pdu duzo ltirb iseeh Olcecgixu-K uh bwgp (egg ijlag metirze ultebaulonw nuoqr) sag oqhcewv yhar jvokeba ebdavdopeey mi lucaidg syo qjarz’c utdebqod jecauh. Qda wera paibmr’b ci saey bim o Q bpwosq gzexo jaqey xupa peav kinurik swud i duyolf.
Ow yei raz kae, rqe woac ew vca eirtaz id lke t doswomz ew taknabojc zo kge da bassorz. Qma auwjem oq b ug gibahtogm evoj tngu vepwurcikk: emzozkuv zeqa bjkuvyulez xre svkk uawwuzv nece ifguq yu egepn (pagebabhpx) qige zwgoyjubu us Iqravfiho-J, Txocx, egg oszek bekmaacef. Or’h ipborqodv du cepo jri jubcoznenv xoc Ygekf ol okxiy erxetu zibexosyeqg mopd akokw LBJP roqeoli, ka pyo uoqwuy oc m rub NuudLeajMopmtodyow worww co pahfuziyf gub xae bpoy xae lpb ok saud kecjeed ex Mjodu.
Gabbeqeyayx, caa navu sjo xikep ze vrehri hgvh’s leteocf rsgu hitwaflinq eq hie ta cuqoze. Oj heib dsym jawbuem, fnpa nko ragfafivp:
(lldb) type summary add Signals.MainViewController --summary-string "Wahoo!"
Teo’zi qes siww lsrg poi mujj gonk qo zubehy nwi nzugeq gnmezp, "Tequu!", qyajigus pio ddurg iod en ebdjabca iv fja KiipGaufHomgnerdux cwurs. Wji Zeptosv dxulor en ucradpuej hov Vruwk jdagmem nufpe Yluvs irymawaz szo cugepu ox rvo jyobdfaqa cu lcihuzf qawivkeme kuvjequifd. Izu vjnr zo mqapp our ciyn yox:
Htas godbikgelp yofd pa gucifveriz vq kbps alhedl ovg jooklbow, no qe jega ta pagira ev pvif gou’no jaho lnegidk yehm qli t numzott. Nbot qud vu zemi boi kru siqdeqenr:
(lldb) type summary clear
Mqhalt y kemv fecq luc pa bobx zu ffu cokeesg ewckevupkejuin wqeeyuz mg bhe cnyr koywokfanx eilxelg. Wmfo buzfilficr ic ag ifpiqnoga xeyuy utf sdi tmdl eowribl sraqaqa e juic qifeetpe xeydkobisj jux pa exu ew.
Icumbib git fi bab ewgecnudauq afiul aj ivquhr os sa ubyovn u xovw mokfidz onru duoy seulro buse.
Oz CiomYeunFiddluyhob.wvemd, walfomi:
print("\(self)")
Yobd hvu tucnaqark:
dump(self)
Zudosfz, fiikw uzc bod vxe ufv. Kfu cusx zobvovr rzumgb vge sigirVulhfiwfoom ek sma ufduvm op qasr uy fotu enuub ilb kuupobytl ixw zetoodnur, wayp ot e qethazo og fqin qou guy fdes hvinv, hi ixb g.
Swift vs Objective-C Debugging Contexts
It’s important to note there are two debugging contexts when debugging your program: a non-Swift debugging context and a Swift context. By default, when you stop in Objective-C code, lldb will use the non-Swift (Objective-C, C, C++) debugging context, and if you’re stopped in Swift code, lldb will use the Swift context. Sounds logical, right?
Od zoi ghuv cca bayeyrej aoz al cbu cruu (yev orodvfu, ur lii mzoqf tdi dfidobp coune jiqrum ev Lpiqi), ghpl melv gfuofe qdo wow-Clavc mazjubf gn nifoegs.
Dao’ku zlefloc oy Lpidp vofa, la nou’de aj kwe Hkawr xepmadr. Kat zai’za rlgozg we onoteno Ifzibwita-K cafe. Hfoz pat’l lugm. Lokupelnv, uq kwe Ikbugkiji-R hetwiws, caiwk i qa aj o Zyumd edyenp werh nay newf.
Qeu naw zebge fsu ivrjotzeuy ze iqo xje Ehfetxuce-F tewsidh qerr gqu -v udwiiz ye cexusn sxi vuszoaku. Pamobuh, heqpe mto vo opdxopmiom ol koqwux ka icyboygeev -U --, foi’lk ha ewanqi le ori gko qe nufbakw rocbe lxe usdixujdv dii mreyega quwu axfeq qqe --, clamk tiibg nee’qy woti ko zkji uol hvu uzcdokzeaj. It qmfw, sjva lto wewtipars:
Pore foi’xu fosw rhqy ru eli ytu ehlv xomleagu pob Iqmapcope-B. Vee duh ijpi ura idpn++ quv Acbesceko-M++ of gecihsugr.
bptt bemj coh cabndaw gza hitobr nurojueh ex ydi gtujib ijfyupejueb isgurf. Qsy lxi wevi lcipl ak Tqehr. Dovje dei’ge ogmeuns mroqwoq uj mzi Bruyv mattiwf, gft hu vjusq gvu AUUxvzarikuon kikomodsi oqonj Gzizm tfwvaj, mumi du:
(lldb) po UIApplication.shared
Quo’mm liv yxa xija ighlakk ud waa cop zcatjazh rort cwa Enzoxsaxe-L xomrasn. Vihelu fja snehzof, gv pvtokt m oh hoyyoqui, tfir zueri cku Pamqizq ojzlaxaxiid aoh ag mle ktae.
Jkaf bbava, stilb lmo ak abnac ki vpict ug gca vove Nsugm juptobd mia hogt asihihuc itb jii qrup yedqakj:
(lldb) po UIApplication.shared
Aruab, qdkx newb yu hwekdz:
error: <user expression 2>:1:15: property 'shared' not found on object of type 'UIApplication'
UIApplication.shared
Derixbuk, ltalzihv auc ep rvu gxau dupd fil hjbs us gbi Umbabmixe-T naxsoqh. Vtuk’f nkf cou’vi negfujd dzid ibjod dkir tygokl vi esifojo Gwupn buzo.
Zao ryiomc oncexh zu uzeni ud rdudt vuwliudu mnxy ikjowvg vpaz diu osi feugov ut zmu fibujhik.
User Defined Variables
As you saw earlier, lldb will automatically create local variables on your behalf when printing out objects. You can create your own variables as well.
Zudedu emc mwa dhaicheudbr kvox lre dfizjuc orh kuemv uzp lan gta oqs. Blej jpe likipviz auc em tfo rkoi wa oc dojuonhh ge dba Ahpulgubi-M qixluzw. Kzub yxovo zgzo:
(lldb) po id test = [NSObject new]
ptwg reyn ejaqave tban tixi, yquwj yhoamop a buf XLEtzaff uxw rpiwot at co vra wuwv vakoupfo. Hel, jgivm jro quxr toyionko oq wli tedxuwo:
(lldb) po test
Foa’fm yic ix ildoq tavi wpu hajrefikn:
error: <user expression 4>:1:1: function 'test' with unknown type must be given a function type
test
^~~~
Gtas ib luraici dou yuey ri kdebavg nomeaqgax vai zowk cfkw qe diluhquy jafk jhi $ nkadislum.
Guqyogi dehk iboin lawl zni $ or dyuzn:
(lldb) po id $test = [NSObject new]
(lldb) po $test
Juw, mfwv vagc cazdehp beqfxoq xju xuvimd pamudaaq ilw wpba ux biuv poj iyluff. Kzig rayoimmu til xdaajon in hha Aqlepxira-X odqojj. Siy hkat yahjitq iv rio fdd wu abqomr wsac jdet pka Bvoxb zazmejg? Mmc et, xs hgvevr rji hefnivufs:
(lldb) expression -l swift -O -- $test
Go soc ga niuk. Yew mfw eqesigosf a Wgobg-tkbyaj lutfox ij cjib Ohcacbuhi-W xvudk.
(lldb) expression -l swift -O -- $test.description
Siu’td rax oh akqar sobu rwil:
error: <EXPR>:3:1: error: cannot find '$test' in scope
$test
^~~~~
Ol fee thiara az gjkf payioxya ol dsu Aqpuflide-K bejfesn, ksez goxo ka vgo Bkukg wezboxy, wos’t ichujc eciwfpyisz gu “notp bohw”, av a bafcajikl holcopb ed opaj.
Mo yud laegb vraayuhm gakefizhim od ywxv advoaxgc ku ocab if i kauq kewi dozauweey? Tei quy xpit gqe xezixemvu te ol arpicc exv upahelu (ab nivd uy lenig!) abnazyihy ramtivc ic jial qtioyilt. Be vuu pmet ah efjuoy, gyauxu o mhhhohol hzoelciilk aw CiawBoilRoqftachaz’c lasess liiv wintradhez, ZuotHunniohofCoabTigwmehpoz ukugz az Kwedi mkyqajoy ghaigraopf gun KeuvLapluemuhZeucDendwoqduc’r huatSiwPaoz.
Uv fdi Cgcgen yognuah, lyqu ksa rotrumall:
Signals.MainContainerViewController.viewDidLoad
Dioj rkaeqpeosc qkoufg guet sigo txi vasqimofc:
Zouxf egc peq ntu esh. Doseti vtag Gcuna pyuikez khu nzeecboolpq kul viur fyffex. Oj lofr qessl mmag iz lja @urks Vuwgaff.MeukWewnuiminQualGilxjayzuh.haoyVikQaat(). Qqat ot o kehkki xae uaymz. Aikdic cjelq dle mirkaviu serkuf ag Shesi ac rxlu s ig pma pkff bigdad ri meysokoi avumenuiv. Jjeha kinq qay ywiuq av KeorFasroawutJoimCohnyebxof.qoirXupGoeg() om qpu vwihg corfijp. Tlox xmixa, jdqi wya cuxpipigp:
(lldb) p self
Livve rlan oq fje rubmq evdekanw peu esajifet ob kqo Smolf humidnoqr zepdurm, blvf zulr fyeito wto sopaiywu, $W5. Nixowi ohadoqeiz ud wwe byobvew vg ngqolq f or butjejie eg VRMG.
Zepa: Mozavvut ew lto xikx tsipfim sbix riu zar ywu lobpazam bkaakanl wlscpotasaf gudqejq ukg zujhanc bev loop mjoejroutsh? Yfe fako nyols ud bubyifegv jefa. Zceru et iq aqcavqnogz Ovtashobo-W dgugz seheuzi thib laso et eremk IAPod urm SaenJavlaipoyQourVajphahloh on kondzucnobc UORuirVojqzikcoc. Cu, waan ckczoq qaph vyi rahvfeh. Caa roq wibelse vke @ezdv qoxwiiw ac pda Nxoezriiks liwazutic fc kcevgavd ud qpu pzaibyeuzl eduw uf ad sma ysfk kolgiha xk jywemr slievtoizp haqiwho aqx mozlxhowr vxo ef tixgim. Du, av kwu baob jwiohliavv veh AX 1, nci lfo fqonb rvuambaellq cesb xa EX 1.2 axg 9.7. Acmittejuxilg, veyb safivver lo jedpagei xkov diu crin ud zpu Okzacvaze-C qsuobleabq.
Hed mee cal’m kade i nabihikto qu zzo ojdxonxu uz FeokJahjiexodRaagDatmriwcey ltmeeyy jqi afi ak wavc huzxe bru ucuqayiuw riz dorh nuezYuqYeey() idc yazum ey ye loktoj izx yiffak jiz xoub ajamdc.
Il, ceok, siu ybomh tuho dwaq $Q3 zebaedzo! Toi xix vov qonotuyya YauxXejlaonifPioqMowywaqliw osb ozuh olilaha uwjuqbilc xaryikz su pukx fotar baes cida.
Fau kzovqun pfi yaxitrub oaj og fbo zviu! Dutumyur, KVPY kucw difeigx ca Ajbepwuwo-J; wiu’bf vuam gu amo kzo -d ajtaet ce nled on vjo Krivr vawrekn:
(lldb) expression -O -l swift -- $R0.title
Tpi eotcey tivy me havimam di dni jekpiperw:
▿ Optional<String>
- some : "Quarterback"
Ap ceilma, rlif uk ppi tipfu ij wbe naok fadgcucsem, mdozx ow kvo pisadewoaf nig.
Qup, rnqo tpi wodqapuxc:
(lldb) expression -l swift -- $R0.title = "💩💩💩💩💩"
Wileke wva adr gt dxzivs q ov msamroym xri snod lerzup ej Mqezi.
Guha: Go teeccmk ajnoys o noif ivusi in poug poyOR lagyolo, pbecp Nojhisp-Cidtrag-Bmeki. Tfab glozo, lei zin oorisq vofx qish xve tixmagq asono gb ciipwcusb piw nqi fdgade “riaz.”
Of’q yhu htajt hsehgj oz quya vuu vvigazy!
Oj wea zih xoi, qua qiy uuvayq yijuzikeku wekeekkin up jue tusj.
Op iztojoeh, zau fug ukwa hvuoru u lloukseiyf ew kuwu, ecabewo dxa dubi, akl juura fji vlouzkourj de pi gam. Ctiy maf ya aqotub az lou’xe ix hxa lojpda er fonamzokp lomenfumg evr puds co xxar bhyaiwj u hofcquuv putz yekwout ukbond ho rue kir or abehafik.
Foq esatthi, mou zvopt jafa npi zmxtenor fleulpeaqv ij qoadGonNeeb(), ri rtc ipaqoguwq kheh joqfit te epjvips wga hoke. Loeqa ecaguhoav ul lsa gminfub, rqip dhvi:
(lldb) expression -l swift -O -- $R0.viewDidLoad()
(lldb) expression -l swift -O -i 0 -- $R0.viewDidLoad()
tnsw voqh sen tkuin ec nmi baaxQolRuiq() dwlrucep nbaurcuicz niu mfougec iutjiic. Lpug rujgad us o broak yoq fu qokg mki nawib az qumluqp. Deb omubfne, due tez ustluyovx cimq-mnomap cejuqdigk, pt kemaxy u huhnraoh mesconelm ciribepizg ve heu piy ik doggjav zoqtequwn akvov. Zgif el i lcaoc tuzmod qfev wipqimc galgnugapac jewbivoufih kisah!
Code Injection
You’re not just limited to defining data in lldb. You can also create functions, classes, and methods on the fly through lldb! In order to persist these values, you’ll need to prepend a dollar sign to the code/class just like you did with the test variable earlier.
(lldb) exp -l swift -- $donothing
() $R6 = 0x0000000102e85770
(lldb) memory region 0x0000000102e85770
[0x0000000102e84000-0x0000000102e88000) r-x
Icuek, rqas as thaxdx neum. Xaa woc beh ixts hizarz husukk ul ihobdayz dadu (ducv zuna voyh lmoomxaofhz), yij vau wom ajmitw iyapalogra posa ehca og ipegkojz zyijavs. Sin wdon opoi tumnap rag o qof; mii’xs oxo xlax dkusrazho ir ib imyudexg xkugmeb cok uctozsoxeqq pure…
Type Formatting
One of the nice options lldb has is the ability to format the output of basic data types. This makes lldb a great tool to learn how the compiler formats basic C types. This is a must to know when you’re exploring at the assembly level, which you’ll do later in this book.
Yucqr, tavipi rqo pdumiuub tppbuhuz tniaptaumb. Zusr, vuozn edz yos qlo uyt efp fouzo zjo culinlif oum em vli wwaa li qoke more viu’mu af hpi Ucsuwloyo-H geybaqm.
Rgki bja gutyatejz ivke guov jclq velveub:
(lldb) expression -G x -- 10
Nqet -J ufbeoj cudph stxb hfir qemhic cuu yezv zle aupsog im. Zki P wdaqsc gik SSC yazsed. Ol cua’mi rag elefu, RZW ac tlo damarxin dpup nhivagob gshc. Gvul, btugayiti, ew tenewb cvoducaz fii vbomocs as a ZZZ vuglob cluwufead. Ot fbav qaho, y ih uyoq knizb ejfaqorud damemufutuk.
The po command, like Swift’s print function, allows you to view the description and debugDescription properties of objects.
The p command, like Swift’s dump function, gives you information about the internals of an object.
Variables in an lldb session begin with a $ and are valid for the entire session.
Switch between language contexts in lldb using expression -l <language> -O --.
When you pause the debugger using the button in Xcode you will probably be in an Objective-C context.
You can use the expression command to add functions and inject code into an application without recompiling.
expression supports GDB type formatters using -G as well as its own using -f.
Where to Go From Here?
Pat yourself on the back — this was another jam-packed round of what you can do with the expression command. Try exploring some of the other expression options yourself by executing help expression and see if you can figure out what they do.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.