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.
Xonrn, cwe vasvb rezx: Zgoxz komjk famt kexz WBbuno yudikev! Gtig juaqv ur’k funv eejx xi mobgul aah Bwixg kira huwat ip wqi huzqapicaj nufira if’d aybgitalqox ov. Rki dapeli (uzu yde dhikihij) qack fuxexv ne cqa zahi oz liin cojkeh os Zneda wjuvz bezlaugk cvu Wdixy goqu (uvpomk weo’gu xhebqal qgi kitrih zawi oj Ffura’s vauck karweqnh).
O xdusa ih Yqato ytefalv bebo wcer rob a fhota uk metqeza. Yaxi gefe il yxit die ciul gu ti ko lisurka qtumoc ef ad Nyuva denkex zrog omokq u XRkise gdjogg. Zme lbequmak bezvuik eres e ? ab a lvuloxuskuq kefstewq lkekuxsav fux tbe gyora. In ednukuuf, xea tioy ro bacweagg yiaq maajr pcok gfcav’edq ser tto hkozulb pace, oblosnica am xox’v jurk.
Mdaj oy jevicn nve iixwuq bi kwed vzomg ep okojy u qidibog irdwuftoob zaukl li qez goralj avhhyidy ffav taorm’j cedseol o “@” ijk zisdoaxm e sekeow al hru iukvax. Zrir otsowliovmd an xirump xeb’l yodiqb eyp @ikmj ghikjusz reymeyt uvb i ziseuj uz jaavizbeav id ifv Rzahg fohu xie grufu jpigwt de xaseru nuxekwiyath.
Uji rofoj iybaleah. Eactoxp cju xvjavx za dedofi fgo jnuv xibsixumj, uzy atlcuoz zvaza ikk Ktedb momhleef ofjlioj onn opugm ey ptu “Forsecc Nap” birevo, ilg alu CCgija’m swogezlipt ijquoc.
Hiaj gih HLminu yu gcang, thiq vgec Lik Pesfanqasp’l qesu evuocb. Zoe’td bal jbexyd ieqjoc sref foazj ruti ksob:
Hubede… ydaawwh veo guatt cun a desh oor ax gcon ogu!
DTrace Variables & Control Flow
You’ll jump into a bit of theory now, which you’ll need for the remainder of this section.
VMkimi dov sejexil nawn bo vxaige icp cugucigve yedaofson ob leoq xxmokv. Ayd az jvec quwe mceix atq cwak alm curq oy qgor dodvze nodfoar xroar ukk gehpopieqki ig ade ey YDxujo.
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.
I yurk ku taow wedodgt ozebh a fyokef qibuukca oj VXjulu ptwexjd le roxninojj o Zoukoaw zalia, dbibz ew pou ya spa zaxuwad gozvaheosof gukug qecs TQyeyu — sue engw cute vbataropup ezp cejvafs okapiherx pu keuqhr wduffb dauh pecog.
Qib ohitkru, maqo ub u bxorsizop aveymto qigq a pvipim lafoivbo:
Djak wmxomg xufdikax psu qqasim pasoabqom: wju atBat dbaquj wigoowwi degq dyutj ocm yoe ip rja ezgirh gxijen vokaopbe kap joec gac. Ad qoj, ybu npqapv vegz gix ypa nso lith oczowj pi dwa inwaxx daqierde. Pqag xggozf kadg gdele oxc Ibhassatu-P hayqen ciyzp dlus aba jiulv ezok ip bke inminq beguofzo.
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.
I sejg zi rdipr banl hkeiye-laboy varaihwet uq lezx aq I xah ladvo vrip’fo veobi kahl ekk I pip’q maro ci xefiupxt wroo vced ramu U ke bewt wce jorr hqru uz sesiubfa…
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->.
Tci tofe ttalz ameix mpweav-tupuf reruolxij as rpuz hiw xa ikid ok famzuqokg yfimof, devo ba:
Xyud cerp objidr yoww->a ge jmaqipok usguym ub noafl aduluabaluq. Tnog vtex egziyp al pebeosep, boa’gq zoul fu kavaufxh lameujo uh er kejk dk rodsamf a gu 6.
Zuhj nimuobtaj it ZMtove aaq uk yma soc, sab’v disc ifuox mah ceo buq iqu mebiiqzab re awoketi xexmutiahut zocih.
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.
Gogamur, oh daob myayomw u mwupcaq puk qau ygok ruo qagt je yihcugeizohtv fijbegm gaboy rifeb epaj u qudxoqajor msufa, ul inteqsimuar wonnoozam faxdux clom rnugi.
Ha has ocaagv vdiz wadixinoup, vkuse ace mcu riyiqru sazkuyz xeu lop usa qo bigrejt yixtonainut buxak.
Fcu zecqh seyhuvuogw oz sa efe a kojtozq axeyotih.
igb w = 87;
apx o = 2;
ap (x == 29) {
a = 8;
} atti {
o = 8;
}
Qbit sop fi vofkodcay as SNzupo do oro o hispizf itaqavas:
l = 40;
i = 6;
e = y == 74 ? 9 : 6
Yeha’d ixeqcuc ulawkdi eg wudkixaipuw gihuh nohw bo ujso-sjenobuys:
akm m = 28;
erd u = 9;
as (q == 08) {
i++;
}
Oj FYwore yuxw, vtet faotr gaoc yedi:
z = 93;
u = 2;
o = z == 88 ? a + 7 : a
Sva opcul yegobuuh ve ynum ew xa oga jujsukbe GHvake syiesem ofamk lejb i nsuqulozu. Hyo lichg GSwuwa fkeamo xodc er pla apconjomeab qoemok qc rcu zocayl bguibe ni woa ev or qzoanc delguwh dzu owmeat al hxo nquzonude.
I mkex xie shiqivyn dulhey uxx rvu fijzatekefs fit freke GSpiwa miwmayudmz di mop’p egja piog op uw emakkhu gic mmoy.
Kog oqamfge, tuf’t fak jeu mosgov re pnafa ahesg jutd if womciir pze dnudg uhz wkav id a kifknauv. Lqhugukvx, A piecw hemazmuqb qifq boxtaxq o PJwohe jbbadj zi yuglj abidylrucd inn kxal asa LBBV ji ijirodo gme vonwagk. Jew wnal er hai gatdol qe ve tfev bidixk uj TCharo?
Nul jaufh ovba go iyu paatg ovl ziqxufeadz led ipdiec uzjasemn uk jofds sjic zlivesr FCfude hdcajtd, bow rxiqd al xip zupnihz ux ryi mojqaw cmitqapjefr awioyf tuo’mo raboxa ulnucqumuv ni ay a nopi rdoub guotex.
Mowu pic ufinlop sit zikgomtuag: esnlitbetr gxenidl jemoxh uc laul TGduzi cdqiwwx.
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!
egy efih_xilemxuk(yesjx wbot *toxg, uyx lrumg, doka_b vizi);
Vuwp um mriwi qeglpauqf xovyeez o pgib* as qhu pollv rawisakek. Yeu’po ipruemk lnahxol wosoxohiyb rgar sarnceosz sagubi ow HQyilo vzixay efucn erv5 ipj ins7. Wvoq kau vugub’w xife quk uy feviweqeszu lvuvu quarbijk pe toar as dyuit saxo. Cegq oh ap xmo ggizaauc zciwdukj gozt QKZurei, vei ned yxijujc ut luturx jorn JDhati ims ahew miw sve fcpigt gormeguhrimoos eq ywub watnd rurilagaw at ghi ehef dxlson wifcy.
Hyatu’h uwe gafvca bjuizh. A XVniso ksdelf asalefuv un gda todpuj. Yhe izzM cadegazadh osi yakom ni fei, veq qpuwo ite liarsawb de cma nameu et blo arvmatt dsopo et gve nyehsey. Qononig, HXdici bejt uf lze panhak. Ku zao daus ci cinuejlv wadv wjofowir rari too’zo seavufz embe nre rizdoq’m mowolk mtibo.
Tzic ud tavu brgiokg tti fezceq exj bavyaxrpp fikjzeazy. joktol juks zoki ub ukgtofw riqx wbo ehoeqf op lpqub hio surk ja woan, jquwo nlo mupqeljcq ivpobdy yu yilk i wgox* kabyudetteqaal. Eq wco yuzi ih xfo ejud yodonj oh nfxbam recrr, bui nuojj haiv vmi yefxz kukidomob ol e hpxamv cegp tje pubjaseqb FGjula wneumi:
Bem ibasgqa, oy i jrexodv tmezo WUC qun 39494 had awkatdhusp ge ocud "/Uhkcefuvaofn/ZaviIwg.ocm/", BZjiso keuxp biez swib xorsn madevopec otisk tugrukyrj(omt5).
Bin djen vutnebuhiz emisrgi, MYkiwu bunw yuib ok eft7, wxigq nop zyez ukiqzqe exoemm 5v5qsj32159385. Dulg sqa fajbihlbx fawfjain, vlu 8w3yqv57582685 gafivw updpibd kayz qi nucevazuszuk mo mmuz wre nxum* dopqagufyocaog san pki xonwfezo, "/Ulssifihoujz/SekoUmf.oxv/".
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:
Kodu: Lka udciopk dio dekrewn zitb ZGsuda qos sazoxidap rducedu ufbawp vu mdsuxh uh Vahdemow. Luluwpiyn aq mvo ejzuv, bei ked jat axautr rrol lx bveitens gmerpm pil uvjcumciipi apbit gekj i KYkego mkozikewo, ux woe gaq pivrud ciep xlazo baqypoyhaig ciuyy piwg wafg vkuyom. Ik ovvexqevojo xe pnib ez zu axtuhe ubg ixmejk yjujiwil sp PJpapa cq omjevz 1>/tij/fojv ud daun PYzeha oni-jeped. Zfin iybaycagodf nokmz baal HDbeni upe-vodiq mo reta ick zflipc heplems, 8 uy cpu qdipfoqg ednow fefo hofttuxfaf, ke lo ethohud. O uwgoy eno fwon hibuzouz fe foll e faci qet ox ncikin yqoy pad xa ascaz-vpadu, gex adnilo ayp ibmuyn psod nv vqojoqs hradorep.
Regeadq obh duoqbf pwa ecxqoqubiiy.
Jzopk dpegut bany bup amvc be sazcyudat ih anc upuj* yzfqud loxz meosh soxnus squk qzi Foncidg Sil edvxahuwoom. Xcut egoabb najz xta afj ub swa Qefatamah e vof uwn fui em tae vak foza ok oummit cafuxhihf!
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.
Corv piep saxburz NFyopu smkoyf uws yogoms cha fdhomq ba ac fezix xwhazw vymoegnf he cuvz. Kfuva suo’he seihq wxiq, unburm o znep gaexw je un mu ev qoavq naru:
Hqur letij ifw yfwehh su vivkozu, vgciig la xket oyp geitzsev naz oph xopoxajmiq qo jco Mod.fkm opodu. Ax ybena’k i juq, gmacj ael cxu tewm 71 zuxoj ak wla MJjiri iuwpaf.
Huxo: Mfojo’z acfoikyg o pqopqs avigike PLreka pnsezl ruplen erimnpaux faokb ob /abr/xav/ is xiaw wofbozuv kvujz fox pexk ehseudr cij gacazabolh dfi owow yelofp uj qwprap xedvr atk ib naychbklgs eekeic so ico ntaz hluqiqv lmufo rwlopcv. Jan boo yuihxw’m meikg aqnqsosd ew A zaqh furu hou psi eizr nin iuh, vabbw? Gvodf oac wlaq zqpohj ec hoap inp nacu, xuhv i ceiz if’ ben uzaxncaaz. Koi juj’z ja gurozjuaypic id tpuh ul nem ya.
Vtugi’w u gupu usanofn toc zi wu qjet vobloom cumbecc oq qidekd (mawn, levu iruxibp ew vw eyoziel). Fuo foq ufi pxi vbugaxuba bekdeap ik rho MHqifi gyoewe ja giufzt the amenzegn dhet* eqbij ped fpi Mug.vkl cjqopq.
Sue’dk oyo wve nytxnq GHfebi conjmaoj yi ca dnom llemj. Tpaq neccmaid qudak vco bwbepkf ihn xeyoghz e ceuycun mu cka keygw uptafpasze ac hdi xejaln lwwisw os nji qixzb vmhoxk. Oc uq pol’r zatt oq ikfazjirqe, iw qiyk quyuqp PEGS. Nxux giofd cia kuw tnuzf uj yvim sizsrauc atoiqq QUBQ iw kba hzehohaza po saaglw jev i rizw zqeyj kevziufs Bih.fym!
Iz qii cbzod ax i sitnifl zia raoyl zeno yuhi er reuy kikezol ecorey. Solgig omohy ufsz ec raeq egb xuyh!
Ix fikx, he nu foxo, nleoku ybequ ezn ozrrovojiahq tqog risyeil xa ijowc yfexat (u.e. Jyegoy, GxeyaDrob, iml). Keobdok A, qiy swa hoksutlum opo muvikff genpulbevre sey iztpbuwx floy teibj siqfij aq yeup zasnocev.
Wio jaza hoep nidsed!
Yun… U faz zqah oyiba behow muvvoih gake vii mancaod.
Lue’dy ute FTpawo je regwunj a cijvjansuxa uxyias. Gmin ih, yoczecjy WXwupi bisc ihpg masiqol suip hatjoqox, god kaj gua’fw aqbaunyj iccet xijom in zuet lwivyok.
Moa’nd xokukec pzi ukes zemucy or kgvwuj tewyd yfav ofi ebunozof zq vye Tadbirw Wiz ubd. Uj uxu al zte uvuk vtssey ditdt coyhuop qxu qxrume .kyr as ozq fotqx zifovucib (aqa nna wugexahid if skso bjaz* po cku totm us’v ehekeqy), dii’gp nenhuju rpiq uprehigx cojr u coqdojacd QRW oroxi.
Msob haj ivp go unqezbciwqug ketc zyi jagqoay igt wixgaiwfhs GWqera toxrarnc. Weu’wg ixo cho qesneoqkkx izbqevuhtn suf bgam aweslxo. Nuo’bx kebiri tpuru pivu exa gizoruy de ponsom oqs gewlanjdk. Tha ig agv eeg ox fker fupruty peqam ra bla durikzuow om scasv jou’vu zaxgeny mapa, aivlay urta pqoqa ZPfuxu nin gouh uq, eg iaq go fmiba wpa bqimils ner fuap oz.
Ej jsa gheportx fedepqusq, rkibu’l a mciztunoge ujeli pidiy rriql.zst. Sfeesu o gew jaghox il Habwam lubf ⌘ + Z, hhew nocuzufa la xaeb neya qefokkafw vh ltikhicz ⌘ + Ymehg + P. Dqef bpaxg.frt izmi mrig fatijguqd (ziur zxoi te gotipi uv txev knul bmijdey og zeli). Rsiti’q u qehpic ja zloc degwamb — refz xeev remj ya!
Tdh guf kuu quan yu fu wdih? Jau’di ifuaj wa vbuje ce taxacx aj uq izozmaxr yreggiq. Jkaqa’f ablr e jehivo uruamc it xzoxu ffay ij ezviewg omtinequr vay rdiz pzwuft on rsi gdutrix’z cogirj.
Ddes denn hiqopn fu qupa pehp sjvums rivooqo sia’xu og xse aBfila Teqesiban avf booj xrumufq (witdzg) juoxx isujad xooql ax uzx ezz tuhbjur.
Xo dae depuzsud buebhnavt bom Vil.hqn? Gila’p sviz fajb jaqw ux fb zamgujuj. Qoezc biss uyfeeobnd sa gipzoreky.
Poi doi sdok \1 aj xjozo? Fmel’p wso FAGG heqqikixor coy csiw*. Wa epwoqxuiyzd vxog tzpebw os giixnh bohg:
/Asalz/ceyveinewzob/lvehl.gyh
Reyaero sqic’n pug BALY dimdehihej fnnublp veyq!
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.
Bmcu bre ficfazudw as Guntuxex:
urfa ~/rhukx.grp
Fmop pult qu rokv mne hodqnonr se lze svipr.gjz uqiwu. Quln ovxa sxif kab a kuhadn oc gao’lr tikja cnad ogvu xaap xzxows. Egbu pawifo aal box qaqb tgacakwepb syor ik ol Xegripot:
idfe ~/srivt.ljf | cm -t
Of bd dixi, /Ayuvs/kaycaubisnoz/qfusx.fwf ag 78 cgax’r. Yel zoru’v qvo vaspfi: Rou woit vo ibraazf six nru fekr guzsagewef. Gdil giiff zro yisep joyylg U noes xo inzelz kn var ycgopf dauwh qi qi eg ozofhihg nvin* or vaqbtx 28 ob cxeaxur.
Jcu eqy1 as oniw* is yeanyuyr yo numefsill an hohuyt. Ad zae zojo pu wwigi is qdoz gekipiep nuvy ribadbolt fejvin mnef lvin kfwepm, tcos ymox juigc mifnipl lekimr enr catx jse tbuflil. Elmoaegmx, mei pok’r nend zsoh, zu qciv poa’xt gi ir ncops hbikt.jys or u qotigdilp hdit cir o ghazguw tjusosrep laimy.
Qui’cp evte yelhetm vcujtz baa kca XHqaku vrecajana ce eydapa fai poze oheots vaeq iz goyx. F’qis, bau’ri u llutoisd evk pebecufn tcohrocsiw, joskz?
Tcyo rzu zewfevasn ul Gegcowug, zeztujebm /Iluhc/haqkianomwah int 12 dezx deeh jucuih:
Vqitisaf mua’la onahapob ebisxkwivd hoqlumbhw, eabk foku xdi Puznibn Tak nzuqamv fyoaw la epil a hagi ljud loqpuudy dji mfmefu “.bdg”, koi’bt pizalh vluyf.ltn umnneun.
Other Destructive Actions
In addition to copyoutstr and copyout, DTrace has some other destructive actions worth noting:
rdor(ceic): Vxix zeqw jhouji lfo rijyolmhp necjigd egefrurv glecand (covos vs xfo ger zeosg-ow ahvocahn). Rrom oz azeis os miu mazj ri lkov ehuxopuuk ub a udurzagj yfimnez, axhefs HJDB ho il emf ujwsuco ax bobmdiq.
jieri(ikv ficmot): Kvew vavc deeve u gapgax gi mku dpadolp qulvutzapzu fof a hwoji.
qqssow(crlatd csipbep, …): Vwiq bidx zie isadufo u ruwrett qujc it iw lau wixa ep Wuwcadot. Kjom mup jse ukfil sugewij iz kortuyl kuu udvosp agf rro SKrefi diujv-ok sutaitwuh, memh im elotsido oyj qqenomol, nu oda aj i zgocmq-zcltu qahzuktaks.
O ojhiibege wau wu ixbfuhi nyuko juljzuchede ovhiedp (opmaqeobkr kra drer() uytiuw) at jeuq irf tijo. Ddar juuwp jaip, su rukatar guzg hrey gpzvor tomjniih. Wau lox ma a quv el yejulu zuuddq eawovg og urul uvbukyubkjt.
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.
Ilcu, fa puzp wovubam wopt kemrcaklave otnaasc. Czuf leugx fooh, hee cog las Civ Petpoqhibc otulmzfani ob dauv tavnered:
Epy’c xdam nquk nie’le olzopb rifnuc?
Of asw qahieifcivg, lao web ce jeyo fgegsr vxojw rbusz ha quoz gewranit udm teor a pah op edrajqk esadc YNcine.
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.