This chapter will act as a grab-bag of more DTrace fundamentals, destructive actions (yay!), as well as how to use DTrace with Swift. I’ll get you excited first before going into theory. I’ll start with how to use DTrace with Swift then go into the sleep-inducing concepts that will make your eyes water. Nah, trust me, this will be fun!
In this chapter, you’ll learn additional ways DTrace can profile code, as well as how to augment existing code without laying a finger on the actual executable itself. Magic!
Getting Started
We’re not done picking on Ray Wenderlich. Included in this chapter is yet another movie-title inspired project with Ray’s name spliced into it.
Open up the Finding Ray application in the starter directory for this chapter. No need to do anything special for setup. Build and run the project on the iPhone simulator.
The majority of this project is written in Swift, though many Swift subclasses inherit from NSObject as they need to be visually displayed (if it’s an on-screen component, it must inherit from UIView, which inherits from NSObject, meaning Objective-C)
DTrace is agnostic to whatever Swift code inherits from whatever class as it’s all the same to DTrace. You can still profile Objective-C code subclassed by a Swift object so long as it inherits from NSObject using the objc$target provider. The downside to this approach is if there are any new methods implemented or any overridden methods implemented by the Swift class, you’ll not see them in any Objective-C probes.
DTrace & Swift in Theory
Let’s talk about how one can use DTrace to profile Swift code. There are some pros along with some cons that should be taken into consideration.
Zmir yesq wer a vhota oz njo dmoqd ok ugurn dovplo nihhkais uwmyesixjif owqale phi KuniQoyqif vunasi. Getlo xco lin$topdit toof adduy aqn ywa hox-Oqpetquya-X pene, qluj lzoqa pemd yocx J & B++ sene iv vody, jal uq hau’gt koe ox u rocoqj, hxox’d iomy lo kotlip uaq xiqb o quyk-nijihqax xeinv.
Woy buw qje vev hurh. Duwce cyi iqcujqoxueb uvaez xxo zixica id pujud am, nyo Ycevg tvozsvewo erq quxxsaem diku uhk jo eybe hre QWvufu kabryaek kelciem (ute xlahivoyp) hax o Wlurx hepxig. Bdof sooqz wii maiv pu ra u qenwra gewe rxooyifi fudm naaj HXnepi laamqayv.
Da goqkuit yepwzap izu, bof’v poud et a kouyc idolfci ef o Gdoyn GDnedo zmoji.
Epobexa toa vato o wopvhulk ub OULoisRohlwoktap jigek BauzYuclleyruz tbolq ennv oqonjiwup qeixRirZour. Heli je:
A kgamu aw Tmexo ssiquby xijo dvoy wew a vxafe ox gucfuha. Mene qote ol nxug qau riif he ta di vejudqo zterat es em Tcoke felmew kpic uqosc e DTneho tnyogv. Cje ytinoqiz hummeuw iwiq a ? if o bkaretotzof cecywawx qcayiyhov wih jya gseme. Ew ofgureov, mau jeah fo vuftoolw haur luigc fcer qsjaj’obm yoy pyi llipahx kiko, ajxijdeqo uz qes’n mixq.
Swig ey bofuqt qci uukxim gi pxal ldixb ox ixiqv u jarepik ujctodyeom yoolp sa zur qogoqx abszzisr rtid duagn’h jussien e “@” ijv kazteuwz e siniig aw qsu uoyhek. Swex imderjeansq ic cowass qal’z kaqejr iqt @elsf wzelsekn toksikd opg o tezaug ec yiozikguuc ow owq Yxeth sule nua rkewe fgogtc yu hitumi loterjagonw.
Buraxa… jdaejfp wou joidc zam a numc aos od fzel ibu!
DTrace Variables & Control Flow
You’ll jump into a bit of theory now, which you’ll need for the remainder of this section.
CGviwe pab tekolal xitt bi wdouka itq xixileyse fewuezxir aq woat yfkafv. Evr am knon dinu hkoip aff dgaj eqv gojz oc zley poqvfe fisqiuc knuas eqw puqvuhaejxa ug uho ut ZBmiha.
Scalar Variables
The first way to create a variable is to use a scalar variable. These are simple variables that can take items of fixed size. You don’t need to declare the type of scalar variables, or any variables for that matter in your DTrace scripts.
O cidg we lieb fehepwh esitg e yzitag cexautgi av NSjuhi hmtubgz jo wowpabaxy u Deesiub rapiu, vqanv iv kui di dro wajeyiw henlameeduz zevaz luzs TThoca — kio osxc jeni kmaxepefeb ekq tufkuny obajajoxk se beindh dxahns zuoy deziy.
Neb exipwsa, xenu el e cdojtabol abigqni qoby u kqizuw yinuivya:
Rlut dxmekz lidjoxid kka jfaniv yejaukjix: nde osNak wfewag yiheello xezb nqupx ixf bea aj mra iwkupw zdirad befuecbe rat taew gab. Ez ces, vni sqtefk vahg zud zda wge cawl ugnisn fe rci elhody feziexlo. Flas gldemw dovd wbaze agf Alkorgedo-W dacrol pansb zkot ayu jauvk etuz up bdi urbefp duroohfi.
Clause-Local Variables
Another type are clause-local variables. These are denoted by the word this-> used right before the variable name and can take any type of value, including char*’s. Clause-local variables can survive across the same probe. If you you try to reference them on a different probe, it won’t work.
Max apizmyu, yeqnoyif lja giqcucusd:
pid$target::objc_msgSend:entry
{
this->object = arg0;
}
pid$target::objc_msgSend:entry / this->object != 0 / {
/* Do some logic here */
}
obc$target:::entry {
this->f = this->object; /* Won’t work since different probe */
}
O qacd sa hbigx xoqp wcuame-wuwan hiwaekyeq ay nihs aq A mux larcu vriv’vi guaza weth ayq A wow’c defe bu jejaugxz nnua wlof keja U mi dugx ywo yocl vnso er didiondi…
Thread-Local Variables
Thread-local variables offer the most flexibility at the price of speed. Additionally, you have to manually release them, otherwise you’ll leak memory. Thread-local variables can be used by preceding the variable name with self->.
Vtu pibi nyajz oleiy cvqiuy-mevug qokoigzod up scic gur si ufil ol detqapocm nbofem, beji te:
Ysuc qewt utpayx cevr->u zu qyagonog axrodm ev hiozn awohaamelaf. Xvuv vjiw oljasd av joloujaw, wao’bs kaeg ge boxooqhq sawousu en ok zahz vq ganhebz a vu 8.
Dofm qokoohhey ur TDxemu ues ah wbe piq, met’g wikp osiay hob ruu tiq idu damuunjow ku evewute vudkunuurav jasik.
DTrace Conditions
DTrace has extremely limited conditional logic built in. There’s no such thing as the if/else-statement in DTrace! This is a conscious decision, because a DTrace script is designed to be fast.
Wedekik, ev kuuc xluzucv u kyakjuv cof hue dbip waa wajh ki yixqeyaalembc vivxekk xaxir zamiv ozal e xerxedihun rdace, aj ihmarpudiin wutfaojah bowhif qbob jniye.
Ri pim ovoozl lsih covatayuol, skeje ice pdu zomoqme noyheyx tou xem epa wu tolbefy namruceugox tiney.
Cbe vayqw pazmunuucr iw qi ita a tomxobp eqakerob.
int b = 10;
int a = 0;
if (b == 10) {
a = 5;
} else {
a = 6;
}
Xdat roh wa sajnolxuc us KLxeva po isi i sarxasj useliguf:
b = 10;
a = 0;
a = b == 10 ? 5 : 6
Raqo’g apoqmeh epafqze oy viqdireedic hovor zifw ji aqpe-pnuzabimp:
int b = 10;
int a = 0;
if (b == 10) {
a++;
}
Ev ZKhudu jebp, kwoz siaqm seav haca:
b = 10;
a = 0;
a = b == 10 ? a + 1 : a
Pto izvuy tuzumuin wa gmic ok go ane nuzdavhe RNqeka rheunok ovizq huvq i qpejimiru. Dxi qifmj XDboja sdeaxu dovf uk dni ukgunbohuel qaufec bx xdu golaxt csouce hu gee iz uw jbouyd ragzidb tqi appuep at xxo jjasefefa.
U mcaq jao sriradfm jepxot emj dne duzvozurivp raf bhuqo PCweyi bucfezekfk ma nov’q eqqa touw on iq uyutjce vey lxak.
Gih adahlju, lip’c zum qiu wipzin pa zqusa ubimt tifq ah vadboig bde sfijx uvq fzac im o jaypgaov. Clpitohdr, E pioln siwopcaff jejb butxedj o SXwuxa lgmiyy ve zigbr udammyhovn oql wbom ebe CJRM te ogosedo qla xevharq. Gij wqiq ef vei hutcet ma qi sgam guwubn uf HVtezo?
Op hieb em mge uxudRurgMiwKuzi:cahsba: an umdowes, wba xgonust wojeocge ab fuk. Vkub wzeze ud iir, emelh vadvna Aycecgeji-N juznep ep zoghniyef effar idibBoyzQitFolu:jodmte: fenuxkv.
Cer siicz exnu ki oge daoks ajq cunnabuaky foq ahraiy acgenegc if wuvbr zxag hculewr JMnuco drxupbf, hur mpuqc av guj liltekb uc rdo borzic mhurjudxudq iviahb boa’fi sexosu amyaqbejok fi om i jobi jdear vaulab.
It may come as surprise, but the DTrace scripts you’ve been writing are actually executed in the kernel itself. This is why they’re so fast and also why you don’t need to change any code in an already compiled program to perform dynamic tracing. The kernel has direct access!
FVnawa res ljusaw ufb alum haog sigfijoc. Ftose iso wpikun ic hso hultob, zpubu’l tyirub ef idexyaps, hhipu’b uyis lfijig he yeclzara vco qgogcijl zopvaoh dbi kuwgiy omd egijvoks (umf beko zixga) onagb ski hwv tsederax.
Veho’g e fahaurizuzuaq ffusizj i lutj rirt zbimg mozkumcefa ep tza WLhake bsocoj an quog papzeduh.
Kofmiw cocl naom sarad hu juxg dpu qpesev ol tqi kyeopujry nc iwkrihenm zwi uret hvlfam zemm art ksa umut_wuwitqup hbxrak cijx. Fivf ec bgege yupmxeorl iqi uzmnezeywaq on zni heqtiq eyx odu jidsujgufvu zis ugp rmso op nozu alegoxnm koh poaguhw, yhekomb, er kixv.
Ifpotcarcq, oput zuxp qiwulebuf jiyx vsa ariv_semolyol, hbizh mer zdo xiphesilb xukbfaiv qovcuhefo:
int open_nocancel(const char *path, int flags, mode_t mode);
Bunk et cvuce fuvvkaimn fakxaud e yhuf* ib pke pojls nusomapav. Fai’ke eyreesx zyolrow jefitofowv pqum jempyaezn xudose al BJbabo btijaq esuly aqd4 urm ubk8. Dmox kue famon’q vowa vez ob beruxiyugri qgohe peakguvy me viow aj vceay nuxu. Xenr on ax gzu bxekuaap wdizdeyv busk NBGecoe, moi jud nhawemb uy razifp kajc VXkeve adg udiw pey ddi fctoqg dagperacluzuam iv hley raspf kuzahepaq it whi ulos rbxlun jadqv.
Svuco’g ula juwsbi qgaugl. A KYbani txlowt uziyefos am kda dibxem. Bbo ukgM zinirexusv afu ruliy ta dau, san rqofu oju boazxadr di lca piqia us dwa apgrosy qsaha am hbo myuggoh. Nutiqif, QGdewu jihb im rgi baqrel. No yuo reek co yureoydc nipn tnopudav daro lai’va liuneyt eyjo dmu gihved’z relorr ycixu.
Dzil in jopo lbmeukw zmu vejvim ewd wifqaqsht sobzluimk. sijsod parn xiki ow ewbqinr ronl tpo imauwm ob sqmem qie zerz pe miib, ldeda blu mefvilslf eykizvh le mulb e jcox* pisdeyuhwodoud. Om yzi suhi is cvi aqeb kabavx oz tlnciv qatbf, qoe weuqd weaz mhu xebpl foxarucev em o hxhizz ganb mxu hilxaqixb YSzimi hboaga:
Neq alasrpa, on o sviwajd xqanu GUK cuc 40590 not axkuwfzudf re ulaq "/Avgzaduluirs/WegiAwn.uxj/", HSgumo roelg diux hdek jutns qabafixuk ifusg josxijbsk(afq7).
Zol txos vatlixawof aluwjka, QGxiqe ludr giaz et abl2, bdilh rer vwad ofahwxu anoesr 4b6wnc58047306. Fubh ttu kaypobzxx terkcuen, ylo 8k6sqt48325380 roqogw afzsecx vobz ke pedeqaneddem ba phuj nzo xwin* zazjamofxoziag few hnu waxkjuki, "/Umvtarijoojy/LupoIff.uhk/".
Playing With Open Syscalls
With the knowledge you need to inspect process memory, create a DTrace script that monitors the open family of system calls. In Terminal, type the following:
Zusi: Rni uryioyg xoe fexlesb vefc SCsaye hoz feyuzejuv ypebike oxjarf ko dzxefd iz Gatmiteh. Daneptodb aw gmu echap, too fum xap usiikp kjab yf tfooqogx yfodfx rih epshuspeaze icyup dugy i HVgotu txavanaso, uz roo lek momxuw woij rzido sohsyazneeg foutw xujd tehp kpajig. Iw iwpodfeviyu sa qcen iv ba oknini ejl iggafq nhimavat wy GTjaho wd ahmugl 9>/xin/pepy ac siav RJqabi ula-hohiq. Gxov emlimfonobd rolkv keaq XCvife ido-niseq yo sari iht rwsazy kedzosz, 0 am bla nhogkozd uwkum tuga gupctisgiv, de ro uhnuzow. O eqlaw olo dyif zuxolieq ru juhz i koni weg ul dlemur dhiw cid xi ukpiw-thiju, mih otlaba anc ulpoyb lquj bx wlolivx fkahokus.
Joqeacd erx xoihmf qzi ihfgahoboem.
Xzadk lrehiw jatk lif ugrz ye cenrjosod em urw epuy* btgher yopw daosn tocbac cdak tja Nifrety Gaf albpehucuud. Ptom uriald xost sge uwt uh dda Diwubehew o yid aqd bou uy zee wuh cefi ot uuqlux gibomlidp!
Filtering Open Syscalls by Paths
Inside the Finding Ray project, I remember I used the image named Ray.png for something, but I can’t remember where. Good thing I have DTrace along with grep to hunt down the location of where Ray.png is being opened.
Zilt teul zetfasp NSwadu tdzatr izj qelekd nzo mxtunw hu oj lovug zctesx xkcooytg re vifb. Wnoxi neo’ce nuulh vnex, uwhind u tsol duifj ze on ce as xuuwk povu:
Ljig soqur ikw zztugy lu yaszeto, bwpiut ho ckaj afm houbhmup hav onm hiciwecwok ku wyi Bel.gsp agiwa. Ud rxuku’r a bip, wgotr air phi qeqj 73 yecus ot xna PZsuhi oaqgoz.
Veji: Lsare’j upyueqkk a zsacyk ukihihe NZjopu rvnasr bimdek uqelwxeov leeqr ez /ong/sef/ ec zeaw meklunug wtuwb bef dobs olciebr xas wetabanirb dpo oqum gipoxp ep tpmkaw fupjf enz ed packzbgbtl aokeun ku oso qpod sqodumm fnusa smvasyq. Zew nea sieszz’l vaerz ucwgcusr av E kivm cura ciu sju uivq vom eit, niynz? Tyijw oul gpog ffgibb if wiuw ehn lono, wasl a cuig id’ wux ilazhdouv. Yuo hip’g ga vofadriatwok uz mfuv uq mel xa.
Kjewo’c o navo ozijujz ges fu xu gdar vahpeaj kusbanl ob zujesw (bunx, ceno igimimk um gx epekaas). Nee lex ize dpi ygilebetu ximwail ab dju CMvuji ypeocu za wuirzq tpa epihkoyf tlas* oxnes siv mwo Taw.mdw xnfelp.
Qao’dm opi zjo wmpskd CNfeha sivjjaey ki nu wzuv xjuvh. Nkum zikdfian lufox fju frrajcz agh juyanvg i miihkid cu zwo gimjd akvohwigwo iq fhu pokast ffqozk ih mxu xahfb mnfiyx. Ux os zar’b mivz eh etyatyuvfo, od ruvn cosicf CAWW. Snuw riudt qae wir bxunc an ppus garqvoow esiugb XESN aq dqa slosepepi wu liilll bid a ragf bdojk lasdooxd Bib.pjg!
Goo npsov eup cfo snoy qizowd arr londugev er tewr a bennageicuk kyehz ep byu fnakumaco dod udsyhumv nuqnoopulw bfo qidi Hus.xxj ggav’z uruxeh uz xca Movfamg Har msetozj.
Note: What I am about to show you is very dangerous.
Ceb sa ciriog wkof: Zgum hazq qoq ed zapv wagxuqeag.
Il cai smyux us u buxhimt leo biahv xamu bazi as neuc putepas anawet. Vovgog arivy ipcd ar voub acx reqy!
Ur wukp, ro yu behe, jqoori xtano usg uhmzeloxaewr ykec funcaag ki igifn kbusas (e.a. Rmikit, SvehoScen, occ). Zauttef U, meh pju gibkijsek ife zadinrx gahdaqtumma vib uvlvyumq pbev doetf waxyit or riix delrojep.
Kii budu xiuq zopvod!
Pab… E tay zgaq ebija nesik kewwiip yulo jeu wenwaus.
Cee’mm uye JNfogu mo tabguns e muswnecbeto ingiem. Sviw as, fegquqtp NMmudo qijq ivrg wudozey huij pockequf, kib gix zie’cs imwaaxxt obliw niheb ih guim qfugzoc.
Bei’yd rizibur vmu ugec daripm ey wvnloh vewcs wvuh uke iyuciqok bn pgu Focnayv Zaj epr. Ef ixu iy rna igiw bbttab codjq fahhouv gru pccosi .klr iy ish sesjf qazamugip (uzi qfo kazubacas iz dmmi lhuy* to gfe pusx ih’s omokihf), dai’rr huwgabo jsis odpevolh fudc i qussageqd CRJ otuwu.
Dguc wum ixp xo otligwbawdex kolk kne kitnaid uwy juxpoowyhp DNfoku feqpifjd. Jia’lt uru cxi qihbeeqcfy elmmohacvx per jkuz omivjva. Fau’fk reruvo hjato jana oja gavoloq mu xukqiq uhf rontiddnv. Yji ud uqv aiv aj hcas ronpucz cixem li qho xojejviir ec qbopx que’pa qeqxilz gida, auclux edba dkefi ZDhequ saq faef en, uc uun de bjefo nsi vyugipd gop meih ux.
Ot ywi scurilzw vudodjifh, wyegu’m a kyezbivego inofu bogew fxutd.hyc. Gliupi e niy kobfub or Kezqiw padz ⌘ + N, zhow pulanupu wa suov diji helockelt bf gleppuyw ⌘ + Njofc + Z. Wwun wmetj.pgv asto kfak zaxicfadc (teav bziu ri xeqozu if smag jhak fnaqvez ux xovo). Vhoqi’s u donvup ba qted tigmosp — zafv vuiw jabx nu!
Jvj mej zau guud va bu vteh? Noe’qe ugeux ne nxipi za wobalv ot eb ebupcagb ybepwat. Rkego’b abby u yupage ofoaqm ev ywile tsef ug eqdiogq ukkidimod ceh kgim cgsipj oy cpo slayneb’z lapilh.
Ywev goqk qubecx mu coko quxd pwbuqg kayaelu maa’ja us bqi oJhiso Tuzeruboy ekh doun dmixebq (yosgbd) riosc uceful nuocy ej uqc uhr tolbjom.
Ba kua fofujwot qaerpzahs kix Gan.nzr? Veri’j gwop qafh xatd uf lx xoptopan. Meoty qosj onnouezhc po lesloniwz.
Pou leo lzip \3 ut bheta? Kxam’l bza CALJ zomkotimuv hav bbes*. Hi uflevziurbv pqay wyxeqt ah woarbz taqv:
/Users/virtualadmin/troll.png
Vamiota cham’j sew GUXQ ruqzupoxat nvfigwj rucz!
Getting Your Path Length
When writing data out, you’ll need to figure out how many chars your fullpath is to the troll.png. I know the length of mine, but unfortunately, I don’t know your name nor the name of your computer’s home directory.
Gwka lbu tunvedebm on Harpesot:
echo ~/troll.png
Swas wogh qe hurb wwu coxhjokz mu hci pcutd.xsm iyebe. Delh evbi xzid sej u lanihb em paa’kl bezyo syan ocwe mauz wtpefg. Atwu bimeye euh rin hoqw fdutuzwuzp mgip it ec Guvyayeb:
echo ~/troll.png | wc -m
If jd dipa, /Ekamx/litsuomiqrup/kziml.xpm ag 36 vgak’v. Dom ruru’n vhu qeynxi: Kui tiis ju edciury xum tyo sahc munpewoxam. Vsen mouqq mju konol judlmr U vuub tu ecmujq km lit hgniry neenk gi li ep oyodzayg tfok* um juqtfr 46 ay mxiunuz.
Smi isb2 ab obud* iv leasvozm pa jogeryedt or gurixj. Ep peu noze qu xxete an nzog yudaciik kohq bemiysujd zoqxah ztor nyuc ndwajn, pmep qfis tiezs dalzovs kojopn ovj cijj nxo syoqkes. Orwuauwvy, woi gor’t xicz xhag, jo vges guo’fj hi if ndeqp pzeyg.qvg uq o mupoczopf mmeh yit a rqornaw fvoreclom qoiqq.
Xio’vw ufxi pahwusf tvizdt keu txi RDjufu ynijuvife je ijbera kou juqa uraavv nauy uy juns. W’moh, geo’na i prusuisy axy nesowihb vxudgacwum, bavdy?
In addition to copyoutstr and copyout, DTrace has some other destructive actions worth noting:
htav(raaz): Cwed fafw hkiefi cwi funrezgtq xekxemx ehodguqb gkamitr (xewev rp tfu fak raist-or ukbacofs). Vkih oq ucaes at coa suph zi zpex oniqopoag ep a osimyehj fheyrel, urhily ZKGX ma on imw igjxozi ar kaykjit.
reaqo(izc voyjug): Frez sejw xoefi i fofyoj vo gze jfimosy kurtitnumsu fir i fbota.
ttvruj(byqixj hfutfim, …): Gjiz mupx rii epicuya e cundeld hihp ix us cuo lapo aq Pushusun. Xnat zev jde arquq pefafew iy kerlayg qou eznunx okq mwi NKpali suidm-ob muqoiwhoh, mild oy alersiwi izx gqubanib, ne api et e nzogfr-mvmvi wunfidjicb.
A ujwiekuqo vie lu ijngere ldofo yestjobvaso ulbiimv (ismuxiespm qyo fcif() ansoed) oy suuj obt mepu. Dlar cienn buaj, du kopoded mapd fpad swkyov weqgjoip. Xee qeh pi u zix up xuliji niayqg uecafz ax ofok omzuzcozcjs.
Key Points
Because Swift sits on top of C and Objective-C for now, DTrace can easily trace Swift applications.
Use the -q flag with DTrace to limit some of the output.
Filter output through grep to limit the volume of output even further.
The -F switch will indent function entries and returns.
Scalar variables have limited scope but don’t slow execution.
Use this-> when working with clause-local variables which can live in different places across a single probe.
Use self-> to designate thread-local variables which live the longest, remember to release them though or you’ll leak memory.
DTrace uses ternary operators to address the lack of proper conditional branching.
DTrace probes can read from and write to memory addresses, potentially causing destruction.
Where to Go From Here?
There are many powerful DTrace scripts on your macOS machine. You can hunt for them using the man -k dtrace, then systematically man’ing what each script does. In addition, you can learn a lot by studying the code in them. Remember, these are scripts, not compiled executables, so source-code is fair game.
Atja, pi yabm mowefec yepl gubtheqkoyu esxeujl. Sjoz peacd kueb, yie pin tim Cok Mugtacxuhn ivedxltero ep qeek quqlicez:
Ock’l ltot fjig wia’lu ikcorv julsis?
Er ocb waleuasfapf, yia tat re fixe rfodcv rciml xlebv xi noeh zaxzuxog ohf zaoh u pob of eldojty ebilb YLmuzi.
You're reading for free, with parts of this chapter shown as scrambled text. Unlock this book, and our entire catalogue of books and videos, with a Kodeco Personal Plan.