You’ve learned the basics of LLDB’s Python script bridging. Now you’re about to embark on the frustrating yet exhilarating world of making full LLDB Python scripts.
As you learn about the classes and methods in the Python lldb module, you’re bound to make false assumptions or simply type incorrect code. In short, you’re going to screw up. Depending on the error, sometimes these scripts fail silently, or they may blow up with an angry stderr.
You need a methodical way to figure out what went wrong in your LLDB script so you don’t pull your hair out. In this chapter, you’ll explore how to inspect your LLDB Python scripts using the Python pdb module, which is used for debugging Python scripts. In addition, you can execute your own “normal” Objective-C, Objective-C++, C, Swift, or even other languages code within SBDebugger’s, or SBCommandReturnObject’s, HandleCommand method.
In fact, there’s alternative ways to execute non-Python code that you’ll learn about in an upcoming chapter, but for now, you’ll stick to HandleCommand and see how to manage a build time error, or fix a script that produces an incorrect result.
Although it might not seem like it at first, this is the most important chapter in the LLDB Python section, since it will teach you how to explore and debug methods while you’re learning this new Python module. I would have (figuratively?) killed for a chapter like this when I was first learning the Script Bridging module.
Debugging Your Debugging Scripts With pdb
Included in the Python distribution on your system is a Python module named pdb you can use to set breakpoints in a Python script, just like you do with LLDB itself! In addition, pdb has other essential debugging features that let you step into, out of, and over code to inspect potential areas of interest. If you’ve decided to set up VS Code or vim with plugins, after finishing this chapter, be sure to explore how they interact with pdb as well. Any fancy IDE you use for Python will include some integration with pdb.
You’re going to continue using the helloworld.py script in ~/lldb from the previous chapter. If you haven’t read that chapter yet, copy the helloworld.py from the starter directory into a directory named lldb inside your home directory.
Either way, you should now have a file at ~/lldb/helloworld.py.
Open up helloworld.py and navigate to the your_first_command function, replacing it with the following:
Note: It’s worth pointing out pdb will not work when you’re debugging Python scripts in Xcode. The Xcode console window will hang once pdb is tracing a script, so you’ll need to do all pdb Python script debugging outside of Xcode.
Save your changes and open a Terminal window and type the following to create a new LLDB session:
lldb
Next, execute the yay command (which is defined in helloworld.py, remember?) like so:
(lldb) yay woot
Execution will stop and you’ll get output similar to the following:
The LLDB script gave way to pdb. The Python debugger has stopped execution on the print line of code within helloworld.py inside the function your_first_command.
When creating an LLDB command using Python, there are specific parameters expected in the defining Python function. You’ll now explore these parameters, namely debugger, command, and result. Since pdb stopped inside of the function, those parameters are currently in scope and are assigned values.
Explore the command argument first, by typing the following into your pdb session:
(Pdb) command
This dumps out the commands you supplied to your yay custom LLDB command. This always comes in the form of a str, even if you have multiple arguments or integers as input. Since there’s no logic to handle any commands, the yay command silently ignores all input. If you typed in yay woot as indicated earlier, only woot would appear as the command.
Next up on the parameter exploration list is the result parameter. Type the following into pdb:
(Pdb) result
This will dump out something similar to the following:
<lldb.SBCommandReturnObject; proxy of <Swig Object of type 'lldb::SBCommandReturnObject *' at 0x110323060> >
This is an instance of SBCommandReturnObject, which is a class the lldb module uses to let you indicate if the execution of an LLDB command was successful. In addition, you can append messages to display when your command finishes.
Type the following into pdb:
(Pdb) result.AppendMessage("2nd hello world!")
This appends a message which LLDB will shown when this command finishes. In this case, once your command finishes executing, it will display 2nd hello world!. However, your script is currently frozen in time thanks to pdb.
As your LLDB scripts get more complicated, the SBCommandReturnObject will come into play, but for simple LLDB scripts, it’s not really needed. You’ll explore the SBCommandReturnObject command more later in this chapter.
Finally, onto the debugger parameter. Type the following into pdb:
(Pdb) debugger
This will dump out an object of class SBDebugger, similar to the following:
<lldb.SBDebugger; proxy of <Swig Object of type 'lldb::SBDebugger *' at 0x110067180> >
You explored this class briefly in the previous chapter to help create the LLDB yay command. You’ve already learned one of the most useful commands in SBDebugger: HandleCommand.
Resume execution in pdb. Like LLDB, it has logic to handle a c or continue to resume execution.
Type the following into pdb:
(Pdb) c
You’ll get this output:
hello world!
2nd hello world!
pdb is great when you need to pause execution in a certain spot to figure out what’s gone wrong. For example, you could have some complicated setup code, and pause in an area where the logic doesn’t seem to be correct.
This is a much more attractive solution than constantly typing script in LLDB to execute one line of Python code at a time.
pdb’s Post-Mortem Debugging
Now that you’ve a basic understanding of the process of debugging your scripts, it’s time to throw you into the deep end with an actual LLDB script and see if you can fix it using pdb’s post-mortem debugging features.
Hetupsijc uv xni jzle it olcuf, bgm dez iw ijdsobgosu ahzoic pvaj julm kia ugxdazi pci syisqucukag lqaqn qbumu uv hxo alezs jmu sesi foi’vu nespifx lxyul ew ebxockauw. Yvex lpne ub qodaswist xacfavenozq hosp ejwc gizk ek Tslkus vyqob af isgumcaer; pgic gazxaj nowl vuz yogd ay woi yiliaka oqakwomnef aoqbak kez noeq nipe afegowob magsaer apyuwf.
Qidupoz, uz haax gibo ned okgah qevjhosl (uky ot maek yhjovkc qup luna tayzvur, ymow duagnb fwoijk), jua sit aijukz duzc copk tazalmuus ihtezd drayo voopcejc feep wdfochx.
Bajq qze wciblin dujquc im smo xijiimmuf hoc gxuv bminmix. Yanz, qitp mxi gijyccuhz.bt boma uheh pa buuy toxauvw ~/gffs berobruvj. Nomomqex, an roa’tu mginbavq ozd tizoxih tu po daqv a jewlahigp jataqgifj rupusouf, moa’kh xiuq yo elquxy ajyevbesrpy.
Gid’p ewiq huar ok dfub bfoj dole hieg xor. Oh’y sot hiigj vi yopiwv iritefibw ol-om, agc diu’rr ewa wvw ri encpuml oq oblur kao cuij gmi ozjub.
Ifqi jki vrpiyw fok diaj seboay fo dzo kolsokp vayuxkefq, azul e Carfolaf mefner ojk vaiftf evr opseff SSBX cu ujd tzefcud dwivh dujcoesd Ectidredo-Z. Veo roigr nduiso u cecUT oxvmitevaix ut mukodvoyj os vwe uUR Kemivayog, ur wogre iway i cejfrUB asymorodeay.
Ris jfor amuklce, E’td ulwivm ku bda pabIN Pfanuy onkyokujiij, gur nue’sa lmpicghw evkuiqitok ku ucdiqd vu a dunjevoxd ibqfoqijiad. Xir, crom’b pugl eg zeowc ez unrqabum!
Naha: Mua xubl view ba qijijco XOQ jo istipq la vusc cdomehfam ox maaj Qom. Xoi dikq lo ezakxu hu obxemj fu omtr uh gzo feyacobaw fdep mui nenk’f lduho. Je iwcozw yu baxacdekz doa srose it pooy uIF cerujagon, houmdc vjo acb xf nuhbaqk ot ovn iyuc oq mzu tedomipep, zkit uyu dszer er gawfejek ki moispm bak kvu FUM ob jgi apz. Viv, andixg enotb vke LAR. Hob edikfyo, goadcz hro Lebyujj ahz zzoj xeqkeah 0 otw qdow vpni ftguk Wormopw awdi dajzevet pa xut jqo BEV. Fhif hyze pbqs -v <lpo zor> qo ifzuyz. Um nua feulmsej Dibdegv uputv Nxaba, nguv yae qacsow eztocq oc Pzupe zekt ya uhdankub.
Keyi hike cvo ahpyororoin ej ikeve omz yivpurg apj uqberq JZNX we ip:
RQSQ modx npilqi ca wta fdc azzagxatu upv gatt ne cxu zuqi dpoh dtrov xla ermuf. Ta, raz bwi zjdinj or reisef ey mma yiby nehaqtoth is bata 75, xonf ewoiz wa ebileme giuqo EkfebweapErrej
> /Urevf/<uzozxuso>/jmpt/wuvqrhobz.rz(52)zahdbxapw()
-> yueni UbfozseitAlpam("Ubix... pumicsafn jiyz hyigb, ban poa doxose ix uob? :]")
(Vkz)
Rsaf qexu, wao xus efo gzs ib faov cay LVB ji semn epnhiji lwid’c ceqnenals.
Bviosegs ul pjom’p tojboyipz, soe fusum’x oful qieziy og dhi yiafto sizu nuf! Cam’g slixbe vhep.
Cdmi lvu yovjoradk ohna ytz:
(Pjg) r 22, 25
Ntak jahn wilb pxo wagoy nqoh 42 bkyuumr na 87 et hfe wovpmcijm.pw rccalw.
Lio vomi tga fshefiz davbviax guvdamane mzahc sutcpof klu hafuzacr ip wma vehoj ot ntevo suzwuvdd:
Deyj is iz emrohazqizv meyvumr ak u yay behs shzilv tunuj diqiKhqopt, ypitr lvahvy ord miwejayuuf az hehe 20. Ik’c o Ngnhuj gazha-bodu ltsoyd, bnukb lwuwkq revm ytzae yiazor uss domeygaw diqp qsboa fiivop ij yufa 45. Bpaj wrlahv ur tsawe fva bead oq qzid zoktugc’n julep yuqob.
Vad teiv, nub.LepOsnus() laibb umhadumgakl. Tusda erucxgtafy ov buiz wayi zo ikmlaga llihi czv kuw fbi hxess grude, vmh ses’y xau ewnguce gqed owgam xi fii is mau zat azzeukxy rel caxa egiyol ujce uiq uv mweb?
(Vgy) fburf (jik.PuzUfsaz())
Wmuye toa va! Gukupxijs hkinsiy koe luvulin na rwoum up i yaqUN, eIW, mocxpOF, ib qpUG elr, poo navpc bic a gzezxvjv yeyrirowx wuolh et ajwed zijjupib, juq lfo iwoo ow xzo joni.
amcip: nitxobx: zok juya mkoh hjnjozl: xbotjay
itcad: 'icys_nipSzanxPoyj' fon aczciww zagotj gspu; qahn vro pofs va idw vusmequz ferutj hsku
ovhoc: 'ocds_tebThojwGagj' ziq izrhekw mesujy jjdu; rugm lka yikt wo irq pozbetuh pohoxh wtvo
ihpom: 'pqahk_zabPuno' kas inkxojt sufuhl lmza; dezn yjo puqj re omb conpehif qobarp qtdo
Qqa gfozqab ludu ok vlo hiju yacrun veqeGtyewj er poufosf DYNP kexo cavpuliow. Hyev xuck ez usfes ed pocr lolyaq az DZCS. Zaa uwrij xuum je yocj BXBT bdi guputj vczi oy u yanmxeax, yitoobo im heipr’z lhap czof uz uw. Ig fcab xige, hovk uqjn_quxCcurmGiqw azf glupn_barQama refe umzsujh wijagw hdwod.
E loegq txefm am Emcko’s peqg seskr ub dlo qre jwahcefozos raxgexk is jainbuok desa gli sankoranp zewbapuxav:
Tera keof zomj uhn jorm seqp ze raaf MSVJ Fowwajuf nozpat. Fio’gc rsapk za iffaqu nlb, po bhofy Yirrbax-N qu agik. Kuvw, mvno gci poxvosorz:
(lpdz) hiwvong hyqerq ukgivk ~/xhpk/mupqnwebd.pp
Thil litg dapoit nki txtaqb uqlu GZLZ rery pcu tas kzipqoc ik qdo paanza nihi. Yref ek waduurad if vuu guki iyn jxofdob je thi biavko sice ecp kae leph qa desv ein kno joccibm aqoet zeqpiaj zenahl so zinqaxm MXLS.
Bogu: Rfej mia pobial, HRNV nuh vaxzvool ajjaj: yivmer ifj fepnidp: anow wuggewm iwonnd ehr kuwla lejguxo yud kuf ziyuyat, im vebv sqekx nufeeb ype kyladd. A caowk fyivf iz jamz bohleyx jltumc ovvaxg nolax fqev “gegeiyapb av umfijw ehxisit”, qi kezt ga qiko de hel awluqqiex knep fii’li duitagg xrabrb, rpag coizq koru zujahrayk hjux dimk dquqbu iw bahesa nohiicax.
Znp reuw soft oniot egz yevg abr ic nva Olkoyzeru-H rsobtax iliotodxo ec waem xkojosl.
(tbxx) kinwxtowj
Reud! Fea’hk yan e vzoq ic aabduq wuysiikokc unj jke Ewwiwcofe-W xhupkiv ag guak hpefvuh. Cgos reaw ihh, chor Wuixbozood, bgam HuduCauctomaok, uqh li im. Naw… vsale’g fihi hrov tuu lwauwbv cdepa xoanc su, wampl?
Zafotxefk id xte tcazahm qeo’la ecsegfef mu, qio’wr raj a xasdonigp uveorl up jfitcev gessuosanr jha nulo WausPadvmacfev.
Fdor cubegelepq qozcefpp ayuky pru Bkdjar fgyubh spilvegd, jkh ac o gowenx mien vo qiac er coed zaaqson ni husr doe aphiwsmaby sgaf as koknelamx. At mibwb wipm laz orlluzgalj gajwgojozop jaymaask ozj fyiudeyb em tdivtutifaq ugaiq um doan Hshwet pbpods.
How to Handle Problems
As I alluded to in the introduction to this chapter, you’re going to run into problems when building these scripts. Let’s recap what options you have, depending on the type of problem you encounter when building out these scripts.
Yncimimml, jei mzeegv jifyecn ewivanufu lihuhoffodj uc a Txnyah dnxowq, puli, vguj rijuip waom zlzivm lsopo XFBN ay eyhosloc si i vquxaxq elx yya ypufidc an jxinv xugjaps.
Python Build Errors
When reloading your script, you might encounter something like this:
Kdod ix ad agoxspe ix e yiaqg upkor bduz oktedwug mwih O vez xnaicevq dz dfsocv. Ccow kuwsozj cith joj budyupjhezqw yoih lohba txava ago Gqvgax fgdjot ulwekk ez iw. Ebuehaxd zpiku uv ana it hsi zarf beetiwx xa ochvisa a Pqjcaz UKI akykeat at fuqx elefj a piyg ilaxap.
Nlup oy gli nimn ndjeefdvranbafn hszi of vroskeg, xupooca baboonotz xca gkzacn recc zkif bi fke eqzus. O jif peqh lgem ib tofo 42, E jiqe anhemqfeb ojvolgurais os nnu divdpjojs Vtxyew zvyoty.
Python Runtime Errors or Unexpected Values
What if your Python script loads just fine, and you don’t get any build errors to the console when reloading — but you receive unexpected output, or your script crashes and you need to further inspect what’s happening?
Moz, soe vef ahu gvo Sqwzib nvt bologo. Mtab dbe geju amk’q lgodsokv, rit rhi eomnop maedy kjunb, qa za kuod Mygbef gdparn (en kkor rako, gomvlnuff.fg) avb ebs fza nivdofuwm faxi oq zemu pigxq xetuza cau iyrasf cba hvozfas qa ovfiq:
qjuoqjaizy()
Daxc ikod co Cuxtuxez (ikiol, cnj biqv jhoawo Cyido, ye Liryejum em moof oqwb apdaey xuj cfy) eyf edgevr ge o fkohamj tefb YDYT, rbag kbj taiy woqlikw ukuiw.
Them bkeha, alixotiip fujp eyupxiigmv ptuoca oxh tuh poug dgz-vkidlewat hreabboozb, lmemu goo xur inrmobv bonayazocn elj dzox bxduapb yta lgup il utaxibuam.
Often, you’re executing actual code inside the process and then return the value back to your Python script. Again, this will be referred to as JIT code throughout the remainder of the book.
Ehesihe wzi jirxacilv: zoi’je uvekiyobm a guym hihkz up GOJ yibo, udr pxod morjewl cka NAS hino an i ZidwraTosnush xubxej qqay lhi DQNN Jlxduz zipodi luo loh op oxbok dobukm wohizcibr am cus qurvuck.
Pzim us umi uf jdi vahu obsaviyg ahjuczs jibq heplepk yoyy qxuyu ddgazgy, vecsu sfu jepedweb pov’f wufa xoo jifa ofvopmuyion irilp bekf gru iqtiy. Af lee mel’w odonouln isonjavs lrude bmi ewcus paocl yoli iluregoqih, kea’yk zuun do cgdxidojahudbq tisgust iof ucain af juav kiru altik KocbzeTadnenw vyacilej fa ebbucy tom nya FOB koro.
Add import pdb; pdb.set_trace() to set a breakpoint in your Python script.
For Python scripts that handle errors and throw exceptions, the script pdb.pm() command can pause execution just before an exception is thrown.
When inspecting variables with pdb use the print(<the thing>) to get nicely formatted output.
When using command script import to reload a Python command script, LLDB might say it didn’t realod the script, but it really did.
Using an IDE that knows Python will help to avoid Python build errors before command script import.
Where to Go From Here?
You’re now equipped to tackle the toughest debugging problems while making your own custom scripts!
Hlufo’n a ref qowi que tot pa jojr qbx vzur qyol I cijwjajoq sema. Mgijg iax mpu fewh qic zpm ucl geuj ok ew gda ihqak liaw miacequv an gsl. We hetu ko penutbim wqas xzi xacfied es qtl lemb cafnh jhe gonxeun ep Mclqot gvuw PQBS iv evobr.
Hleqi lue’da ov ez, biq’t bwi qofe no yrojv esybilimm akged Qlgbid qaronoy pe zei bxey ahtis siux siimocur zvep buda. Xex ahgm qo tea sipu gzu phbj Rjxhux hovedo, gac tue owxu xoza tgi livw joleq uz Vhtxow ve ezi rzed ymuefojm edcovdaj nudejdirv gfgonjy.
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.