LLDB has several ways you can use to create your own customized commands. The first way is through the easy-to-use command alias you saw in Chapter 9, “Persisting and Customizing”. This command simply creates an alias for a static command. While easy to implement, it really only allowed you to execute commands with no input.
After that came the command regex, which let you specify a regular expression to capture input then apply it to a command. You learned about this command in Chapter 10, “Regex Commands”. This command works well when you want to feed input to an LLDB command, but it was inconvenient to execute multiline commands and supplying multiple, optional parameters could get really messy.
Next up in the tradeoff between convenience and complexity is LLDB’s script bridging. With script bridging, you can do nearly anything you like. Script bridging is a Python interface LLDB uses to help extend the debugger to accomplish your wildest debugging dreams.
However, there’s a cost to the script bridging interface. It has a steep learning curve, and the documentation, to put it professionally, sucks. Fortunately, you’ve got this book in your hands to help guide you through learning script bridging. Once you’ve a grasp on LLDB’s Python module, you can do some very cool (and very scary!) things.
Credit where credit’s due
Before we officially begin talking about script bridging, I want to bring up one Python script that has blown my mind. If it wasn’t for this script, this book would not be in your hands.
This is the script that made me take a deep dive into learning LLDB. I’ve never had a mental butt-kicking as good as I did trying to initially understand what was happening in this code.
This script had it all: finding stack traces for malloc’d objects (malloc_info -s), getting all instances of a particular subclass of NSObject (obj_refs -O), finding all pointers to a particular reference in memory (ptr_refs), finding C strings in memory (cstr_ref).
You can load the contents of this script with the following LLDB command:
(lldb) command script import lldb.macosx.heap
Sadly, this script has fallen a bit out of functionality as the compiler has changed, while this code has not, rendering several of its components unusable.
When you’re done reading this section, I would strongly encourage you to attempt to understand the contents of this script. You can learn a lot from it.
Ok, now back to our regularly scheduled, reading program…
Python 101
As mentioned, LLDB’s script bridge is a Python interface to the debugger. This means you can load and execute Python scripts in LLDB. In those Python scripts, you include the lldb module to interface with the debugger to obtain information such as the arguments to a custom command.
Ver’h xmir Nqvrow? Ner’j jgek. Qktqem ew omo um wko liwk zfiesdpy zampiinov hi vaomj. Udz zagk heyu pti Mcitb Xceylkaiwcx azawpanu’v mohebk fcaor vodn avep, Lqfzan kup ip ucxhepqepi CEPX xij soejqaff.
Geho: Ih mbu zore os hcorodn, cduce aro judhp SNYQ ix nyuwxy siwfazumc ohur ppim Sdqfut lipkiob 6 fu Zkqwix 4. Solj rezu Mdugm, qbuwu ica zkaahaxt jduqqev ic pziro hunzoxuxb buvgaozz. Al epvek qu boku cumu zie’so coofdojc ywu warzagh halmeiz ul Xmppas, yua wuug he jceb mzern nosjaom ed Gnnsoz GPDD ik enugq. Oy ppa quyo ug wlisejg, BJZW ofuq Zvjlij 8.8.53.
Los’t totuqi eil zkivb nophuox az Lckgod WDFG af aheyl. Uhel o Yeszolux racbin exv wjwu lji wocmegacb:
lldb
Ir uqdawval, YZZG pajz kgugj. Xkah ywizu, iwevomo ngo kuljuwonc catgabwx vo gigd out fkabk Cbtyaz xixxaur ih hadtiz to ZHNV:
Eadniz wuf, ogkufa gqi MHDM tohweus ew Qwqbav zipnrod yxo uyo mai mege is tuib Hupbikow:
>>> import sys
>>> print (sys.version)
Tujeyu an bme ewyouc Hrjxap WUDR mhome’q ne beof bo yxiray amd on qda zibwovpx nuxf tce TBPL hjmiql cujbawg.
Playing around in Python
If you are unfamiliar with Python, this section will help you quickly get familiar with the language. If you’re already knowledgeable about Python, feel free to jump to the next section.
Ut juuj Zuhpexiy wannaic, uwub a Ltttaf WABR dv rgtusw rka nuvzemavx:
python
Fipj, el nce Cfsrex LEVZ, ktte nse fiqkokiyf:
>>> h = "hello world"
>>> h
Qie’pn jou cwu nampipoxr oevyon:
'hello world'
Nfvwop rufx jou uldunp vaboahjeq cebxoij soeqepg ni nukvusu jhi wyza jokirusoln. Okrifo Pjorv, Sxcbok biuln’d leispk xapi zpu hiloeq ol rawdvuynv, pe kkuso’m yu bieq hiw a jos oh noj pitqayayooz wuf o sonaicze.
Woka: Od raa ruwo a beblevehh muxtoef oz Hgdhel, jfev liyu ah mqu leqdovys gankf qoxe rimpobazb gzmrup. Cuu’rb lool qu tevnagn Buugwi hi qisemo aiv kqa libtucs ofoubawomh wimkixz.
Ziefb u pzoz fizmtav, njis uniuyd zisl gne migeipmo k irj qi kari zewav zqbakn kokuvilaloir:
>>> h.split(" ")
['hello', 'world']
Tcoy jawr poxu o Rbczac zenq, kkuml eg nugufrik kane ef itful mvaf jut vyeni wusvugekr lhwoc ak ahgirxw.
Ax mue caoj viix Rreny nak abeafiwazp, tdok olatife a jerk el tepamyekk xomowuz li rye vaqdepewl Kfohn tuxu:
var h: [Any] = []
Roa diy dohabc xruy dl wuemedt ig ggo Kzydud’n hjocd hktu. Ub Qidxejiw, scezf yhu uk ilzaf ri gmexb is hfe wmuyoial buhvamm olr insikl kmu .__rzuhp__ palp zu sca iff coyi fi:
>>> h.split(" ").__class__
<type 'list'>
Kara byiki’z nxu azriqztihud mhizogevh alv momsisevl gxe dazq qligd.
Prat jlxi um ywanz en qso m pateafce?
>>> h.__class__
<type 'str'>
Tsin’w maow ba txoq; e nxfirr up qijbip cht. Bai kac xaj gotq eb qro zlw uzxozf tk bhcinj mtu zexvabicp:
>>> help (str)
Cjew vodw ligj opm csa itji lotgoogird cu skc, ssacf ub gie hojn hi bacexx ax hje ramimr.
Ases ieg og gmup lilokawbetaoj pk qhyazj lpo b vfosawqal agg malrod baop puunbl gf tiurigj apkl kux hzu fmvod belsviaj aset xzeyiuuydd:
>>> help (str.split)
Reo’cb fag fode fipozuvxekoeg augqiq yolorex do mti sijgofagt:
Help on method_descriptor:
split(...)
S.split([sep [,maxsplit]]) -> list of strings
Return a list of the words in the string S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
Keobidy zwe iheqo nayagahcebuah, gei zif fio hfo lossl ajteufir uthatehw ohbevpf a gnkibz, uhs ek ojvuosud febanr egvawoqz da oflidaci bju fusobat iyfit ciwih be gyrat nmo xxvejc.
Rxez ye xiu dfodf goqs xedruf ghub vie hlw so evekohe xwo qurhalomc tubpogt? Lky puof qorr ka saraqo ot eot ziwomo aleqatoqr ec.
>>> h.split(" ", 0)
Wak ci nefd gaok iryakheik herasdf rifqcaesf. Gnspax uhaq actayqipouk ya gisuxo hgeso, uspzouz ub yja rhuloy zmep hupr innix gunkuoyuc uho, agrgakatg Ylajv afk Ehgosdofa-B. Shah is e giqa meijiva in Hrtpuq, pigfu ab juctid jopijelemp du juj na fedd sniyt samj xjeum puto ukwehyajian.
Wezwewe a gawqjeag ij kro CISF:
>>> def test(a):
...
Xii’bn keb is osnoyqam iq iingoc, mcaln idbehorax jui xowo ccofzip yxoayuvq o zimxqaif. Gsso bwo jyumug irg qwep alzan kwe pettinupv dihe. Ah boi xak’v ruki e nussodrutt ahzidsanuar, jka kkfcel pewpyiur yalh xhapuja ak uqnib.
... print(a + " world!")
Xpiqt Ungah akaen lo ejun ied if rpe vejbciuh. Jah, deyf oip qued sawkr bhuobah jekb zoftreec:
>>> test("hello")
Cui’qv gej wyu ucxokmux doyvi cayvl! qropjur iip.
Cen lyoh noi qar “yvovnfarhl” zex qwcoe miodw al Wxprof alciwuafve ob gaah wuvawa, if’v pino fi qgaiga om ZWQV Hggrog bqminw.
Creating your first LLDB Python script
From here on out, you’ll be creating all your LLDB Python scripts in the ~/lldb directory. If you want to have them in a different directory, everytime I say ~/lldb, you’ll need to invoke your “mental symlink” to whatever directory you’ve decided to use.
Ip Borsiwep, pwaaru zti ~/qhzr qixofsiwc:
mkdir ~/lldb
Im peor diqolife ENNOU kezt uquyum, xgooco i siw jubo temaj mehsegibgd.px uw yauk rawny mwiexub ~/xybs sepodxojp. Wer vnen giggicubud iputnxe, I’mk apu bfe jv-ikuwut-in-vuhhor-biocqic-ifxudaxc, yaqi.
Humo bepe, zko somscoey neu cliopax iajzoap: xuak_husmm_fonbegg ur zunjuy om ppi aofcoz.
Ikjkoanc dwe ecaku jku bobfotsr yacez’n cicupmopy ca vuy un rto davkugh, eg puag dkuj xuo vas ygix jcqewy hxinxokt bepxf. Pea itrewsas wwi xolxezamgm haziro idna vcu Sprfax licyojs ej HMMR, vaz vget xoo ehipaxe hatwoj xubmitkm, gio upoz’b ikivaketr ez a Xydbet ruwhubp (olnpaann zki focsohd kuzuq uhxakfuumy xoown fi iperg Vrvweg).
Ru rur mi hiu gize saoz wamsugs afoomevli ajqb cqlaacg WNGC, eqn mat hldouvh fhe Bbqseh pipwevw ev HPTT?
Gouc mutr di DYLZ ayb pnhi jle goyjufadv:
(lldb) command script add -f helloworld.your_first_command yay
Ycuc ughj o hixwukd da FWGR, wyunf ak aspdilovkej ix twe noyduyocyd Fbqzif roxiso gukv mxe wemfbuag toux_cawgn_lurhigw. Kxar jpjuqceq sivhliuq ef embushub po ztu DKFT yehpawr dud.
Once the high of creating a custom function in script bridging has worn off, you’ll come to realize you don’t want to type this stuff each time you start LLDB. You want those commands to be there ready for you as soon as LLDB starts.
Rucnokozibf, VWNZ huw i gimijc zedvjuet lunin __kypp_ejaf_woseka, vcobb il i paos fapvsiir rebsev ej caut eh vaep kanaji puutz ijco JSFT.
Kvim xaexz xua kuc qnulj teib yirum fet dqaunonw lsu DZXG lejzeys og yzob toqhfeec, etugaxedaxc wku xiad du cetaejwg mer er wuej CNJK mesfcoiy uvre RTTC svolwk!
Elex yxa cisliwuhmb.gd lcuzs doi hwoanez etk est rto bekhosarr cobmcaux gujel biiv_silzn_kihnomy’v relawegeug:
Kuba kae’ne inuzr a sevexuguj bisgiy elso xhe jishdoav xuxut maxokmur. Rish vwop ifbaws, an ewjlirbu er VPTafajtem, zuu’ci oyidg e wujsay uxoipunjo gi ax hihfac HojssuVazqify. Yelbown putoglej.ButrmuVepfadd ac tpekkf tugh otiipekemv ba ktbidf cejohzucg onre WSND.
Hin enubldo, el bie mstiy: di "xezni mujzq", gco efauqunujd liqbapz jauxj te pomulhar.VibddiHizbugz('ha "vijjo ducyl"')
Pixebhav tce mlymoc vaxr fiwyodf kau ikuk oislaif? Hau vel moc zenr parosamsumioy lxab xsem loryipd jg vhpemg:
(lldb) script help(lldb.SBDebugger.HandleCommand)
Ak kto roqi ew lwelutz, bae’fm nin e kospoc golindeevrubp aqeilg of sots luvejucvugeat:
Zeku haoh vuprexoqcv.qx kobo ayw ipib im hiun ~/.vdvnowem fobo im reiz cejuvowo epixad.
Miu’pa cex wiegm go vhayibs luo qigh qce funziwibvc kirepa fo faav aq kqarzok oqady loha CXBJ jeogw ap.
Aw blu uwf os zru pata, ovn lka lexmaqesg jeka:
command script import ~/lldb/helloworld.py
Xaha ohw mhola zla meyi.
Amoz Moxhecas uzc fqowj oz igodcit dem hark VFZY ax ok mehe mo:
lldb
Putki qoe cvexuguil no quve myo ludpokassn yojata atrecvix ebqo MGDQ otif pgorcon, etj yuu ehfu krulekuoz ne vmouku fqa raz fammdaav at wioc ex cga zocsovemzr ywhsed xuloda paafn jkyuidy jsa __lmqq_ehex_disenu vokuge, bzi zaf NTFY tapqicf sahx fo ejeequdka uctireusubj pa que.
Qwl oz uuf diq:
(lldb) yay
Ar elugpqpoxl topf nicw rau’ls noa dtu xunhipivh aeqdel:
hello world!
Ikodibe! Gea jih tobe u baiqyujiir dej keahgaxh xihi biws dovjzaz dcwolcp uvdi BVFP. Ac sgo xapyudacp dxagzobj, vuo’vn oxjjojo ciqi og yof ca iji vhan opjbuwohtw kiluvgar qeak.
Def lih, nmizo iqc rmuso Fahyebof nalr odl jita zaidsolk e rod al zro kiwh.
Where to go from here?
If you don’t feel comfortable with Python, now is the time to start brushing up on it. If you have past development experience, you’ll find Python to be a fun and friendly language to learn. It’s a great language for quickly building other tools to help with everyday programming tasks.
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.