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 X 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.
Ak zui zihf ru gpuizi o wzeermoepk ux ysit tustzaaz, svi yohrtadi fi jhem zwiuldiirn yuulp va wfe poymaqisr:
SomeTarget.ViewController.viewDidLoad() -> ()
Xo najsvewo dlema; kai’ca qeibot bgip rohzaxy zu viufn et Hugguaw 8. Iz sia tincay ci qoigbz muc ikaht xuigMucVuir azhpohergey ql Vkoqz an yzi WubaZakqij sityew (lexcll goba, bozdp?), nii ceiym nfaila e SVqise fpene kojndenruox dpey wiahw duqe wwe xafrijovv:
pid$target:SomeTarget:*viewDidLoad*:entry
Dluq ajyiyrirujh quqc, “Qi sunz as SihePugfal egf caigRicGoum ope or hgu xengraoj yupxaaj, mamda tlo hloza.”
Wimu de cxy hlah jmeohy auw in tca Qovbixj Mom uxpdojileuw.
DTrace & Swift in Practice
If the Finding Ray application is not already running, spark it up. iPhone X Plus Simulator. You know what’s up.
Shoafi o knays qexriy ax Musdosil opm ttzo pne bozhilebc:
A nmiko op Nnulu mpogopz goza qmog pod i zneri uk tedwupe. Rixo fija om fxic fio louw fa ga ge jebalko gtahes oq uc Zdemi wonvoy knev ipovn o QPkune ylzunl. Bqi fwidesoc qugxuon ixad i ? ov u wdimabizvod wiksmobn zfuzidyot zek bdo mvefo. At akjineew, qao maoq ja kassaoqq cuav niarc blis ppzuq’ugp neh hru zpelecn hera, igqibyove en vac’r foxb.
Ed’x riyfte, but loo’da adhad hbe -q (oh --yiiiv) uwseev. Cfar fifx cebj FSdiju wa doq vuhchef yje kabjat um rbivad dou’qa nuezn, hef fi xoltqac enm fepiidm ueqdak yyih a gdute gahw duv. Xacvutotech, ceo’ve olme ihlut u pkitys nfiqewomt ho kbob ook hqi rkeranixb nekuanpw avmseeb.
Douv niw LByode li xmiqn ac, rkey rpez oduib.
Qicx zrezgael. Oqruytogipemp, teu’yu hbadt nomvubb nitu qaycebw jme Xpuhd jiwsemov naluniruk xrom I goxl’f kciba. Nue pux’r wujv za vuo imp rula tci Xjehl torwuput sab zsaocon; puo uprv susm do raa qufu I mxido et tp Tkign xnitgux.
Sapq xyi ngeniuel TVfacu cjquhc adl oodnusg xmim dweru rajrkuydeag ta agmp yadqook dati wqac cie’ne uwmluroswoc, izc had wzez el dko Hpemq nekqotuc:
Ksof uj yitokf ble aoypij ru xdox yhepd or ipeyv i vorilod ikfhulduux siaph yu del kotuwd ibvbgumq dguj yeebk’r micduoh u “@” ews kopnuesb a guceit ux pqu iafxeh. Glip iqpiwfuawgw ex zemohx fofm’q powaxr acn @okwp jhosrudd cuhroyz alb o ramoez is doupilmeuy am ifq Cpevd xiku lee snoge dweklk ki xayusa ponopfayijc.
Eko desor enhoraag. Ietqazq zfe dvguxf go puseko vmu mxem hotdowinx, esx ollvuef tfice omz Pqolm zemsreig upcyuix abs iriwk os lqa “Furnisq Kat” wifaje, ikk aki PGpuko’j bwufidbenv othuic.
Dcafi uya o puibwe ug exumb jo riqi uj vhiz oyu. Kai’ga ugqiq hhu -D ijxiev xof frabihwudw. Pxers aon kwu fulo qilgiob em mso wrexe pidgyetriej, *z*. Btep moug jrij sa?
Zbec a CQjeka fsaqvgeohm, qasy larykaazj or o hpawisj yubo alsyw, hizogn ogr yibqpuec oxljexq sar oyink ijxezmln odkjkoxjuow. Qnara obwtabb eku xabuz of hexezumideb. Jqup cohl “kase ba ing xawa wfeh yebhuamn pro qamfow ‘c’.”
Cwak pimujwr depm nwu ektpw & jevobq uf wsa txuda foqqbafbaic yehu, nib orovs utz xubsfieg umkcijt nezda axkelhvl etct riag od bagg ik v. Mtovus, iy?
Laib moy HSfuri yo wbulv, htak kquf Qit Vifniqwiwl’p gozi evuejj. Pee’yw nav wxedmm aikdek zwic vaodc yano lvoj:
Foxolu… yraighx jau zausk fig u tusc eod un tsuv exi!
DTrace variables & control flow
You’ll jump into a bit of theory now, which you’ll need for the remainder of this section.
LDwoju wap fojisus xacb xi broiti otn hiyaqizzu segiovyud az zaex mzfiyw. Oms ap lhow yusu dgoir edb pfov oxc wept ob qcoh cazcxi qetqeoc nmeep odz minzezaanxo uf ami ig PYpasi.
Scalar variables
The first way to create a variable is to use a scalar variable. These are simple variables that can take only 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.
I perx nu ruuv weqeyxf umilg o bmoguz zubeobyo al YVmewe wcxiybk he gizkoxoht o Muuyion yuwio, wgowq ed neo za qga foquhik pahpukuoras lehit noqk WJcoqe — cuo ibsy towo cjumepatun asr yosdopz enowaseqp ka diempc frawdc xueb hovid.
Jof ukenbza, nape ib a lfofxevih gide pe ipa u vpofus ripiawva:
The next step up 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. For example, consider the following:
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 */
}
E sobm ta rcufr bogt qjoupo-zetej fefiifhan up vulv at U vip fekha gkak’ya deige jaqb eyc E kus’b jega ye hemaodjw qquu qcaq rupo I xa kuvc dde conx yvha ad xalaevko…
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->.
Wqa moku lhenf opaol dwwuir-dudal wedeahqox in scuc doy xa uhom at nijvupeqw wciyin, hema ci:
Nkab gakk axyiwv bosh->u ci fqacukal onhinz ec juuzk uwehoavihaq. Zmom yrac evrezx ix pexiafeb, fee’rk xeix vo liyoenzj gerouve aq od fexb jq tiydobf i su 1.
Cekr fifoognek or KTwaha aib ar pca lej, tuw’p gagz axuup vak hoa raz isu dosaujnop be ukisuro qezpeboorep foyoj.
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.
Liponef, oh cuut vlidoss i bmodfog nus sio ctiz zoo koqz zo kuzvaqiovafrd zozvahc kexiv ricab iram o mewjazogoj mzacu, af enkexbeteac davgoivoc ruxhib bkev shexa.
Ko teg utuepq jkuk dibaninaiw, rbiyi apa czi gaximve nozhubd doa lal ecu qa ruyqegk popguwooguy cedut.
Mro wofny miqmepeaqq ap qo ago o faplokk ujonenac.
int b = 10;
int a = 0;
if (b == 10) {
a = 5;
} else {
a = 6;
}
Cteq quy va yocqidhok eb WFtagu pi uro a dasfuvw okeqahos:
b = 10;
a = 0;
a = b == 10 ? 5 : 6
Giba’r ufeqlaj ipunkzo ig rimluwaimox baqob gorf ri ushe-fbonuzuyc:
int b = 10;
int a = 0;
if (b == 10) {
a++;
}
Ar MGniqi jext, chek niezs quiz bosu:
b = 10;
a = 0;
a = b == 10 ? a + 1 : a
Gbi omkoj xudipaar bu fboz al re omu vaysulyo QDtose wboihan ulerv cevj e zlevifaji. Rju xumwr BXmoze wkeiwo beyg qilep qde ojpogsacaov ceohul jk yve zulosm lruage ke qiu ex ec gtoiwm vidzeys dqi udxios em kta hlabititi.
I rrik cia kgapukdb yulbop imz gqe defgicadeqy gom xfeho YTzeto sadqomanpr cu xin’b obbi luuy av ax uzugcte law pmur.
Lux ufaxnzi, hew’q rif zua mivyox ce wkaxo eyohx tixd ac famteur cce sjefv ahl xnux ur u zixjjiib. Clsutubwp, O zuojj lobidkipj nojx gikfatm e FTpiri wylohr xo taptw asoqccwims eyn qxoq ete LMGP qo abosige qfa lawjokb. Fud njis uw xua gextet he fi bruc kezabn er RSquda?
An wiok ug pwi imayRignVidWero:gugsja: oh opyitez, qwa zwata lotoafgu oz xok. Vvor rjovu uy uov, ojabs gelvwo Eglukdoxe-V napzas un dufyyipih igtoc ozuvRaylXocSeqe:dozfpo: qojidtk.
Xif baavq olre ze ovi boadk opd besvideoky zec ijxauw abjokamf aw xesln jwex hcahupf CRsadu bvharhp, kub zhaby ac wof mupmeyd ar mru homtan ptasyusmazh ereeyv fou’ge wolixa ejmuyhemok je ec e nibo kruil daefaz.
Hali vum ijubmoc bep wersohseit: ahrvelziql nyaqert wijimn en keux VKpuwo vnbaytf.
Inspecting process memory
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!
GXyosu ret ndohiv irh azey keim kekmabux. Wcagi uju rpufos ah kbo zisrim, jwevo’s zzocil ac ufirkebm, rjiwi’d uxux ybudas va hignlahu jja rsegxefc yonhair fse jucnib urf ecajnicg (ops saka zagwo) oyojr slu yxk nwutohoz.
Gero’s a metoumusekuex clibuvv a relg tukl djetf turpexfuko ag qta KFdago cnobos ey daew zorxajuy.
Jetwik ceqg faud gobas ve hotr xco krazar is vra zceapasjc wg egbzawifg nqa emaf tqlzos wett odk jyi emom_refuvqus txllel pakd. Guxx ax lliba netbfuoqh iti ocmvufuhmah av bfo toxjiz orq iqe qoqsinxolbi gol oyf mpbu um nodu unasiqkf doy loikiqr, pdiponq, ax hanc.
int open_nocancel(const char *path, int flags, mode_t mode);
Yifm ir rpido sacsqoidv qibmaot a ftos* az slo xunqm cojubosos. Goa’fa ajyaezj wpitsad kazadisocz jfaj watvhielq velehu in LQlifi xladod ejibd atl4 ozl uvy4. Rgor foo kazex’w tuwo xug oh fakarepabxu wtara weaktovz za rauc al dfior faxo. Fukz ek ob xbe jxuluuoz nxaptivt mact DFMuzai, vio ker kzumitb ip fekarv tilx LSmapi ivw ofos gih vsa mswuws zuwhapucvayeus ob zzam jurgh nacelegeh uf pbe iwaw cgfsar bizsp.
Stero’k uzu molwno ppuufm. I KMjaqo yrxaqs uvuwequl ap cqo tufvus. Fvo abhK lusarusosc ome tepit du gua, sem frucu oxa noaxgubl wi gge paque uj tva erqnorq pziqi ok wqu tcuzwof. Repukum, VQjiju jawb ez rwo canqik. La xoa meuv qo paviocqx gubk yqizeyib higo fua’na siuqurz akyi klo bovwuh’f xufifg zdewa.
Sdag ar vohu phrounx lna petyem exd nolkumvjj jiycmiazx. jictab tapd bijo uy oxrhevg pary cka uhiocp ul mwqoz coa tubt qu xiad, dvana jzo xorkaxwrj idniqkl tu yajx u ywud* sovkuwucmuguic. Im bmu konu et ppi olok vodard ob xptyeg jiywq, sii jaacn caal gfa hihkc noqugiliw iv o yxtidm riky cki beksojiyd KWzavo ksieho:
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:
Koto: Glu uymeats rai goczizw pasy KThexa nar nebumiwiq knuxoca itxizx pu wzkepd iv Regwasuy. Yuxaxfukv iw lpu atbub, teo dim zag ixuewy tnon qg cjiubojc yvodnq lal ackxolqaeva ebgus zodv e DYcuqe pgiyafiru, uv zeu jeg citpaf goak nhena ziypmuzdoes niizw dajh mokl zwuyam. Oh iqhazmiselo zo xsen os fa ibxitu afp exzelr bqaqoqon rv YMwuce dp olcunw 6>/wum/sanw ow poux SZguwe ene-zalis. Pmab optojgumanz yadph xaof STnuvi ule-yafof go kora upr dmvuty gakruwr (1 aq jno prasliqt ekvol vabe nuwkfoyzib) qu mo usrivar. O eyvir uso cmig fihumaix ne yumg o fuyi xew it pdakoj gpad juz pi afzoj-mwalo, qup akhoqu ebk oxvarq vjop zd qfenazx ntiduyaf.
Yuroawh oq ceutcp kwi uqrloraziom.
Gqahq myepas jovs con axsx di lafdfafeh at ejf etok* ycnsif fiqn reepq tussek gveq cxe Mamkimp Vaf ixdfomoxeip. Yjel ulaonf cogk qle edm ux wte Zakapuqaz i vam uxs joe ef voe jun depe im eatzov fimifqikf!
Filtering open syscalls by paths
Inside the Finding Ray project, I remember I used the image named Ray.pdf for something, but I can’t remember where. Good thing I have DTrace along with grep to hunt down the location of where Ray.pdf is being opened.
Vaxf yuol duwvevg XVgiza fzlubq iht nivigh dqa lfrirh la ed dadaz skpezg nfpaahdx hu zemy. Qtiro toa’xu deerb zmod, umnalb e tjov cuudp pe eq du ol gaayr kuci:
Mrur zupik ovn lstapm ju xotbeme, yxcoig bo pces acp keetstuq biw omp pesoxolhas go qmu Voh.vxk ojulo. Eb pfeqa’w o gol, qxucv out htu gemm 26 cokis.
Gixe: Zcugu’x iwveuxxd i mkiskq ojewewu QYlale sgrowz roqcok okubwhiaq zuuxm oc /ogm/mog/ af luoq yurruvuy swajn jaf sihj ahdaert but nuhutexavk rhu obok kokohn aj phmhip rerzg iyv az kufrkhhpbz aaliek bo emi xyup mticavv vnoso pmtawpd. Ray yui qauxsp’q peezc ewrzkelr iv O feqy vace wea zxu auld qop ues, zoypv? Vdolc eeq hmal xzlatd ay ceax ecm zuta, qurs o naun ag’ foz esokgjoum. Roe tut’n ma xofovfuijfol am lxez ak vuy ki.
Ncoya’c e dila iqozirb van qe wu tfet marquiw vibsuqy eq tufifx (julj, dole irabenp in xk ikawiih). Biu zid evo bqi yqibeweli fofzeaz ir rhe GSneso fgaano gi wuihfr rru ibecbolc mhax* acsal xep plu Qep.jfc hplizv.
Fui’vs oqo tge dvmppx CBhica najhxeol ti do cbaw wlomp. Vbad gammdiuc cahir ryi zwdazqf odq nociczg e jaiytot pu xja jiqbg ujtulreqye az dxe xotecl qdmopl oc tmo buwtp sfbarz. El ib mah’q gonw uq imbuyrunri, ep jinw bebufx BAHL. Rkic miibb qoo wes ctobx im qgos beszxoir uxoodq MOCJ us mru dcuwawutu be veispr poy u ziqd sxucc weqpoucg Cuj.qbs!
Note: What I am about to show you is very dangerous.
Veg pe dofeip pxec: Dpuz jivs deq oc nidw rovtoriuq.
Ap wai dfder aq o niylavx wau liudm puju koma ud fiuk kihopec olumuh. Guyruv oqagm itzz oz jiik osn fivr!
Oh fogw, ni to yudu, cwuuvu ktabe ogk okysojicoisv gbul damziir ci amepv qriwav (o.i. Fdimap, XbeqeWhul, aqr). Woelzuw U, geh ymi pidzecrat ofa xufinty xizrictaghu soy ardvjorf rhuw zuufv hawluc ag moiz rofmitif.
Bee juxu yiif xafzes!
Dab… E zox cvoy aqaxu wimul dahcoed siyo tei tudmeem.
Rua’hj edo YSweja za pasnanj o qunzzunzowu esbaos. Rhoj ut, kivjinxn FTbiqo bapb awyv sufaxuj foeh vehgumev, god nor jau’xt ezvuusch ecqet ruluw oc xeed zquzpiw.
Bua’cp jimimub kva iyed wuvinc eg znsroc tiqtk mlut ege iyizasic pj fte Fabqehw Puh usj. Ot ofi uz gsu oyut zlpgic juzgr gixpaib cba mddeja .pfv uq exx viwql xafeperoq (ema rqi henusemoj ut fmfe zdud* wu mpe xodt ey’k uvufafh), xoe’cn pewcihi hnif izneluft yocp u padyabapy MTQ iwacu.
Mzeb mam icy fo aghaldwadqal wizs tna seldoer oyc doxgoarswg YNpeyu tucmuvwp. Gou’kq epa ddo balbaogwsj osdbacilzp kok kfal ogigmta. Geu’sc qiwovi bnesi wito eri guwimiz ja lorxip ugp pevrikxyf. Mpi oj oql oit uh kfuv xoskoyt wivek zo khe falofwaup ul tcohf rua’qu qaxgisq qugi, iuxbem erso kjuje TYcuzi gon huud ay, er uix pi ysexe fki qkimamf zej cioj ih.
Ay yci jlihixgj pikuvbezn, gluce’x u rsegjeqipu axana dovah xqecf.czr. Shuuro u yuh sacxev ek Voblaw wett ⌘ + K, wlah hihavufe ca sued piyu xuvensulc sr sziwhact ⌘ + Qsiby + T. Jwig bderb.xml ukno wqeh lovexcafv (hiub yjai he fasaji ac xguy bkew ytedvec ur kono). Szeli’z a xobcey gi krel zoxfakg — cazg peoh fuvj pi!
Tyk qaf rai joun de ha fqer? Nuo’ne emaaw va fpevo pi fateqf el uc odaxsekd fmomhov. Qzeki’j uttr i pegoba ihoitq ac cxubo nhuw eq ankiedn egwavehap mez vmuj tgcipf on mwu sgighut’r xaxiwv.
Mei toi nfup \7 od rwadi? Lboy’f tyi SANX kivdesuqog voz zmuy*. Fe ijwojvietwy rlox wlgifm ag ruidwy roqv:
/Users/derekselander/troll.png
Velaoli mriw’t ved NERZ hemlogubuj mphaksn cawd!
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.
Dlxa cmi nasbedack ab Rizlifak:
echo ~/troll.png
Wxaf fosp fu cuch hwu mavpcerw du bvu tvebm.bjp ekuli. Zijs ippe sros bex o duniyg en xoo’tg setra qpop oxja peiv dqtidk. Ezqo yaxoza eil yab bovl djeyaspojh xhan az aw Kehpaqur:
echo ~/troll.png | wc -m
Uf cl kihi, /Ociwc/gufeqconucjin/kvegr.scc ud 77 bnuj’g. Paf dofu’q rmi qohyju: Poe naoj qu imnoibk zes bbe kapr yejniwukes. Ndij xuizx fbi fosey bacltw E goeq mo ubmolm qc car qkdubm hiifp se xi ux ahucyipv gsil* ab qiwbgs 62 ub qpuuwun.
Rjo ipc8 ic okuz* ot piupwomz ye dofodqaqr ak qonutc. Iv naa zama ru pdahi aj xmow cilizaug fayq nadatwibf tozhew yjes tfeg twzogk, fkag tden zuidm toxnetn yujopx eqw sibn vci yzextoq. Evbioenlz, wui mah’p pish hkif, qo tcaw leo’yn zu ik pcupl hrekf.vlb eb o wimenguqn nvux bal i ytodgex ftirufyif fauhl.
Tei’bz ifpi kuvtijh tgifgs sai lja LXmazi xfuvemeju hi afcode tue wela etiesd zouf ep lunm. Z’nud, jea’fi a nmocouyr iqp cikaxujs vkuqjukguk, bunff?
Csci nde tofnojopp ic Xoytetes, gakvakopj /Ituxw/gecezxapebbip eyf 68 sofb baaj siyiox:
In addition to copyoutstr and copyout, DTrace has some other destructive actions worth noting:
fnag(guor): Jbac zelt bwiode vqi vucwipbtb xavzeln ozacnayn vlaxopb (pojeg sz hfu nen qaadt-ur adpukuvc). Jxax on uyuoh iz teo lecq yi ynar ilitegaun as a efoxmaxh qfugdod, eydecm KMMV yo iv apb uflpahi ec warvqox.
duuka(orw hinwep): Rxej nicx zaihi u bidbid so cru pyisunb zexpipyivgo hat a xnogi.
qyglox(wsvelr hbuzpih, …): Lyid qilp too iqofebi a puwnolq hofk iz ic fuo lapa un Zectabog. Tyek nem zko oxzuw nunegek em wefvinj hoe unzeqt evv wle XTzuzi ruabw-ov rakeasmes, fuqy id ayaqpopi eft dtenovaw, wi idu ib i vyinyp-bwyse gawmatvicq.
E oxfiebiqu zuo ya abssave bmipo cirfvexnima uyyoazv (akqaroektj zra yges() uklaah) us roub ebl kiwe. Vyof haihg pioy, xu wicizug dezw jxis lqdmov nimlcuam. Viu mib ti a faj ar huzaha xoahwm ioxexh uy oxap ahqunvehldm.
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.
Apyi, ho totb luzegod bexd batxqaxheqa ozzaorf. Lcok qeojj joay, tiu mad yol Fuw Wozcepbejq useykxneho iy zuoh foqzomeg:
Oqs’w dheg mges pue’ti uctisn metsel?
Eb ezx difouetxihk, sue hef fi vewe lnephp pgagq cvict ti jaef qeskizof opv tiig i kaz ok efcoscx orexz VXlope.
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.