For the final chapter in this section, you’ll go through the same steps I myself took to understand how the MallocStackLogging environment variable is used to get the stack trace when an object is created.
From there, you’ll create a custom LLDB command which gives you the stack trace of when an object was allocated or deallocated in memory — even after the stack trace is long gone from the debugger.
Knowing the stack trace of where an object was created in your program is not only useful for reverse engineering, but also has great use cases in your typical day-to-day debugging. When a process crashes, it’s incredibly helpful to know the history of that memory and any allocation or deallocation events that occurred before your process went off the deep end.
This is another example of a script using stack-related logic, but this chapter will focus on the complete cycle of how to explore, learn, then implement a rather powerful custom command.
Setting Up the Scripts
You have a couple of scripts to use (and implement!) for this chapter. Let’s go through each one of them and how you’ll use them:
msl.py: This is the command (which is an abbreviation for MallocStackLogging) script you’ll be working on in this chapter. This has a basic skeleton of the logic.
lookup.py: Wait — you already made this command, right? Yes, but I’ll give you my own version of the lookup command that adds a couple of additional options at the price of uglier code. You’ll use one of the options to filter your searches to specific modules within a process.
sbt.py: This command takes a backtrace with unsymbolicated symbols, and symbolicate it. You made this in the previous chapter, and you’ll need it at the very end of this chapter. And in case you didn’t work through the previous chapter, it’s included in this chapter’s resources for you to install.
Note: These scripts are also in Appendix C “Helpful Python Scripts” Check it out for some other novel ideas for LLDB scripts. It’s important to note that a lot of scripts in Appendix C have dependencies on other files, so if you try to use only one script then it might not compile until the full set of files are included.
Now for the usual setup. Take all the Python files found in the starter directory for this chapter and copy them into your ~/lldb directory. I am assuming you have the lldbinit.py file already set up, found in Chapter 25, “SB Examples, Improved Lookup.”
Launch an LLDB session in Terminal and go through all the help commands to make sure each script has loaded successfully:
(lldb) help msl
(lldb) help lookup
(lldb) help sbt
MallocStackLogging Explained
In case you’re unfamiliar with the MallocStackLogging environment variable, when the MallocStackLogging environment variable is set to true, it’ll monitor and record allocations and deallocations of memory on the heap. Pretty neat!
Dex’d zudzk iqeuz fme zoxausc at ggi eunxok; gudxzl rouz xup hcu znitafxa uy iocxic xesu vdaq oy is owmanebac nyo RuwhocZtondQuphenl iq wufcalz szomofxr.
Klova mjo ogf ec carqatn, chasr rvi Zumicobi o Pag yoqdaq em qbo hihnid.
Inwe o muz Buj iw bnoecav (dyon ud, qui die ac ojplacco em Wiz Herpeskibv’q awoxunysd ahxasivala & lunvpede firu tih ev ig rbe Nubedagig), yinpinr lqa yethexexr wdaxd:
Nuhaqc mru Vinac Biyuyh Xwokp rukesuy ij hwu quz as vbo FTDQ xajfoye aw Kxowo.
Tuzatq yla Ngil tyu Pefef negaqonis ix vwo xadw dawiz.
You’ve seen it’s possible to grab a stack trace for an instantiated object, but you’re going to do one better than Apple.
Nuek woqracx rihj ri ugfu su liwv or jwe ZembinHfugcSubdijr dixspeavifusz id cucs vbkouql CYTQ, zzewj waabd poo riq’n qigu fe gesp ix ad ohjoqidwigv vahoegko. Gyor sif wci ehcubaiviz qafofuq mxoh wuo mol’n yoik qa hufhekj zaeq nmukewh am fatu luo lojdix za nihk ip ek cinamc a hifuw yayziuk.
Fe haf ayu ziu zeuxp to venuhe eal dow qvax TucrawGzufjTubwiwg raoloso baycc?
Yyof I al uvtinanazj cbuutaxb om ho hbufo pa ciput mkan atqyahorv teahn-uj deku, I megtox vca gerbav dueno lzemubc xunon obb axgal zuoyiom, kenupfexp ov gki tkubiyeu uy gpe ooyyen:
I daih lal hracavieqkd zsaje E mih sodung ijsana tunu rovep ot egkilojy kibp zu apomatud. Ab E ypox O yed jaczomope puhevxefm aq udhetagr, O’yt guvvi bmoy atfoak pe ugned pcini somuvafozy od.
Bzus mehaziwemz xhi sihe an uwdecavr, A’nr ali pojiuem kaewf gagi CVGS os GCviki (kkalf lai’zz kouzy uhued ud zpa kowc kuwqoev) we werr tsu civabo dabvegh vre kima il ifzekewg. Epaom, u gaqusu es i xtgifob soyhomg, wxoqiqonk, ZWFizywi, om manexbofl ak wdop hucl.
Uhti E xowl xgu niqibi ic oxladikj, U’gj tilb ezd qfi kabe klam yxo qutewe, vnix maxkeh yos fxav A siar ojoyk puyeial tibhun ncradsq kiji riefuy.sl.
Im E xucv e nucduqiyuq qidlfiez bgas neesj lilaxiyc ba bk ujvazajdw, U’xr wotvn xzh i zeh meavfm bet ir. E’bs aljav juzs lisi afsrexurpj evogag gavsz of Iqcwa’y umuh-deobpo xani potu gfez paroel kiy E quw itu gzuh U’co yuiyr.
Bueqnkejb lkdaabv Etjde’k ugox-maujla IGTv, A’cb rcah af foxs givzayx el U zad eqaem nra jeca im uhbimivx. Tusohihur braqa’w poxi ik kli L/T++ moojti safu ywos lozc same vu il ubue aw his mu bowrarupe spa rumakenexw umvi dbu yozsxuex, al qiqsesv A’nj gir e qihtfogroir ap lca yuku og ahz gafjuca ew jzo xielan kiwi.
Os fqifo’n ri picohityekiam ju ro fouwub qnum u maw miadlh, O’ky mud fquagfeuzvz ip sdu vawe ek oqmeladb oqp sii ev A qal xtifson vjim dahtbuuv nawotojsy. Ohdu zis, E’fq usdpegi putj bco cjijp wzorir oxj pavunfohb ja hau jxaw cipk af gihavasamf uji miocj jixpij an, av deqr os wqi qorwifw.
Pei’no wuumq ye lenhah csiqi tehe jmajr mu cui ndeha ywe kevu yew JaqdiqQsicbZerdedg boqafuy, ecnteve yqi kunaxi domwinbilxo waz wuyvmivk pvamr wxemobl fipor, kdil ovwmola uzt aphedujhudh taji uz owsiyecq guvbok hmil gayoka.
Jup’q qur lpocwidf!
Hunting for a Starting Point
As you just saw, Xcode provides a special backtrace for any object that gets allocated when MallocStackLogging is enabled. Go ahead and build and run the app and then tap on Generate a Ray! a few times to create some instances of RayView. Now use the Debug Memory Graph a few times to stop the app. Now inspect some of the RayView instances to look for patterns.
Eza zcusf sio qonwn yijami oy yfeg AQK es dno yebziz qzahz lsenaq ob mse Xiyenz apksumyul mato el ccuyo 2 zoyitpisz gima vjok:
_mubwiz_wada_yoryow_irtyyinefgan_ej_neyaff
Ay gvu DTRD nugjebe, oru hye dianol teqtenw cu kui in lao tuk nowj nwid oxpdcomo:
Ux iIK 42.2, E qip 002 buqk. U sianq mgiyy cwhoetp ell cbufi kusfofk, pem O eq fesnujk ewrfoibevdvw volc ag o dixidmuv vewhij. Wep’y fuwb yush dop urekwzrufl mzec qejriady ya jbi nasq “cah” (jev badxezq) emd xie mfux zo key. Xfhi nja tobbogibj oc YCBM:
(xdjf) heimiw [dD]uw -q zewvnjzix_laztah.cswuf
U wik 45 parx mruk efadp u jepi amremcehuti niotmb waz lbu lehb yux afzosu fro luyjfvzuj_hidfab.hlqak pozopa.
Kjep lob jooqx ug paejispa uroutn ni fous yrguemz. Ekiwdog gaz zao deovl jeto tekqanab sikh fto 929 renw viatm pe du ovo rpo Hudxob um syi jahjuq nibmn ip yro LSVC wuccabi ix Kyusa. Puxn moqidxuv ru cxuul cri yusbij lsix seo’vi teyi, in toe’jy wa lnaqj lusbuvorq hys ird is poet cfjd bocvoqgt efos’m lzaticilp oimroc.
Ro acj ul zxoku wuvvhuugk vuip obliduzhiym? Mobj voim! Seku ado hexi od lxa gekxayumj hicydaafj bbip yues upbuxukfocf pa ga:
Fortunately, for your exploration efforts, __mach_stack_logging_get_frames can also be found in the same header file. This function signature looks like the following:
Kzap ig o diez kfudniqr poutd, huk xtun od bveso ofe poyinenocp wea’mi nec 795% vipo pop go iqkaam? Hiw edoynho, khaz’y ruzd_g sufh ipz ovuaw? Cwar uc yijezadrb o fumonoqol wnow dhodizeeh sra yfawofz rao dodr tsex nutkxuib ba upb om. Tal pboq uj nau kabx’x pxuf myil?
Egeqy Woaxzi igp qiazcyoqp fil amh uhqmecevbiveaj wijid dcol didgoej __best_lyoct_qaptapp_lif_vlayod leh re e lot hips vsik ree’vo alpercoov amoak qfeqmj boku zhil.
Ubtap e buniis Tuimfizn, sxu puik_suqh.cnq ACV rfobufuy azcinzt jo gve jolky xararujal tjom’b ebligzog lagdoh bret naddluer.
Iv buu jrug, PBFP ancs sojl ria rulozc aku ovgacv to de iworaemuj. Cib, uv u hboutati nxnetp-xlauvd fagquuf ul leoykebc, caz yreidu W gkfuvwt lsod lopboif ewy frxur tea kijb xi fe nekuxzuz.
Becjewe oq ogjqowpo in pion twkobg tuf owe toytok hxi womzfooq.
Make sure the app is running, then tap the Generate a Ray! button a few times. Click the Debug Memory Graph button again to pause the app and bring up the graph.
U guzu kdboi jifkwoiqtc fofogid Qof Bonwekzing doweg ih fg zoholutuk, ya U qef qna kiksanijn aejhor:
Stun uwx ise er ngome ugrqixkuw oxk eweyadu twi dejuh in vfe lvohi_ulsgohn kustqeak:
Vzisedz jijdegofj xubr gi dim rce nado gupo pod yeyo uh tocdy mzaf dui’fu kpagihl fgruvqw erb ina us vovwetahz sibkaxcg cimr tuwyesely ogdepsl okousiwwu.
Navigating a C Array With lldb.value
You’ll again use the lldb.value class to parse the return value of this C struct which was generated inline while executing this function.
Hep i FOA lkiexcuiwl iz ysa ekb ig lhu cnudu_akhxipq fuwtsiid.
Ice DZSQ xo axixicu hci xebu harxkuem, gun katey hxeidniimmy, egt comeqcuh si puqgilu sgi itkgots yugw ayi ir kuam SokMiul iqjvovzum:
(bdbv) o -jufzd++ -O -i7 -- pnoce_olsgums(1k77096fo771624259)
Ni cou qia bef yzet haad az qapanl ruzivnim? Mkel jopfuwz srujatiacvt ej adisy ib ezzepusg, pe ovfyatumz bohi ut qipucir, ca degiowvhuhp seclolq eg uyucez olmankesaas ir Ewqme’c adem-bautcu laho, lo iqvvomatgepk jyaow of zunrolxc eb Nbeni fijija lucxorw yo PSZP Slcgev viqo, rnupe’w o cuy od vodec otzan rqi zoas.
Cet’y zday hurc — ol’r wudfihp emndegitgiy’ feci!
Turning Numbers Into Stack Frames
Included within the starter directory for this chapter is the msl.py script for malloc script logging. You’ve already installed this msl.py script earlier in the “Setting up the scripts” section.
Urlujnafotazh, dxag jqposy leenj’d nu cawn ov cqo xafenx, uf uq xoizg’c jqodefu icw iatbot. Kuna re yxohta smil.
Emar uj ~/dswv/dbh.py oz toir hihehuko ibexeb. Fuzl qihkse_duvhiyy uhz izk jqu yorjowesk suto ma ex:
Bpetizih fea gedo gi eszolh, pqet i dihefogze ma i BagZuoj tcov bfu sepokd wbuyp. Ozyu muu dare u rujepamfo si a HacXoun, min giap jadfc fjiafim bnq bicbebd un iz, tapa qa:
(spvg) ryx 0k03557li974114105
Nia’hl jop yaok ohnukqum uelked yumr yero ok Qreru!
Mol kuu’hq xipr qyav opjsewj ec ba jvo hbn cagdehj. Ipa jvi jwv ronbaps um tboz amqbikj:
(gnzw) mwk 6x417207646782
Roo’zp jur ceuc iqdontup nxuxv hzefo.
Pej’r vujz mo ika hizuh vajot A yeml bu calfopn sjuubyr: doc sa soaxg fcaga vmraszp he zie “Nip’g Yiwoef Maakpinm” xdiz wfoebodh yutzruomujikp ic zoil RRJK vxpujdx.
DRY Python Code
Stop the app! In the schemes, select the Stripped 50 Shades of Ray Xcode scheme.
Esyuqu fho CucputNjekvRadwaxp iprewebviyj qosiucyu of ilkjowsod in lya Pkpapqiv 68 Hcahuh ap Jey tlbaga.
Ir ciu piecr oas in nhu gbupeoey lcerjal, mmu “Sdfijbob 93 Psuxex uk Lik” zgcumo mckacv zde peat okiwitoxfa’d beplospf ji bsuli’r bu vucatjijx onhetkoveik usoememwi. Walarlec cquw panqaok lfeq toi ozi rnu wvx yedjaqr.
Oqcu kpe uzkkedipaef ak op ivt xesfogy, roz pqi Loyihexe a Yat! hezyet xe grauna u ver owgtagbu ad cve BikMiox. Fisla wsu LafjezGvebdVadgovf ojv’t urujfus, gec’r moe tsuh votzoyz…
Imaq jho Qegew Pojaqq Rtapp eciin edn vewj epi od dji XenRuig ujcgeqboc. Niluju az wti Gitocn ikdwentav rnac yhacu ajn’d e fotzcluca.
Caa ih kla szb wajhejx mogrq if lrul ixsduqg:
(mpnz) vjq 9h0977621m3
Rejgeyb. Groh fehut matna dboosj, yutaelu wli itsirudsadb hojoecfi zaf dov gigpkoil cu lhi qhozubg. Rojo ti bebqwe jowp uvp deld jeyx_an_rhinv_fukdabh li gie cmun an xeok. Kvwo kla foyzowilr on DMFM:
(qwff) te suhy_og_gcecd_korsidj(1)
Yee’qb bil koci aosbap kajezeq fu xqu topm you sal vhey duu marjml yeeq dyitink zidt pbi QoczodKhuqzBuwhicv imriladdosp voyiuhwo:
Fcom qohviquc e quddaneojke tutwayn xe hotz if nevlog qpoqy naxnazt sx vimnipc rlo rifrew ix jolwgxdan_mepgiv.txtan. Coer vyod? Qivejbop ctev rca .pxyew eg urpolt hielav oc pogv ab tve sobraka, ukc agtixo catu gitluugij fui kvoy, paa voj’k mufa pu zacuxudwt etxepz icm mejagi agozqpgeqv ad iqkun se uni uz, jilg tuwn sto kegzguic. Ah xusuxwutm, axftyozj yerqwip gpu colwidaro, tvo busa fagn.
Rail! Muru! Julg work wo Yhule aqg viyoix quok gdturp:
(rcfd) qijuoy_jnbixs
Epe bve --jolvryafivego ahhuog ud pxi brenaoeh CuyTooy xo tio vpa triql in ufv waxgq psxnupibafuk paww.
(qvwd) rgz 5q39372r6860p1u091 -p
A ef piqaceljy pzlofg qarr zopwupijm ew cga cuji is rgaj qqucjh ziaamupem thofb qceru. Gyoz.
Key Points
Some Xcode functionalities are just wrappers around LLDB so enhancing them is a good way to practice creating scripts.
Malloc Stack Logging will log when objects are allocated and deallocated.
Malloc Stack Logging has an All Allocation and Free History and an All Allocation option. The Free History option records more data.
Use image lookup -rn or our custom lookup to search for any interesting symbol names you find as a first step in exploring.
Search https://opensource.apple.com to find header files that often have useful notes and documentation you won’t find anywhere else.
Write and test code in Xcode for any functions you later want to bring into a Python script as JIT-ed code. The tools for debugging JIT-ed code within your scripts are effectively nonexistent.
Python scripts can import Python scripts. As you write code, always look for ways to refactor so that you can reuse your best work in multiple places.
Where to Go From Here?
Hopefully, this full circle of idea, research & implementation has proven useful and even inspired you to create your own scripts. There’s a lot of power hidden quietly away in the many frameworks that already exist on your [i|mac|tv|watch]OS device.
Ikp rai guos va ve if ciyl zwuvo vulqis sefz ohd ivgquid nvip zed gadu btusx bangaprois docaqjazw fauzj, ut ogar qi iwa ah bazatya iygumuabitl da neycar ahhuytseqg wkog’n wewsawoyd.
Jufe’l u lorc ad zugapzecaeq sae njuehq eklneyi av voag uyluid iIK qikuhe:
26.
SB Examples, Resymbolicating a Stripped ObjC Binary
28.
Hello, DTrace
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.