12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605(*Generated by Lem from dwarf.lem.*)(* -*-tuareg-*- *)openLem_basic_classesopenLem_boolopenLem_functionopenLem_maybeopenLem_numopenLem_stringopenLem_list(* TODO: check why this is not imported in ELF *)openByte_sequenceopenErroropenHex_printingopenMissing_pervasivesopenShowopenDefault_printingopenEndiannessopenString_tableopenElf_dynamicopenElf_fileopenElf_headeropenElf_program_header_tableopenElf_relocationopenElf_section_header_tableopenElf_symbol_tableopenElf_types_native_uint(** ***************** experimental DWARF reading *********** *)(*
This defines a representation of some of the DWARF debug information,
with parsing functions to extract it from the byte sequences of the
relevant ELF sections, and pretty-printing function to dump it in a
human-readable form, similar to that of readelf. The main functions
for this are:
val extract_dwarf : elf64_file -> maybe dwarf
val pp_dwarf : dwarf -> string
It also defines evaluation of DWARF expressions and analysis functions
to convert the variable location information to a form suitable for
looking up variable names from machine addresses that arise during
execution, including the call frame address calculation. The main
types and functions for this are:
type analysed_location_data
val analyse_locations : dwarf -> analysed_location_data
type evaluated_frame_info
val evaluate_frame_info : dwarf -> evaluated_frame_info
type dwarf_static
val extract_dwarf_static : elf64_file -> maybe dwarf_static
The last collects all the above - information that can be computed statically.
Then to do lookup from addresses to source-code names, we have:
type analysed_location_data_at_pc
val analysed_locations_at_pc : evaluation_context -> dwarf_static -> natural -> analysed_location_data_at_pc
val names_of_address : dwarf -> analysed_location_data_at_pc -> natural -> list string
The definitions are deliberately simple-minded, to be quick to write,
easy to see the correspondence to the DWARF text specification, and
potentially support generation of theorem-prover definitions in
future. They are in a pure functional style, making the information
dependencies explicit. They are not written for performance, though
they may be efficient enough for small examples as-is. They are
written in Lem, and compiled from that to executable OCaml.
The development follows the DWARF 4 pdf specification at http://www.dwarfstd.org/
though tweaked in places where our examples use earlier versions. It doesn't
systematically cover all the DWARF versions.
It doesn't cover the GNU extensions
(at https://fedorahosted.org/elfutils/wiki/DwarfExtensions).
The representation, parsing, and pretty printing are mostly complete for the
data in these DWARF ELF sections:
.debug_abbrev
.debug_info
.debug_types
.debug_loc
.debug_str
.debug_ranges
.debug_frame (without augmentations)
.debug_line
The following DWARF ELF sections are not covered:
.debug_aranges
.debug_macinfo
.debug_pubnames
.debug_pubtypes
The evaluation of DWARF expressions covers only some of the operations
- probably enough for common cases.
The analysis of DWARF location data should be enough to look up names
from the addresses of variables and formal parameters. It does not
currently handle the DWARF type data, so will not be useful for accesses
strictly within the extent of a variable or parameter.
The 'dwarf' type gives a lightly parsed representation of some of the
dwarf information, with the byte sequences of the above .debug_*
sections parsed into a structured representation. That makes the list
and tree structures explicit, and converts the various numeric types
into just natural, integer, and byte sequences. The lem natural and
integer could be replaced by unsigned and signed 64-bit types; that'd
probably be better for execution but not for theorem-prover use.
*)(* some spec ambiguities (more in comments in-line below): *)(* can a location list be referenced from multiple compilation units, with different base addresses? *)(** debug *)(* workaround debug.lem linking *)(*val print_endline : string -> unit*)letmy_debugs:unit=()(*print_endline s*)letmy_debug2s:unit=()(*print_endline s*)letmy_debug3s:unit=()(*print_endline s*)letmy_debug4s:unit=(print_endlines)letmy_debug5s:unit=(print_endlines)(** ************************************************************ *)(** ** dwarf representation types **************************** *)(** ************************************************************ *)typedwarf_attribute_classes=|DWA_7_5_3|DWA_address|DWA_block|DWA_constant|DWA_dash|DWA_exprloc|DWA_flag|DWA_lineptr|DWA_loclistptr|DWA_macptr|DWA_rangelistptr|DWA_reference|DWA_string(* operations and expression evalution *)typeoperation_argument_type=|OAT_addr|OAT_dwarf_format_t|OAT_uint8|OAT_uint16|OAT_uint32|OAT_uint64|OAT_sint8|OAT_sint16|OAT_sint32|OAT_sint64|OAT_ULEB128|OAT_SLEB128|OAT_blocktypeoperation_argument_value=|OAV_naturalofNat_big_num.num|OAV_integerofNat_big_num.num|OAV_blockofNat_big_num.num*byte_sequence0typeoperation_stack=Nat_big_num.numlisttypearithmetic_context={ac_bitwidth:Nat_big_num.num;ac_half:Nat_big_num.num;(* 2 ^ (ac_bitwidth -1) *)ac_all:Nat_big_num.num;(* 2 ^ ac_bitwidth *)ac_max:Nat_big_num.num;(* (2 ^ ac_bitwidth) -1 *)(* also the representation of -1 *)}typeoperation_semantics=|OpSem_lit|OpSem_deref|OpSem_stackof(arithmetic_context->operation_stack->operation_argument_valuelist->operation_stackoption)|OpSem_not_supported|OpSem_binaryof(arithmetic_context->Nat_big_num.num->Nat_big_num.num->Nat_big_num.numoption)|OpSem_unaryof(arithmetic_context->Nat_big_num.num->Nat_big_num.numoption)|OpSem_opcode_litofNat_big_num.num|OpSem_reg|OpSem_breg|OpSem_bregx|OpSem_fbreg|OpSem_deref_size|OpSem_nop|OpSem_piece|OpSem_bit_piece|OpSem_implicit_value|OpSem_stack_value|OpSem_call_frame_cfatypeoperation={op_code:Nat_big_num.num;op_string:string;op_argument_values:operation_argument_valuelist;op_semantics:operation_semantics;}(* the result of a location expression evaluation is a single_location (or failure) *)typesimple_location=|SL_memory_addressofNat_big_num.num|SL_registerofNat_big_num.num|SL_implicitofbyte_sequence0(* used for implicit and stack values *)|SL_emptytypecomposite_location_piece=|CLP_pieceofNat_big_num.num*simple_location|CLP_bit_pieceofNat_big_num.num*Nat_big_num.num*simple_locationtypesingle_location=|SL_simpleofsimple_location|SL_compositeofcomposite_location_piecelist(* location expression evaluation is a stack machine operating over the following state *)typestate={s_stack:operation_stack;s_value:simple_location;s_location_pieces:composite_location_piecelist;}(* location expression evaluation can involve register and memory reads, via the following interface *)type'aregister_read_result=|RRR_resultofNat_big_num.num|RRR_not_currently_available|RRR_bad_register_numbertype'amemory_read_result=|MRR_resultofNat_big_num.num|MRR_not_currently_available|MRR_bad_addresstypeevaluation_context={read_register:Nat_big_num.num->Nat_big_num.numregister_read_result;read_memory:Nat_big_num.num->Nat_big_num.num->Nat_big_num.nummemory_read_result;}(* dwarf sections *)typedwarf_format=|Dwarf32|Dwarf64(* .debug_abbrev section *)typeabbreviation_declaration={ad_abbreviation_code:Nat_big_num.num;ad_tag:Nat_big_num.num;ad_has_children:bool;ad_attribute_specifications:(Nat_big_num.num*Nat_big_num.num)list;}typeabbreviations_table={at_offset:Nat_big_num.num;at_table:abbreviation_declarationlist;}(* .debug_info section *)typeattribute_value=(* following Figure 3 *)|AV_addrofNat_big_num.num|AV_blockofNat_big_num.num*byte_sequence0|AV_constantNofNat_big_num.num*byte_sequence0|AV_constant_SLEB128ofNat_big_num.num|AV_constant_ULEB128ofNat_big_num.num|AV_exprlocofNat_big_num.num*byte_sequence0|AV_flagofbool|AV_refofNat_big_num.num|AV_ref_addrofNat_big_num.num(* dwarf_format dependent *)|AV_ref_sig8ofNat_big_num.num|AV_sec_offsetofNat_big_num.num|AV_stringofbyte_sequence0(* not including terminating null *)|AV_strpofNat_big_num.num(* dwarf_format dependent *)typedie={die_offset:Nat_big_num.num;die_abbreviation_code:Nat_big_num.num;die_abbreviation_declaration:abbreviation_declaration;die_attribute_values:(Nat_big_num.num(*pos*)*attribute_value)list;die_children:dielist;}typedie_index=(Nat_big_num.num,(dielist*die))Pmap.maptypecompilation_unit_header={cuh_offset:Nat_big_num.num;cuh_dwarf_format:dwarf_format;cuh_unit_length:Nat_big_num.num;cuh_version:Nat_big_num.num;cuh_debug_abbrev_offset:Nat_big_num.num;cuh_address_size:Nat_big_num.num;}typecompilation_unit={cu_header:compilation_unit_header;cu_abbreviations_table:abbreviations_table;cu_die:die;cu_index:die_index}typecompilation_units=compilation_unitlist(* .debug_type section *)typetype_unit_header={tuh_cuh:compilation_unit_header;tuh_type_signature:Nat_big_num.num;tuh_type_offset:Nat_big_num.num;}typetype_unit={tu_header:type_unit_header;tu_abbreviations_table:abbreviations_table;tu_die:die;}typetype_units=type_unitlist(* .debug_loc section *)typesingle_location_description=byte_sequence0typelocation_list_entry={lle_beginning_address_offset:Nat_big_num.num;lle_ending_address_offset:Nat_big_num.num;lle_single_location_description:single_location_description;}typebase_address_selection_entry={base_address:Nat_big_num.num;}typelocation_list_item=|LLI_lleoflocation_list_entry|LLI_baseofbase_address_selection_entrytypelocation_list=Nat_big_num.num(*offset*)*location_list_itemlisttypelocation_list_list=location_listlist(* .debug_ranges section *)typerange_list_entry={rle_beginning_address_offset:Nat_big_num.num;rle_ending_address_offset:Nat_big_num.num;}typerange_list_item=|RLI_rleofrange_list_entry|RLI_baseofbase_address_selection_entrytyperange_list=Nat_big_num.num(*offset (of range_list from start of .debug_ranges section?) *)*range_list_itemlisttyperange_list_list=range_listlist(* .debug_frame section: call frame instructions *)typecfa_address=Nat_big_num.numtypecfa_block=byte_sequence0typecfa_delta=Nat_big_num.numtypecfa_offset=Nat_big_num.numtypecfa_register=Nat_big_num.numtypecfa_sfoffset=Nat_big_num.numtypecall_frame_argument_type=|CFAT_address|CFAT_delta1|CFAT_delta2|CFAT_delta4|CFAT_delta_ULEB128|CFAT_offset(*ULEB128*)|CFAT_sfoffset(*SLEB128*)|CFAT_register(*ULEB128*)|CFAT_blocktypecall_frame_argument_value=|CFAV_addressofcfa_address|CFAV_blockofcfa_block|CFAV_deltaofcfa_delta|CFAV_offsetofcfa_offset|CFAV_registerofcfa_register|CFAV_sfoffsetofcfa_sfoffsettypecall_frame_instruction=|DW_CFA_advance_locofcfa_delta|DW_CFA_offsetofcfa_register*cfa_offset|DW_CFA_restoreofcfa_register|DW_CFA_nop|DW_CFA_set_locofcfa_address|DW_CFA_advance_loc1ofcfa_delta|DW_CFA_advance_loc2ofcfa_delta|DW_CFA_advance_loc4ofcfa_delta|DW_CFA_offset_extendedofcfa_register*cfa_offset|DW_CFA_restore_extendedofcfa_register|DW_CFA_undefinedofcfa_register|DW_CFA_same_valueofcfa_register|DW_CFA_registerofcfa_register*cfa_register|DW_CFA_remember_state|DW_CFA_restore_state|DW_CFA_def_cfaofcfa_register*cfa_offset|DW_CFA_def_cfa_registerofcfa_register|DW_CFA_def_cfa_offsetofcfa_offset|DW_CFA_def_cfa_expressionofcfa_block|DW_CFA_expressionofcfa_register*cfa_block|DW_CFA_offset_extended_sfofcfa_register*cfa_sfoffset|DW_CFA_def_cfa_sfofcfa_register*cfa_sfoffset|DW_CFA_def_cfa_offset_sfofcfa_sfoffset|DW_CFA_val_offsetofcfa_register*cfa_offset|DW_CFA_val_offset_sfofcfa_register*cfa_sfoffset|DW_CFA_val_expressionofcfa_register*cfa_block|DW_CFA_AARCH64_negate_ra_state|DW_CFA_unknownofchar(* .debug_frame section: top-level *)typecie={cie_offset:Nat_big_num.num;cie_length:Nat_big_num.num;cie_id:Nat_big_num.num;cie_version:Nat_big_num.num;cie_augmentation:byte_sequence0;(* not including terminating null *)cie_address_size:Nat_big_num.numoption;cie_segment_size:Nat_big_num.numoption;cie_code_alignment_factor:Nat_big_num.num;cie_data_alignment_factor:Nat_big_num.num;cie_return_address_register:cfa_register;cie_initial_instructions_bytes:byte_sequence0;cie_initial_instructions:call_frame_instructionlist;}typefde={fde_offset:Nat_big_num.num;fde_length:Nat_big_num.num;fde_cie_pointer:Nat_big_num.num;fde_initial_location_segment_selector:Nat_big_num.numoption;fde_initial_location_address:Nat_big_num.num;fde_address_range:Nat_big_num.num;fde_instructions_bytes:byte_sequence0;fde_instructions:call_frame_instructionlist;}typeframe_info_element=|FIE_cieofcie|FIE_fdeoffdetypeframe_info=frame_info_elementlist(* evaluated cfa data *)typecfa_rule=|CR_undefined|CR_registerofcfa_register*Nat_big_num.num|CR_expressionofsingle_location_descriptiontyperegister_rule=|RR_undefined(*A register that has this rule has no recoverable value in the previous frame.
(By convention, it is not preserved by a callee.)*)|RR_same_value(*This register has not been modified from the previous frame. (By convention,
it is preserved by the callee, but the callee has not modified it.)*)|RR_offsetofNat_big_num.num(* The previous value of this register is saved at the address CFA+N where CFA
is the current CFA value and N is a signed offset.*)|RR_val_offsetofNat_big_num.num(* The previous value of this register is the value CFA+N where CFA is the
current CFA value and N is a signed offset.*)|RR_registerofNat_big_num.num(* The previous value of this register is stored in another register numbered R.*)|RR_expressionofsingle_location_description(* The previous value of this register is located at the address produced by
executing the DWARF expression E.*)|RR_val_expressionofsingle_location_description(* The previous value of this register is the value produced by executing the
DWARF expression E.*)|RR_architectural(*The rule is defined externally to this specification by the augmenter*)typeregister_rule_map=(cfa_register*register_rule)listtypecfa_table_row={ctr_loc:Nat_big_num.num;ctr_cfa:cfa_rule;ctr_regs:register_rule_map;}typecfa_state={cs_current_row:cfa_table_row;cs_previous_rows:cfa_table_rowlist;cs_initial_instructions_row:cfa_table_row;cs_row_stack:cfa_table_rowlist;}typeevaluated_frame_info=(fde*cfa_table_rowlist)list(* line number *)typeline_number_argument_type=|LNAT_address|LNAT_ULEB128|LNAT_SLEB128|LNAT_uint16|LNAT_stringtypeline_number_argument_value=|LNAV_addressofNat_big_num.num|LNAV_ULEB128ofNat_big_num.num|LNAV_SLEB128ofNat_big_num.num|LNAV_uint16ofNat_big_num.num|LNAV_stringofbyte_sequence0(* not including terminating null *)typeline_number_operation=(* standard *)|DW_LNS_copy|DW_LNS_advance_pcofNat_big_num.num|DW_LNS_advance_lineofNat_big_num.num|DW_LNS_set_fileofNat_big_num.num|DW_LNS_set_columnofNat_big_num.num|DW_LNS_negate_stmt|DW_LNS_set_basic_block|DW_LNS_const_add_pc|DW_LNS_fixed_advance_pcofNat_big_num.num|DW_LNS_set_prologue_end|DW_LNS_set_epilogue_begin|DW_LNS_set_isaofNat_big_num.num(* extended *)|DW_LNE_end_sequence|DW_LNE_set_addressofNat_big_num.num|DW_LNE_define_fileofbyte_sequence0*Nat_big_num.num*Nat_big_num.num*Nat_big_num.num|DW_LNE_set_discriminatorofNat_big_num.num(* special *)|DW_LN_specialofNat_big_num.num(* the adjusted opcode *)typeline_number_file_entry={lnfe_path:byte_sequence0;lnfe_directory_index:Nat_big_num.num;lnfe_last_modification:Nat_big_num.num;lnfe_length:Nat_big_num.num;}typeline_number_header={lnh_offset:Nat_big_num.num;lnh_dwarf_format:dwarf_format;lnh_unit_length:Nat_big_num.num;lnh_version:Nat_big_num.num;lnh_header_length:Nat_big_num.num;lnh_minimum_instruction_length:Nat_big_num.num;lnh_maximum_operations_per_instruction:Nat_big_num.num;lnh_default_is_stmt:bool;lnh_line_base:Nat_big_num.num;lnh_line_range:Nat_big_num.num;lnh_opcode_base:Nat_big_num.num;lnh_standard_opcode_lengths:Nat_big_num.numlist;lnh_include_directories:(byte_sequence0)list;lnh_file_entries:line_number_file_entrylist;lnh_comp_dir:stringoption;(* passed down from cu DW_AT_comp_dir *)}typeline_number_program={lnp_header:line_number_header;lnp_operations:line_number_operationlist;}(* line number evaluation *)typeline_number_registers={lnr_address:Nat_big_num.num;lnr_op_index:Nat_big_num.num;lnr_file:Nat_big_num.num;lnr_line:Nat_big_num.num;lnr_column:Nat_big_num.num;lnr_is_stmt:bool;lnr_basic_block:bool;lnr_end_sequence:bool;lnr_prologue_end:bool;lnr_epilogue_begin:bool;lnr_isa:Nat_big_num.num;lnr_discriminator:Nat_big_num.num;}typeunpacked_file_entry=(stringoption(*comp_dir*))*(stringoption(*dir*))*string(*file*)typeunpacked_decl=unpacked_file_entry*int(*line*)*string(*subprogram name*)(* top-level collection of dwarf data *)typedwarf={d_endianness:Endianness.endianness;(* from the ELF *)d_str:byte_sequence0;d_compilation_units:compilation_units;d_type_units:type_units;d_loc:location_list_list;d_ranges:range_list_list;d_frame_info:frame_info;d_line_info:line_number_programlist;}(* analysed location data *)typeanalysed_location_data=((compilation_unit*(dielist)*die)*((Nat_big_num.num*Nat_big_num.num*single_location_description)list)option)listtypeanalysed_location_data_at_pc=((compilation_unit*(dielist)*die)*(Nat_big_num.num*Nat_big_num.num*single_location_description*single_locationerror))list(* evaluated line data *)typeevaluated_line_info=(line_number_header*line_number_registerslist)list(* all dwarf static data *)typedwarf_static={ds_dwarf:dwarf;ds_analysed_location_data:analysed_location_data;ds_evaluated_frame_info:evaluated_frame_info;ds_evaluated_line_info:evaluated_line_info;ds_subprogram_line_extents:(unpacked_file_entry*(string*unpacked_file_entry*Nat_big_num.num)list)list;}typedwarf_dynamic_at_pc=analysed_location_data_at_pc(** context for parsing and pp functions *)typep_context={endianness:Endianness.endianness;}(* type descriptions *)(* NB these do not cover all the DWARF-expressible types; only some common C cases *)(* ignore base type DW_endianity and DW_bitsize for now *)typecupdie=compilation_unit*(dielist)*dietypedecl={decl_file:stringoption;decl_line:Nat_big_num.numoption;}type'tarray_dimension=Nat_big_num.numoption(*count*)*'toption(*subrange type*)type'tstruct_union_member=cupdie*(stringoption)(*mname*)*'t*Nat_big_num.numoption(*data_member_location, non-Nothing for structs*)typestruct_union_type_kind=|Atk_structure|Atk_uniontypeenumeration_member=cupdie*(stringoption)(*mname*)*Nat_big_num.num(*const_value*)type'tc_type_top=|CT_missingofcupdie|CT_baseofcupdie*string(*name*)*Nat_big_num.num(*encoding*)*(Nat_big_num.numoption)(*byte_size*)|CT_pointerofcupdie*'toption|CT_constofcupdie*'toption|CT_volatileofcupdie*'t|CT_restrictofcupdie*'t|CT_typedefofcupdie*string(*name*)*'t*decl|CT_arrayofcupdie*'t*('tarray_dimension)list|CT_struct_unionofcupdie*struct_union_type_kind*(stringoption)(*mname*)*(Nat_big_num.numoption)(*byte_size*)*decl*(('tstruct_union_member)list(*members*))option|CT_enumerationofcupdie*(stringoption)(*mname*)*('toption)(*mtyp*)*(Nat_big_num.numoption)(*mbyte_size*)*decl*((enumeration_member)list(*members*))option|CT_subroutineofcupdie*(bool)(*prototyped*)*('toption)(*mresult_type*)*('tlist)(*parameter_types*)*(bool)(*variable_parameter_list*)(* In the CT_struct_union and C_enumeration cases, the final maybe(list(...member)) is Nothing if the analysis has not been recursed into the members, and Just ... if it has - which will typically be only one level deep *)typec_type=|CTof(c_typec_type_top)(* simple die tree *)(* this unifies variables and formal parameters, and also subprograms
and inlined_subroutines (but not lexical_blocks). Debatable what's
best *)(* not including DW_AT_low_pc/DW_AT_high_pc or DW_AT_ranges - might want that*)(* also not including per-instruction line number info *)typevariable_or_formal_parameter_kind=|SVPK_var|SVPK_paramtypesdt_unspecified_parameter=unittypesdt_variable_or_formal_parameter={svfp_cupdie:cupdie;svfp_name:string;svfp_kind:variable_or_formal_parameter_kind;svfp_type:c_typeoption;svfp_abstract_origin:sdt_variable_or_formal_parameteroption;(* invariant: non-Nothing iff inlined *)svfp_const_value:Nat_big_num.numoption;svfp_external:bool;svfp_declaration:bool;svfp_locations:((Nat_big_num.num*Nat_big_num.num*operationlist(*the parsed single_location_description*))list)option;svfp_decl:unpacked_decloption;}typesdt_subroutine_kind=|SSK_subprogram|SSK_inlined_subroutinetypesdt_subroutine=(* subprogram or inlined subroutine *){ss_cupdie:cupdie;ss_name:stringoption;ss_kind:sdt_subroutine_kind;ss_call_site:unpacked_decloption;ss_abstract_origin:sdt_subroutineoption;(* invariant: non-Nothing iff inlined *)ss_type:c_typeoption;ss_vars:sdt_variable_or_formal_parameterlist;ss_pc_ranges:((Nat_big_num.num*Nat_big_num.num)list)option;ss_entry_address:Nat_big_num.numoption;ss_unspecified_parameters:sdt_unspecified_parameterlist;ss_subroutines:sdt_subroutinelist;(* invariant: all inlined*)ss_lexical_blocks:sdt_lexical_blocklist;ss_decl:unpacked_decloption;ss_noreturn:bool;ss_external:bool;}andsdt_lexical_block={slb_cupdie:cupdie;slb_vars:sdt_variable_or_formal_parameterlist;(* invariant: all variables *)slb_pc_ranges:((Nat_big_num.num*Nat_big_num.num)list)option;slb_subroutines:sdt_subroutinelist;(* invariant: all inlined*)slb_lexical_blocks:sdt_lexical_blocklist;}typesdt_compilation_unit={scu_cupdie:cupdie;scu_name:string;scu_subroutines:sdt_subroutinelist;(* invariant: none inlined(?) *)scu_vars:sdt_variable_or_formal_parameterlist;scu_pc_ranges:((Nat_big_num.num*Nat_big_num.num)list)option;}typesdt_dwarf={sd_compilation_units:sdt_compilation_unitlist;}(* inlined subroutine data *)typeinlined_subroutine_const_param={iscp_abstract_origin:compilation_unit*(dielist)*die;iscp_value:Nat_big_num.num;}typeinlined_subroutine={is_inlined_subroutine:compilation_unit*(dielist)*die;is_abstract_origin:compilation_unit*(dielist)*die;is_inlined_subroutine_sdt:sdt_subroutine;is_inlined_subroutine_sdt_parents:sdt_subroutinelist;is_name:string;is_call_file:unpacked_file_entry;is_call_line:Nat_big_num.num;is_pc_ranges:(Nat_big_num.num*Nat_big_num.num)list;is_const_params:inlined_subroutine_const_paramlist;}(* ignoring the nesting structure of inlined subroutines for now *)typeinlined_subroutine_data=inlined_subroutinelisttypeinlined_subroutine_data_by_range_entry=(Nat_big_num.num*Nat_big_num.num)(*range*)*(Nat_big_num.num*Nat_big_num.num)(*range m-of-n*)*inlined_subroutinetypeinlined_subroutine_data_by_range=inlined_subroutine_data_by_range_entrylist(*type inlined_subroutine_data_at_pc = list ((compilation_unit * (list die) * die) * (natural * natural * single_location_description * error single_location))*)(** ************************************************************ *)(** ** missing pervasives ************************************ *)(** ************************************************************ *)(* natural version of List.index *)(*val index_natural : forall 'a. list 'a -> natural -> maybe 'a*)letrecindex_naturalln:'aoption=((matchlwith|[]->None|x::xs->ifNat_big_num.equaln((Nat_big_num.of_int0))thenSomexelseindex_naturalxs(Nat_big_num.sub_natn((Nat_big_num.of_int1)))))letpartialNaturalFromInteger(i:Nat_big_num.num):Nat_big_num.num=(ifNat_big_num.lessi((Nat_big_num.of_int0))thenfailwith"partialNaturalFromInteger"elseNat_big_num.absi)(*val natural_nat_shift_left : natural -> nat -> natural*)(*val natural_nat_shift_right : natural -> nat -> natural*)(** ************************************************************ *)(** ** endianness *************************************** *)(** ************************************************************ *)letp_context_of_d(d:dwarf):p_context=({endianness=(d.d_endianness)})(** ************************************************************ *)(** ** dwarf encodings *************************************** *)(** ************************************************************ *)(* these encoding tables are pasted from the DWARF 4 specification *)(* tag encoding *)lettag_encodings:(string*Nat_big_num.num)list=([("DW_TAG_array_type",natural_of_hex"0x01");("DW_TAG_class_type",natural_of_hex"0x02");("DW_TAG_entry_point",natural_of_hex"0x03");("DW_TAG_enumeration_type",natural_of_hex"0x04");("DW_TAG_formal_parameter",natural_of_hex"0x05");("DW_TAG_imported_declaration",natural_of_hex"0x08");("DW_TAG_label",natural_of_hex"0x0a");("DW_TAG_lexical_block",natural_of_hex"0x0b");("DW_TAG_member",natural_of_hex"0x0d");("DW_TAG_pointer_type",natural_of_hex"0x0f");("DW_TAG_reference_type",natural_of_hex"0x10");("DW_TAG_compile_unit",natural_of_hex"0x11");("DW_TAG_string_type",natural_of_hex"0x12");("DW_TAG_structure_type",natural_of_hex"0x13");("DW_TAG_subroutine_type",natural_of_hex"0x15");("DW_TAG_typedef",natural_of_hex"0x16");("DW_TAG_union_type",natural_of_hex"0x17");("DW_TAG_unspecified_parameters",natural_of_hex"0x18");("DW_TAG_variant",natural_of_hex"0x19");("DW_TAG_common_block",natural_of_hex"0x1a");("DW_TAG_common_inclusion",natural_of_hex"0x1b");("DW_TAG_inheritance",natural_of_hex"0x1c");("DW_TAG_inlined_subroutine",natural_of_hex"0x1d");("DW_TAG_module",natural_of_hex"0x1e");("DW_TAG_ptr_to_member_type",natural_of_hex"0x1f");("DW_TAG_set_type",natural_of_hex"0x20");("DW_TAG_subrange_type",natural_of_hex"0x21");("DW_TAG_with_stmt",natural_of_hex"0x22");("DW_TAG_access_declaration",natural_of_hex"0x23");("DW_TAG_base_type",natural_of_hex"0x24");("DW_TAG_catch_block",natural_of_hex"0x25");("DW_TAG_const_type",natural_of_hex"0x26");("DW_TAG_constant",natural_of_hex"0x27");("DW_TAG_enumerator",natural_of_hex"0x28");("DW_TAG_file_type",natural_of_hex"0x29");("DW_TAG_friend",natural_of_hex"0x2a");("DW_TAG_namelist",natural_of_hex"0x2b");("DW_TAG_namelist_item",natural_of_hex"0x2c");("DW_TAG_packed_type",natural_of_hex"0x2d");("DW_TAG_subprogram",natural_of_hex"0x2e");("DW_TAG_template_type_parameter",natural_of_hex"0x2f");("DW_TAG_template_value_parameter",natural_of_hex"0x30");("DW_TAG_thrown_type",natural_of_hex"0x31");("DW_TAG_try_block",natural_of_hex"0x32");("DW_TAG_variant_part",natural_of_hex"0x33");("DW_TAG_variable",natural_of_hex"0x34");("DW_TAG_volatile_type",natural_of_hex"0x35");("DW_TAG_dwarf_procedure",natural_of_hex"0x36");("DW_TAG_restrict_type",natural_of_hex"0x37");("DW_TAG_interface_type",natural_of_hex"0x38");("DW_TAG_namespace",natural_of_hex"0x39");("DW_TAG_imported_module",natural_of_hex"0x3a");("DW_TAG_unspecified_type",natural_of_hex"0x3b");("DW_TAG_partial_unit",natural_of_hex"0x3c");("DW_TAG_imported_unit",natural_of_hex"0x3d");("DW_TAG_condition",natural_of_hex"0x3f");("DW_TAG_shared_type",natural_of_hex"0x40");("DW_TAG_type_unit",natural_of_hex"0x41");("DW_TAG_rvalue_reference_type",natural_of_hex"0x42");("DW_TAG_template_alias",natural_of_hex"0x43");("DW_TAG_lo_user",natural_of_hex"0x4080");("DW_TAG_hi_user",natural_of_hex"0xffff")])(* child determination encoding *)letvDW_CHILDREN_no:Nat_big_num.num=(natural_of_hex"0x00")letvDW_CHILDREN_yes:Nat_big_num.num=(natural_of_hex"0x01")(* attribute encoding *)letattribute_encodings:(string*Nat_big_num.num*(dwarf_attribute_classes)list)list=([("DW_AT_sibling",natural_of_hex"0x01",[DWA_reference]);("DW_AT_location",natural_of_hex"0x02",[DWA_exprloc;DWA_loclistptr]);("DW_AT_name",natural_of_hex"0x03",[DWA_string]);("DW_AT_ordering",natural_of_hex"0x09",[DWA_constant]);("DW_AT_byte_size",natural_of_hex"0x0b",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_bit_offset",natural_of_hex"0x0c",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_bit_size",natural_of_hex"0x0d",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_stmt_list",natural_of_hex"0x10",[DWA_lineptr]);("DW_AT_low_pc",natural_of_hex"0x11",[DWA_address]);("DW_AT_high_pc",natural_of_hex"0x12",[DWA_address;DWA_constant]);("DW_AT_language",natural_of_hex"0x13",[DWA_constant]);("DW_AT_discr",natural_of_hex"0x15",[DWA_reference]);("DW_AT_discr_value",natural_of_hex"0x16",[DWA_constant]);("DW_AT_visibility",natural_of_hex"0x17",[DWA_constant]);("DW_AT_import",natural_of_hex"0x18",[DWA_reference]);("DW_AT_string_length",natural_of_hex"0x19",[DWA_exprloc;DWA_loclistptr]);("DW_AT_common_reference",natural_of_hex"0x1a",[DWA_reference]);("DW_AT_comp_dir",natural_of_hex"0x1b",[DWA_string]);("DW_AT_const_value",natural_of_hex"0x1c",[DWA_block;DWA_constant;DWA_string]);("DW_AT_containing_type",natural_of_hex"0x1d",[DWA_reference]);("DW_AT_default_value",natural_of_hex"0x1e",[DWA_reference]);("DW_AT_inline",natural_of_hex"0x20",[DWA_constant]);("DW_AT_is_optional",natural_of_hex"0x21",[DWA_flag]);("DW_AT_lower_bound",natural_of_hex"0x22",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_producer",natural_of_hex"0x25",[DWA_string]);("DW_AT_prototyped",natural_of_hex"0x27",[DWA_flag]);("DW_AT_return_addr",natural_of_hex"0x2a",[DWA_exprloc;DWA_loclistptr]);("DW_AT_start_scope",natural_of_hex"0x2c",[DWA_constant;DWA_rangelistptr]);("DW_AT_bit_stride",natural_of_hex"0x2e",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_upper_bound",natural_of_hex"0x2f",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_abstract_origin",natural_of_hex"0x31",[DWA_reference]);("DW_AT_accessibility",natural_of_hex"0x32",[DWA_constant]);("DW_AT_address_class",natural_of_hex"0x33",[DWA_constant]);("DW_AT_artificial",natural_of_hex"0x34",[DWA_flag]);("DW_AT_base_types",natural_of_hex"0x35",[DWA_reference]);("DW_AT_calling_convention",natural_of_hex"0x36",[DWA_constant]);("DW_AT_count",natural_of_hex"0x37",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_data_member_location",natural_of_hex"0x38",[DWA_constant;DWA_exprloc;DWA_loclistptr]);("DW_AT_decl_column",natural_of_hex"0x39",[DWA_constant]);("DW_AT_decl_file",natural_of_hex"0x3a",[DWA_constant]);("DW_AT_decl_line",natural_of_hex"0x3b",[DWA_constant]);("DW_AT_declaration",natural_of_hex"0x3c",[DWA_flag]);("DW_AT_discr_list",natural_of_hex"0x3d",[DWA_block]);("DW_AT_encoding",natural_of_hex"0x3e",[DWA_constant]);("DW_AT_external",natural_of_hex"0x3f",[DWA_flag]);("DW_AT_frame_base",natural_of_hex"0x40",[DWA_exprloc;DWA_loclistptr]);("DW_AT_friend",natural_of_hex"0x41",[DWA_reference]);("DW_AT_identifier_case",natural_of_hex"0x42",[DWA_constant]);("DW_AT_macro_info",natural_of_hex"0x43",[DWA_macptr]);("DW_AT_namelist_item",natural_of_hex"0x44",[DWA_reference]);("DW_AT_priority",natural_of_hex"0x45",[DWA_reference]);("DW_AT_segment",natural_of_hex"0x46",[DWA_exprloc;DWA_loclistptr]);("DW_AT_specification",natural_of_hex"0x47",[DWA_reference]);("DW_AT_static_link",natural_of_hex"0x48",[DWA_exprloc;DWA_loclistptr]);("DW_AT_type",natural_of_hex"0x49",[DWA_reference]);("DW_AT_use_location",natural_of_hex"0x4a",[DWA_exprloc;DWA_loclistptr]);("DW_AT_variable_parameter",natural_of_hex"0x4b",[DWA_flag]);("DW_AT_virtuality",natural_of_hex"0x4c",[DWA_constant]);("DW_AT_vtable_elem_location",natural_of_hex"0x4d",[DWA_exprloc;DWA_loclistptr]);("DW_AT_allocated",natural_of_hex"0x4e",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_associated",natural_of_hex"0x4f",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_data_location",natural_of_hex"0x50",[DWA_exprloc]);("DW_AT_byte_stride",natural_of_hex"0x51",[DWA_constant;DWA_exprloc;DWA_reference]);("DW_AT_entry_pc",natural_of_hex"0x52",[DWA_address]);("DW_AT_use_UTF8",natural_of_hex"0x53",[DWA_flag]);("DW_AT_extension",natural_of_hex"0x54",[DWA_reference]);("DW_AT_ranges",natural_of_hex"0x55",[DWA_rangelistptr]);("DW_AT_trampoline",natural_of_hex"0x56",[DWA_address;DWA_flag;DWA_reference;DWA_string]);("DW_AT_call_column",natural_of_hex"0x57",[DWA_constant]);("DW_AT_call_file",natural_of_hex"0x58",[DWA_constant]);("DW_AT_call_line",natural_of_hex"0x59",[DWA_constant]);("DW_AT_description",natural_of_hex"0x5a",[DWA_string]);("DW_AT_binary_scale",natural_of_hex"0x5b",[DWA_constant]);("DW_AT_decimal_scale",natural_of_hex"0x5c",[DWA_constant]);("DW_AT_small",natural_of_hex"0x5d",[DWA_reference]);("DW_AT_decimal_sign",natural_of_hex"0x5e",[DWA_constant]);("DW_AT_digit_count",natural_of_hex"0x5f",[DWA_constant]);("DW_AT_picture_string",natural_of_hex"0x60",[DWA_string]);("DW_AT_mutable",natural_of_hex"0x61",[DWA_flag]);("DW_AT_threads_scaled",natural_of_hex"0x62",[DWA_flag]);("DW_AT_explicit",natural_of_hex"0x63",[DWA_flag]);("DW_AT_object_pointer",natural_of_hex"0x64",[DWA_reference]);("DW_AT_endianity",natural_of_hex"0x65",[DWA_constant]);("DW_AT_elemental",natural_of_hex"0x66",[DWA_flag]);("DW_AT_pure",natural_of_hex"0x67",[DWA_flag]);("DW_AT_recursive",natural_of_hex"0x68",[DWA_flag]);("DW_AT_signature",natural_of_hex"0x69",[DWA_reference]);("DW_AT_main_subprogram",natural_of_hex"0x6a",[DWA_flag]);("DW_AT_data_bit_offset",natural_of_hex"0x6b",[DWA_constant]);("DW_AT_const_expr",natural_of_hex"0x6c",[DWA_flag]);("DW_AT_enum_class",natural_of_hex"0x6d",[DWA_flag]);("DW_AT_linkage_name",natural_of_hex"0x6e",[DWA_string]);(* DW_AT_noreturn is a gcc extension to support the C11 _Noreturn keyword*)("DW_AT_noreturn",natural_of_hex"0x87",[DWA_flag]);("DW_AT_alignment",natural_of_hex"0x88",[DWA_constant]);("DW_AT_lo_user",natural_of_hex"0x2000",[DWA_dash]);("DW_AT_hi_user",natural_of_hex"0x3fff",[DWA_dash])])(* attribute form encoding *)letattribute_form_encodings:(string*Nat_big_num.num*(dwarf_attribute_classes)list)list=([("DW_FORM_addr",natural_of_hex"0x01",[DWA_address]);("DW_FORM_block2",natural_of_hex"0x03",[DWA_block]);("DW_FORM_block4",natural_of_hex"0x04",[DWA_block]);("DW_FORM_data2",natural_of_hex"0x05",[DWA_constant]);("DW_FORM_data4",natural_of_hex"0x06",[DWA_constant]);("DW_FORM_data8",natural_of_hex"0x07",[DWA_constant]);("DW_FORM_string",natural_of_hex"0x08",[DWA_string]);("DW_FORM_block",natural_of_hex"0x09",[DWA_block]);("DW_FORM_block1",natural_of_hex"0x0a",[DWA_block]);("DW_FORM_data1",natural_of_hex"0x0b",[DWA_constant]);("DW_FORM_flag",natural_of_hex"0x0c",[DWA_flag]);("DW_FORM_sdata",natural_of_hex"0x0d",[DWA_constant]);("DW_FORM_strp",natural_of_hex"0x0e",[DWA_string]);("DW_FORM_udata",natural_of_hex"0x0f",[DWA_constant]);("DW_FORM_ref_addr",natural_of_hex"0x10",[DWA_reference]);("DW_FORM_ref1",natural_of_hex"0x11",[DWA_reference]);("DW_FORM_ref2",natural_of_hex"0x12",[DWA_reference]);("DW_FORM_ref4",natural_of_hex"0x13",[DWA_reference]);("DW_FORM_ref8",natural_of_hex"0x14",[DWA_reference]);("DW_FORM_ref_udata",natural_of_hex"0x15",[DWA_reference]);("DW_FORM_indirect",natural_of_hex"0x16",[DWA_7_5_3]);("DW_FORM_sec_offset",natural_of_hex"0x17",[DWA_lineptr;DWA_loclistptr;DWA_macptr;DWA_rangelistptr]);("DW_FORM_exprloc",natural_of_hex"0x18",[DWA_exprloc]);("DW_FORM_flag_present",natural_of_hex"0x19",[DWA_flag]);("DW_FORM_ref_sig8",natural_of_hex"0x20",[DWA_reference])])(* operation encoding *)letoperation_encodings:(string*Nat_big_num.num*(operation_argument_type)list*operation_semantics)list=([("DW_OP_addr",natural_of_hex"0x03",[OAT_addr],OpSem_lit);(*1*)(*constant address (size target specific)*)("DW_OP_deref",natural_of_hex"0x06",[],OpSem_deref);(*0*)("DW_OP_const1u",natural_of_hex"0x08",[OAT_uint8],OpSem_lit);(*1*)(* 1-byte constant *)("DW_OP_const1s",natural_of_hex"0x09",[OAT_sint8],OpSem_lit);(*1*)(* 1-byte constant *)("DW_OP_const2u",natural_of_hex"0x0a",[OAT_uint16],OpSem_lit);(*1*)(* 2-byte constant *)("DW_OP_const2s",natural_of_hex"0x0b",[OAT_sint16],OpSem_lit);(*1*)(* 2-byte constant *)("DW_OP_const4u",natural_of_hex"0x0c",[OAT_uint32],OpSem_lit);(*1*)(* 4-byte constant *)("DW_OP_const4s",natural_of_hex"0x0d",[OAT_sint32],OpSem_lit);(*1*)(* 4-byte constant *)("DW_OP_const8u",natural_of_hex"0x0e",[OAT_uint64],OpSem_lit);(*1*)(* 8-byte constant *)("DW_OP_const8s",natural_of_hex"0x0f",[OAT_sint64],OpSem_lit);(*1*)(* 8-byte constant *)("DW_OP_constu",natural_of_hex"0x10",[OAT_ULEB128],OpSem_lit);(*1*)(* ULEB128 constant *)("DW_OP_consts",natural_of_hex"0x11",[OAT_SLEB128],OpSem_lit);(*1*)(* SLEB128 constant *)("DW_OP_dup",natural_of_hex"0x12",[],OpSem_stack(funacvsargs->(matchvswithv::vs->Some(v::(v::vs))|_->None)));(*0*)("DW_OP_drop",natural_of_hex"0x13",[],OpSem_stack(funacvsargs->(matchvswithv::vs->Somevs|_->None)));(*0*)("DW_OP_over",natural_of_hex"0x14",[],OpSem_stack(funacvsargs->(matchvswithv::v'::vs->Some(v'::(v::(v'::vs)))|_->None)));(*0*)("DW_OP_pick",natural_of_hex"0x15",[OAT_uint8],OpSem_stack(funacvsargs->(matchargswith[OAV_naturaln]->(matchindex_naturalvsnwithSomev->Some(v::vs)|None->None)|_->None)));(*1*)(* 1-byte stack index *)("DW_OP_swap",natural_of_hex"0x16",[],OpSem_stack(funacvsargs->(matchvswithv::v'::vs->Some(v'::(v::vs))|_->None)));(*0*)("DW_OP_rot",natural_of_hex"0x17",[],OpSem_stack(funacvsargs->(matchvswithv::v'::v''::vs->Some(v'::(v''::(v::vs)))|_->None)));(*0*)("DW_OP_xderef",natural_of_hex"0x18",[],OpSem_not_supported);(*0*)("DW_OP_abs",natural_of_hex"0x19",[],OpSem_unary(funacv->ifNat_big_num.lessvac.ac_halfthenSomevelseifNat_big_num.equalvac.ac_maxthenNoneelseSome(Nat_big_num.sub_natac.ac_allv)));(*0*)("DW_OP_and",natural_of_hex"0x1a",[],OpSem_binary(funacv1v2->Some(Nat_big_num.bitwise_andv1v2)));(*0*)("DW_OP_div",natural_of_hex"0x1b",[],OpSem_not_supported)(*TODO*);(*0*)("DW_OP_minus",natural_of_hex"0x1c",[],OpSem_binary(funacv1v2->Some(partialNaturalFromInteger(Nat_big_num.modulus(Nat_big_num.sub(v1)(v2))(ac.ac_all)))));(*0*)("DW_OP_mod",natural_of_hex"0x1d",[],OpSem_binary(funacv1v2->Some(Nat_big_num.modulusv1v2)));(*0*)("DW_OP_mul",natural_of_hex"0x1e",[],OpSem_binary(funacv1v2->Some(partialNaturalFromInteger(Nat_big_num.modulus(Nat_big_num.mul(v1)(v2))(ac.ac_all)))));(*0*)("DW_OP_neg",natural_of_hex"0x1f",[],OpSem_unary(funacv->ifNat_big_num.lessvac.ac_halfthenSome(Nat_big_num.sub_natac.ac_maxv)elseifNat_big_num.equalvac.ac_halfthenNoneelseSome(Nat_big_num.sub_natac.ac_allv)));(*0*)("DW_OP_not",natural_of_hex"0x20",[],OpSem_unary(funacv->Some(Nat_big_num.bitwise_xorvac.ac_max)));(*0*)("DW_OP_or",natural_of_hex"0x21",[],OpSem_binary(funacv1v2->Some(Nat_big_num.bitwise_orv1v2)));(*0*)("DW_OP_plus",natural_of_hex"0x22",[],OpSem_binary(funacv1v2->Some(Nat_big_num.modulus(Nat_big_num.addv1v2)ac.ac_all)));(*0*)("DW_OP_plus_uconst",natural_of_hex"0x23",[OAT_ULEB128],OpSem_stack(funacvsargs->(matchargswith[OAV_naturaln]->(matchvswithv::vs'->letv'=(Nat_big_num.modulus(Nat_big_num.addvn)ac.ac_all)inSome(v'::vs)|[]->None)|_->None)));(*1*)(* ULEB128 addend *)("DW_OP_shl",natural_of_hex"0x24",[],OpSem_binary(funacv1v2->ifNat_big_num.greater_equalv2ac.ac_bitwidththenSome((Nat_big_num.of_int0))elseSome(Nat_big_num.shift_leftv1(Nat_big_num.to_intv2))));(*0*)("DW_OP_shr",natural_of_hex"0x25",[],OpSem_binary(funacv1v2->ifNat_big_num.greater_equalv2ac.ac_bitwidththenSome((Nat_big_num.of_int0))elseSome(Nat_big_num.shift_rightv1(Nat_big_num.to_intv2))));(*0*)("DW_OP_shra",natural_of_hex"0x26",[],OpSem_binary(funacv1v2->ifNat_big_num.lessv1ac.ac_halfthen(ifNat_big_num.greater_equalv2ac.ac_bitwidththenSome((Nat_big_num.of_int0))elseSome(Nat_big_num.shift_rightv1(Nat_big_num.to_intv2)))else(ifNat_big_num.greater_equalv2ac.ac_bitwidththenSomeac.ac_maxelseSome(Nat_big_num.sub_natac.ac_max(Nat_big_num.shift_right(Nat_big_num.sub_natac.ac_maxv1)(Nat_big_num.to_intv2))))));(*0*)("DW_OP_xor",natural_of_hex"0x27",[],OpSem_binary(funacv1v2->Some(Nat_big_num.bitwise_xorv1v2)));(*0*)("DW_OP_skip",natural_of_hex"0x2f",[OAT_sint16],OpSem_not_supported);(*1*)(* signed 2-byte constant *)("DW_OP_bra",natural_of_hex"0x28",[OAT_sint16],OpSem_not_supported);(*1*)(* signed 2-byte constant *)("DW_OP_eq",natural_of_hex"0x29",[],OpSem_not_supported);(*0*)("DW_OP_ge",natural_of_hex"0x2a",[],OpSem_not_supported);(*0*)("DW_OP_gt",natural_of_hex"0x2b",[],OpSem_not_supported);(*0*)("DW_OP_le",natural_of_hex"0x2c",[],OpSem_not_supported);(*0*)("DW_OP_lt",natural_of_hex"0x2d",[],OpSem_not_supported);(*0*)("DW_OP_ne",natural_of_hex"0x2e",[],OpSem_not_supported);(*0*)("DW_OP_lit0",natural_of_hex"0x30",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)(* literals 0..31 =(DW_OP_lit0 + literal) *)("DW_OP_lit1",natural_of_hex"0x31",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit2",natural_of_hex"0x32",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit3",natural_of_hex"0x33",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit4",natural_of_hex"0x34",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit5",natural_of_hex"0x35",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit6",natural_of_hex"0x36",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit7",natural_of_hex"0x37",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit8",natural_of_hex"0x38",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit9",natural_of_hex"0x39",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit10",natural_of_hex"0x3a",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit11",natural_of_hex"0x3b",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit12",natural_of_hex"0x3c",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit13",natural_of_hex"0x3d",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit14",natural_of_hex"0x3e",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit15",natural_of_hex"0x3f",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit16",natural_of_hex"0x40",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit17",natural_of_hex"0x41",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit18",natural_of_hex"0x42",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit19",natural_of_hex"0x43",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit20",natural_of_hex"0x44",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit21",natural_of_hex"0x45",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit22",natural_of_hex"0x46",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit23",natural_of_hex"0x47",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit24",natural_of_hex"0x48",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit25",natural_of_hex"0x49",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit26",natural_of_hex"0x4a",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit27",natural_of_hex"0x4b",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit28",natural_of_hex"0x4c",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit29",natural_of_hex"0x4d",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit30",natural_of_hex"0x4e",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_lit31",natural_of_hex"0x4f",[],OpSem_opcode_lit(natural_of_hex"0x30"));(*0*)("DW_OP_reg0",natural_of_hex"0x50",[],OpSem_reg);(*1*)(* reg 0..31 = (DW_OP_reg0 + regnum) *)("DW_OP_reg1",natural_of_hex"0x51",[],OpSem_reg);(*1*)("DW_OP_reg2",natural_of_hex"0x52",[],OpSem_reg);(*1*)("DW_OP_reg3",natural_of_hex"0x53",[],OpSem_reg);(*1*)("DW_OP_reg4",natural_of_hex"0x54",[],OpSem_reg);(*1*)("DW_OP_reg5",natural_of_hex"0x55",[],OpSem_reg);(*1*)("DW_OP_reg6",natural_of_hex"0x56",[],OpSem_reg);(*1*)("DW_OP_reg7",natural_of_hex"0x57",[],OpSem_reg);(*1*)("DW_OP_reg8",natural_of_hex"0x58",[],OpSem_reg);(*1*)("DW_OP_reg9",natural_of_hex"0x59",[],OpSem_reg);(*1*)("DW_OP_reg10",natural_of_hex"0x5a",[],OpSem_reg);(*1*)("DW_OP_reg11",natural_of_hex"0x5b",[],OpSem_reg);(*1*)("DW_OP_reg12",natural_of_hex"0x5c",[],OpSem_reg);(*1*)("DW_OP_reg13",natural_of_hex"0x5d",[],OpSem_reg);(*1*)("DW_OP_reg14",natural_of_hex"0x5e",[],OpSem_reg);(*1*)("DW_OP_reg15",natural_of_hex"0x5f",[],OpSem_reg);(*1*)("DW_OP_reg16",natural_of_hex"0x60",[],OpSem_reg);(*1*)("DW_OP_reg17",natural_of_hex"0x61",[],OpSem_reg);(*1*)("DW_OP_reg18",natural_of_hex"0x62",[],OpSem_reg);(*1*)("DW_OP_reg19",natural_of_hex"0x63",[],OpSem_reg);(*1*)("DW_OP_reg20",natural_of_hex"0x64",[],OpSem_reg);(*1*)("DW_OP_reg21",natural_of_hex"0x65",[],OpSem_reg);(*1*)("DW_OP_reg22",natural_of_hex"0x66",[],OpSem_reg);(*1*)("DW_OP_reg23",natural_of_hex"0x67",[],OpSem_reg);(*1*)("DW_OP_reg24",natural_of_hex"0x68",[],OpSem_reg);(*1*)("DW_OP_reg25",natural_of_hex"0x69",[],OpSem_reg);(*1*)("DW_OP_reg26",natural_of_hex"0x6a",[],OpSem_reg);(*1*)("DW_OP_reg27",natural_of_hex"0x6b",[],OpSem_reg);(*1*)("DW_OP_reg28",natural_of_hex"0x6c",[],OpSem_reg);(*1*)("DW_OP_reg29",natural_of_hex"0x6d",[],OpSem_reg);(*1*)("DW_OP_reg30",natural_of_hex"0x6e",[],OpSem_reg);(*1*)("DW_OP_reg31",natural_of_hex"0x6f",[],OpSem_reg);(*1*)("DW_OP_breg0",natural_of_hex"0x70",[OAT_SLEB128],OpSem_breg);(*1*)(* base register 0..31 = (DW_OP_breg0 + regnum) *)("DW_OP_breg1",natural_of_hex"0x71",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg2",natural_of_hex"0x72",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg3",natural_of_hex"0x73",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg4",natural_of_hex"0x74",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg5",natural_of_hex"0x75",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg6",natural_of_hex"0x76",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg7",natural_of_hex"0x77",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg8",natural_of_hex"0x78",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg9",natural_of_hex"0x79",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg10",natural_of_hex"0x7a",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg11",natural_of_hex"0x7b",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg12",natural_of_hex"0x7c",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg13",natural_of_hex"0x7d",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg14",natural_of_hex"0x7e",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg15",natural_of_hex"0x7f",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg16",natural_of_hex"0x80",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg17",natural_of_hex"0x81",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg18",natural_of_hex"0x82",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg19",natural_of_hex"0x83",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg20",natural_of_hex"0x84",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg21",natural_of_hex"0x85",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg22",natural_of_hex"0x86",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg23",natural_of_hex"0x87",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg24",natural_of_hex"0x88",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg25",natural_of_hex"0x89",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg26",natural_of_hex"0x8a",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg27",natural_of_hex"0x8b",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg28",natural_of_hex"0x8c",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg29",natural_of_hex"0x8d",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg30",natural_of_hex"0x8e",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_breg31",natural_of_hex"0x8f",[OAT_SLEB128],OpSem_breg);(*1*)("DW_OP_regx",natural_of_hex"0x90",[OAT_ULEB128],OpSem_lit);(*1*)(* ULEB128 register *)("DW_OP_fbreg",natural_of_hex"0x91",[OAT_SLEB128],OpSem_fbreg);(*1*)(* SLEB128 offset *)("DW_OP_bregx",natural_of_hex"0x92",[OAT_ULEB128;OAT_SLEB128],OpSem_bregx);(*2*)(* ULEB128 register followed by SLEB128 offset *)("DW_OP_piece",natural_of_hex"0x93",[OAT_ULEB128],OpSem_piece);(*1*)(* ULEB128 size of piece addressed *)("DW_OP_deref_size",natural_of_hex"0x94",[OAT_uint8],OpSem_deref_size);(*1*)(* 1-byte size of data retrieved *)("DW_OP_xderef_size",natural_of_hex"0x95",[OAT_uint8],OpSem_not_supported);(*1*)(* 1-byte size of data retrieved *)("DW_OP_nop",natural_of_hex"0x96",[],OpSem_nop);(*0*)("DW_OP_push_object_address",natural_of_hex"0x97",[],OpSem_not_supported);(*0*)("DW_OP_call2",natural_of_hex"0x98",[OAT_uint16],OpSem_not_supported);(*1*)(* 2-byte offset of DIE *)("DW_OP_call4",natural_of_hex"0x99",[OAT_uint32],OpSem_not_supported);(*1*)(* 4-byte offset of DIE *)("DW_OP_call_ref",natural_of_hex"0x9a",[OAT_dwarf_format_t],OpSem_not_supported);(*1*)(* 4- or 8-byte offset of DIE *)("DW_OP_form_tls_address",natural_of_hex"0x9b",[],OpSem_not_supported);(*0*)("DW_OP_call_frame_cfa",natural_of_hex"0x9c",[],OpSem_call_frame_cfa);(*0*)("DW_OP_bit_piece",natural_of_hex"0x9d",[OAT_ULEB128;OAT_ULEB128],OpSem_bit_piece);(*2*)(* ULEB128 size followed by ULEB128 offset *)("DW_OP_implicit_value",natural_of_hex"0x9e",[OAT_block],OpSem_implicit_value);(*2*)(* ULEB128 size followed by block of that size *)("DW_OP_stack_value",natural_of_hex"0x9f",[],OpSem_stack_value);(*0*)(* these aren't real operations
("DW_OP_lo_user", natural_of_hex "0xe0", [] , );
("DW_OP_hi_user", natural_of_hex "0xff", [] , );
*)(* GCC also produces these for our example:
https://fedorahosted.org/elfutils/wiki/DwarfExtensions
http://dwarfstd.org/ShowIssue.php?issue=100909.1 *)("DW_GNU_OP_entry_value",natural_of_hex"0xf3",[OAT_block],OpSem_not_supported);(*2*)(* ULEB128 size followed by DWARF expression block of that size*)("DW_OP_GNU_implicit_pointer",natural_of_hex"0xf2",[OAT_dwarf_format_t;OAT_SLEB128],OpSem_not_supported)])letvDW_OP_reg0:Nat_big_num.num=(natural_of_hex"0x50")letvDW_OP_breg0:Nat_big_num.num=(natural_of_hex"0x70")(* call frame instruction encoding *)letcall_frame_instruction_encoding:(string*Nat_big_num.num*Nat_big_num.num*call_frame_argument_typelist*((call_frame_argument_valuelist)->call_frame_instructionoption))list=([(* high-order 2 bits low-order 6 bits uniformly parsed arguments *)(* instructions using low-order 6 bits for first argument *)(*
("DW_CFA_advance_loc", 1, 0,(*delta *) []);
("DW_CFA_offset", 2, 0,(*register*) [CFAT_offset]);
("DW_CFA_restore", 3, 0,(*register*) []);
*)(* instructions using low-order 6 bits as part of opcode *)("DW_CFA_nop",(Nat_big_num.of_int0),natural_of_hex"0x00",[],((* *)funavs->(matchavswith[]->Some(DW_CFA_nop)|_->None)));("DW_CFA_set_loc",(Nat_big_num.of_int0),natural_of_hex"0x01",[CFAT_address],((* address *)funavs->(matchavswith[CFAV_addressa]->Some(DW_CFA_set_loca)|_->None)));("DW_CFA_advance_loc1",(Nat_big_num.of_int0),natural_of_hex"0x02",[CFAT_delta1],((* 1-byte delta *)funavs->(matchavswith[CFAV_deltad]->Some(DW_CFA_advance_loc1d)|_->None)));("DW_CFA_advance_loc2",(Nat_big_num.of_int0),natural_of_hex"0x03",[CFAT_delta2],((* 2-byte delta *)funavs->(matchavswith[CFAV_deltad]->Some(DW_CFA_advance_loc2d)|_->None)));("DW_CFA_advance_loc4",(Nat_big_num.of_int0),natural_of_hex"0x04",[CFAT_delta4],((* 4-byte delta *)funavs->(matchavswith[CFAV_deltad]->Some(DW_CFA_advance_loc4d)|_->None)));("DW_CFA_offset_extended",(Nat_big_num.of_int0),natural_of_hex"0x05",[CFAT_register;CFAT_offset],((* ULEB128 register ULEB128 offset *)funavs->(matchavswith[CFAV_registerr;CFAV_offsetn]->Some(DW_CFA_offset_extended(r,n))|_->None)));("DW_CFA_restore_extended",(Nat_big_num.of_int0),natural_of_hex"0x06",[CFAT_register],((* ULEB128 register *)funavs->(matchavswith[CFAV_registerr]->Some(DW_CFA_restore_extendedr)|_->None)));("DW_CFA_undefined",(Nat_big_num.of_int0),natural_of_hex"0x07",[CFAT_register],((* ULEB128 register *)funavs->(matchavswith[CFAV_registerr]->Some(DW_CFA_undefinedr)|_->None)));("DW_CFA_same_value",(Nat_big_num.of_int0),natural_of_hex"0x08",[CFAT_register],((* ULEB128 register *)funavs->(matchavswith[CFAV_registerr]->Some(DW_CFA_same_valuer)|_->None)));("DW_CFA_register",(Nat_big_num.of_int0),natural_of_hex"0x09",[CFAT_register;CFAT_register],((* ULEB128 register ULEB128 register *)funavs->(matchavswith[CFAV_registerr1;CFAV_registerr2]->Some(DW_CFA_register(r1,r2))|_->None)));("DW_CFA_remember_state",(Nat_big_num.of_int0),natural_of_hex"0x0a",[],((* *)funavs->(matchavswith[]->Some(DW_CFA_remember_state)|_->None)));("DW_CFA_restore_state",(Nat_big_num.of_int0),natural_of_hex"0x0b",[],((* *)funavs->(matchavswith[]->Some(DW_CFA_restore_state)|_->None)));("DW_CFA_def_cfa",(Nat_big_num.of_int0),natural_of_hex"0x0c",[CFAT_register;CFAT_offset],((* ULEB128 register ULEB128 offset *)funavs->(matchavswith[CFAV_registerr;CFAV_offsetn]->Some(DW_CFA_def_cfa(r,n))|_->None)));("DW_CFA_def_cfa_register",(Nat_big_num.of_int0),natural_of_hex"0x0d",[CFAT_register],((* ULEB128 register *)funavs->(matchavswith[CFAV_registerr]->Some(DW_CFA_def_cfa_registerr)|_->None)));("DW_CFA_def_cfa_offset",(Nat_big_num.of_int0),natural_of_hex"0x0e",[CFAT_offset],((* ULEB128 offset *)funavs->(matchavswith[CFAV_offsetn]->Some(DW_CFA_def_cfa_offsetn)|_->None)));("DW_CFA_def_cfa_expression",(Nat_big_num.of_int0),natural_of_hex"0x0f",[CFAT_block],((* BLOCK *)funavs->(matchavswith[CFAV_blockb]->Some(DW_CFA_def_cfa_expressionb)|_->None)));("DW_CFA_expression",(Nat_big_num.of_int0),natural_of_hex"0x10",[CFAT_register;CFAT_block],((* ULEB128 register BLOCK *)funavs->(matchavswith[CFAV_registerr;CFAV_blockb]->Some(DW_CFA_expression(r,b))|_->None)));("DW_CFA_offset_extended_sf",(Nat_big_num.of_int0),natural_of_hex"0x11",[CFAT_register;CFAT_sfoffset],((* ULEB128 register SLEB128 offset *)funavs->(matchavswith[CFAV_registerr;CFAV_sfoffseti]->Some(DW_CFA_offset_extended_sf(r,i))|_->None)));("DW_CFA_def_cfa_sf",(Nat_big_num.of_int0),natural_of_hex"0x12",[CFAT_register;CFAT_sfoffset],((* ULEB128 register SLEB128 offset *)funavs->(matchavswith[CFAV_registerr;CFAV_sfoffseti]->Some(DW_CFA_def_cfa_sf(r,i))|_->None)));("DW_CFA_def_cfa_offset_sf",(Nat_big_num.of_int0),natural_of_hex"0x13",[CFAT_sfoffset],((* SLEB128 offset *)funavs->(matchavswith[CFAV_sfoffseti]->Some(DW_CFA_def_cfa_offset_sfi)|_->None)));("DW_CFA_val_offset",(Nat_big_num.of_int0),natural_of_hex"0x14",[CFAT_register;CFAT_offset],((* ULEB128 ULEB128 *)funavs->(matchavswith[CFAV_registerr;CFAV_offsetn]->Some(DW_CFA_val_offset(r,n))|_->None)));("DW_CFA_val_offset_sf",(Nat_big_num.of_int0),natural_of_hex"0x15",[CFAT_register;CFAT_sfoffset],((* ULEB128 SLEB128 *)funavs->(matchavswith[CFAV_registerr;CFAV_sfoffseti]->Some(DW_CFA_val_offset_sf(r,i))|_->None)));("DW_CFA_val_expression",(Nat_big_num.of_int0),natural_of_hex"0x16",[CFAT_register;CFAT_block],((* ULEB128 BLOCK *)funavs->(matchavswith[CFAV_registerr;CFAV_blockb]->Some(DW_CFA_val_expression(r,b))|_->None)));("DW_CFA_AARCH64_negate_ra_state",(Nat_big_num.of_int0),natural_of_hex"0x2d",[],((* *)funavs->(matchavswith[]->Some(DW_CFA_AARCH64_negate_ra_state)|_->None)));])(*
0x2d DW_CFA_GNU_window_save is listed in https://sourceware.org/elfutils/DwarfExtensions as "magic shorthand used only by SPARC"
https://elixir.bootlin.com/linux/v4.0/source/arch/arc/kernel/unwind.c#L842 no-ops it
https://refspecs.linuxbase.org/LSB_3.0.0/LSB-PDA/LSB-PDA/dwarfext.html doesn't mention it
https://github.com/gcc-mirror/gcc/blob/master/libgcc/unwind-dw2.c#L1189 says
"This CFA is multiplexed with Sparc. On AArch64 it's used to toggle return address signing status."
fs->regs.reg[DWARF_REGNUM_AARCH64_RA_STATE].loc.offset ^= 1;
https://developer.arm.com/docs/ihi0057/c/dwarf-for-the-arm-64-bit-architecture-aarch64-abi-2018q4 "DWARF for the Arm® 64-bit Architecture (AArch64) - ABI 2018Q4"
calls this "DW_CFA_AARCH64_negate_ra_state"
"The DW_CFA_AARCH64_negate_ra_state operation negates bit[0] of the RA_SIGN_STATE pseudo-register. It does not take any operands."
p10 says "The RA_SIGN_STATE pseudo-register records whether the return address has been signed with aPAC. This information can be used when unwinding. It is an unsigned integer with the same sizeas a general register. Only bit[0] is meaningful and is initialized to zero. A value of 0 indicates the return address has not been signed. A value of 1 indicates the return address has been signed"
For our purposes it seems fine to nop-this.
*)(*
("DW_CFA_lo_user", 0, natural_of_hex "0x1c", []); (* *)
("DW_CFA_hi_user", 0, natural_of_hex "0x3f", []); (* *)
*)(* line number encodings *)letline_number_standard_encodings:(string*Nat_big_num.num*(line_number_argument_type)list*((line_number_argument_value)list->(line_number_operation)option))list=([("DW_LNS_copy",natural_of_hex"0x01",[],(funlnvs->(matchlnvswith[]->SomeDW_LNS_copy|_->None)));("DW_LNS_advance_pc",natural_of_hex"0x02",[LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_ULEB128n]->Some(DW_LNS_advance_pcn)|_->None)));("DW_LNS_advance_line",natural_of_hex"0x03",[LNAT_SLEB128],(funlnvs->(matchlnvswith[LNAV_SLEB128i]->Some(DW_LNS_advance_linei)|_->None)));("DW_LNS_set_file",natural_of_hex"0x04",[LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_ULEB128n]->Some(DW_LNS_set_filen)|_->None)));("DW_LNS_set_column",natural_of_hex"0x05",[LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_ULEB128n]->Some(DW_LNS_set_columnn)|_->None)));("DW_LNS_negate_stmt",natural_of_hex"0x06",[],(funlnvs->(matchlnvswith[]->Some(DW_LNS_negate_stmt)|_->None)));("DW_LNS_set_basic_block",natural_of_hex"0x07",[],(funlnvs->(matchlnvswith[]->Some(DW_LNS_set_basic_block)|_->None)));("DW_LNS_const_add_pc",natural_of_hex"0x08",[],(funlnvs->(matchlnvswith[]->Some(DW_LNS_const_add_pc)|_->None)));("DW_LNS_fixed_advance_pc",natural_of_hex"0x09",[LNAT_uint16],(funlnvs->(matchlnvswith[LNAV_uint16n]->Some(DW_LNS_fixed_advance_pcn)|_->None)));("DW_LNS_set_prologue_end",natural_of_hex"0x0a",[],(funlnvs->(matchlnvswith[]->Some(DW_LNS_set_prologue_end)|_->None)));("DW_LNS_set_epilogue_begin",natural_of_hex"0x0b",[],(funlnvs->(matchlnvswith[]->Some(DW_LNS_set_epilogue_begin)|_->None)));("DW_LNS_set_isa",natural_of_hex"0x0c",[LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_ULEB128n]->Some(DW_LNS_set_isan)|_->None)))])letline_number_extended_encodings:(string*Nat_big_num.num*(line_number_argument_type)list*((line_number_argument_value)list->(line_number_operation)option))list=([("DW_LNE_end_sequence",natural_of_hex"0x01",[],(funlnvs->(matchlnvswith[]->Some(DW_LNE_end_sequence)|_->None)));("DW_LNE_set_address",natural_of_hex"0x02",[LNAT_address],(funlnvs->(matchlnvswith[LNAV_addressn]->Some(DW_LNE_set_addressn)|_->None)));("DW_LNE_define_file",natural_of_hex"0x03",[LNAT_string;LNAT_ULEB128;LNAT_ULEB128;LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_strings;LNAV_ULEB128n1;LNAV_ULEB128n2;LNAV_ULEB128n3]->Some(DW_LNE_define_file(s,n1,n2,n3))|_->None)));("DW_LNE_set_discriminator",natural_of_hex"0x04",[LNAT_ULEB128],(funlnvs->(matchlnvswith[LNAV_ULEB128n]->Some(DW_LNE_set_discriminatorn)|_->None)))(* new in Dwarf 4*)])(*
(DW_LNE_lo_user , natural_of_hex "0x80", "DW_LNE_lo_user");
(DW_LNE_hi_user , natural_of_hex "0xff", "DW_LNE_hi_user");
*)(* booleans encoded as a single byte containing the value 0 for âfalse,â and a non-zero value for âtrue.â *)(* base type attribute encoding *)letbase_type_attribute_encodings:(string*Nat_big_num.num)list=([("DW_ATE_address",natural_of_hex"0x01");("DW_ATE_boolean",natural_of_hex"0x02");("DW_ATE_complex_float",natural_of_hex"0x03");("DW_ATE_float",natural_of_hex"0x04");("DW_ATE_signed",natural_of_hex"0x05");("DW_ATE_signed_char",natural_of_hex"0x06");("DW_ATE_unsigned",natural_of_hex"0x07");("DW_ATE_unsigned_char",natural_of_hex"0x08");("DW_ATE_imaginary_float",natural_of_hex"0x09");("DW_ATE_packed_decimal",natural_of_hex"0x0a");("DW_ATE_numeric_string",natural_of_hex"0x0b");("DW_ATE_edited",natural_of_hex"0x0c");("DW_ATE_signed_fixed",natural_of_hex"0x0d");("DW_ATE_unsigned_fixed",natural_of_hex"0x0e");("DW_ATE_decimal_float",natural_of_hex"0x0f");("DW_ATE_UTF",natural_of_hex"0x10");("DW_ATE_lo_user",natural_of_hex"0x80");("DW_ATE_signed_capability_hack_a0",natural_of_hex"0xa0");("DW_ATE_unsigned_capability_hack_a1",natural_of_hex"0xa1");("DW_ATE_hi_user",natural_of_hex"0xff")])(** ************************************************************ *)(** ** more missing pervasives and bits *********************** *)(** ************************************************************ *)(* quick hacky workaround: this is in String.lem, in src_lem_library, but the linker doesn't find it *)(*val myconcat : string -> list string -> string*)letrecmyconcatsepss:string=((matchsswith|[]->""|s::ss'->(matchss'with|[]->s|_->s^(sep^myconcatsepss'))))(*val myhead : forall 'a. list 'a -> 'a*)letmyheadl:'a=((matchlwith|x::xs->x|[]->failwith"myhead of empty list"))(*val myfindNonPure : forall 'a. ('a -> bool) -> list 'a -> 'a*)letmyfindNonPurep0l:'a=((match(Lem_list.list_find_optp0l)with|Somee->e|None->failwith"myfindNonPure"))(*val myfindmaybe : forall 'a 'b. ('a -> maybe 'b) -> list 'a -> maybe 'b*)letrecmyfindmaybefxs:'boption=((matchxswith|[]->None|x::xs'->(matchfxwithSomey->Somey|None->myfindmaybefxs')))(*val myfind : forall 'a. ('a -> bool) -> list 'a -> maybe 'a*)letrecmyfindfxs:'aoption=((matchxswith|[]->None|x::xs'->(matchfxwithtrue->Somex|false->myfindfxs')))(*val myfiltermaybe : forall 'a 'b. ('a -> maybe 'b) -> list 'a -> list 'b*)letrecmyfiltermaybefxs:'blist=((matchxswith|[]->[]|x::xs'->(matchfxwithSomey->y::myfiltermaybefxs'|None->myfiltermaybefxs')))(*val bytes_of_natural: endianness -> natural (*size*) -> natural (*value*) -> byte_sequence*)letbytes_of_naturalensize2n:Byte_sequence_wrapper.byte_sequence=(byte_sequence_of_byte_list(ifNat_big_num.equalsize2((Nat_big_num.of_int8))thenbytes_of_elf64_xworden(Uint64_wrapper.of_bigintn)elseifNat_big_num.equalsize2((Nat_big_num.of_int4))thenbytes_of_elf32_worden(Uint32_wrapper.of_bigintn)elsefailwith"bytes_of_natural given size that is not 4 or 8"))letrecnatural_of_bytes_littlebs:Nat_big_num.num=((matchread_charbswith|Fail_->(Nat_big_num.of_int0)|Success(b,bs')->Nat_big_num.add(natural_of_byteb)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_bytes_littlebs'))))letrecnatural_of_bytes_bigaccbs:Nat_big_num.num=((matchread_charbswith|Fail_->acc|Success(b,bs')->natural_of_bytes_big(Nat_big_num.add(natural_of_byteb)(Nat_big_num.mul((Nat_big_num.of_int256))acc))bs'))(*val natural_of_bytes: endianness -> byte_sequence -> natural*)letnatural_of_bytesenbs:Nat_big_num.num=((matchenwith|Little->natural_of_bytes_littlebs|Big->natural_of_bytes_big((Nat_big_num.of_int0))bs))(* TODO: generalise *)(*
match bs with
| b0::b1::b2::b3::b4::b5::b6::b7::[] ->
let v = if en=Little then
natural_of_byte b0 + 256*natural_of_byte b1 + 256*256*natural_of_byte b2 + 256*256*256*natural_of_byte b3
+ (256*256*256*256*(natural_of_byte b4 + 256*natural_of_byte b5 + 256*256*natural_of_byte b6 + 256*256*256*natural_of_byte b7))
else
natural_of_byte b7 + 256*natural_of_byte b6 + 256*256*natural_of_byte b5 + 256*256*256*natural_of_byte b4
+ (256*256*256*256*(natural_of_byte b3 + 256*natural_of_byte b2 + 256*256*natural_of_byte b1 + 256*256*256*natural_of_byte b0))
in
v
| b0::b1::b2::b3::[] ->
let v = if en=Little then
natural_of_byte b0 + 256*natural_of_byte b1 + 256*256*natural_of_byte b2 + 256*256*256*natural_of_byte b3
else
natural_of_byte b3 + 256*natural_of_byte b2 + 256*256*natural_of_byte b1 + 256*256*256*natural_of_byte b0
in
v
| b0::b1::[] ->
let v = if en=Little then
natural_of_byte b0 + 256*natural_of_byte b1
else
natural_of_byte b1 + 256*natural_of_byte b0
in
v
| b0::[] ->
natural_of_byte b0
| _ -> Assert_extra.failwith "natural_of_bytes given not-8/4/2/1 bytes"
end
*)(*val bigunionListMap : forall 'a 'b. SetType 'b => ('a -> set 'b) -> list 'a -> set 'b*)letrecbigunionListMapdict_Basic_classes_SetType_bfxs:'bPset.set=((matchxswith|[]->(Pset.from_listdict_Basic_classes_SetType_b.setElemCompare_method[])|x::xs'->Pset.(union)(fx)(bigunionListMapdict_Basic_classes_SetType_bfxs')))letrecmytake'(n:Nat_big_num.num)accxs:('alist*'alist)option=(if(Nat_big_num.equaln((Nat_big_num.of_int0)))then(Some(List.revacc,xs))else((matchxswith[]->None|x::xs'->mytake'(Nat_big_num.sub_natn((Nat_big_num.of_int1)))(x::acc)xs')))(*val mytake : forall 'a. natural -> (list 'a) -> maybe (list 'a * list 'a)*)letmytakenxs:('alist*'alist)option=(mytake'n[]xs)(*val mynth : forall 'a. natural -> (list 'a) -> maybe 'a*)letrecmynth(n:Nat_big_num.num)xs:'aoption=((*Assert_extra.failwith "mynth"*)if(Nat_big_num.equaln((Nat_big_num.of_int0)))then((matchxswithx::xs'->Somex|[]->None))else((matchxswithx::xs'->mynth(Nat_big_num.sub_natn((Nat_big_num.of_int1)))xs')))(** basic pretty printing *)letpphexplainn:string=(unsafe_hex_string_of_natural0n)letpphexn:string=("0x"^pphexplainn)(*val abs : integer -> natural*)(*declare isabelle target_rep function abs = `int`
declare coq target_rep function abs n = (`Zpred` (`Zpos` (`P_of_succ_nat` n))) (* TODO: check*)
*)letpphex_integern:string=(ifNat_big_num.lessn((Nat_big_num.of_int0))then"-"^pphex(Nat_big_num.absn)elsepphex(Nat_big_num.absn))letppbytesbs:string=(string_of_listinstance_Show_Show_string_dict(Lem_list.map(funx->hex_string_of_bytex)(byte_list_of_byte_sequencebs)))letrecppbytes2nbs:string=((matchread_charbswith|Fail_->""|Success(x,xs')->"<"^(pphexn^("> "^(hex_string_of_bytex^("\n"^ppbytes2(Nat_big_num.addn((Nat_big_num.of_int1)))xs'))))))letrecppbytesplain(c:p_context)(n:Nat_big_num.num)bs:string=(Nat_big_num.to_string(natural_of_bytesc.endiannessbs))(*
unsafe_hex_string_of_uc_list (List.map unsigned_char_of_byte xs) (*match xs with | [] -> "" | x::xs' -> pphexplain x ^ ppbytesplain (n+1) xs' end*)
*)(* workaround: from String *)(*val mytoString : list char -> string*)letstring_of_bytesbs:string=(Xstring.implode(Lem_list.map(funx->x)bs))letjust_onesxs:'a=((matchxswith|[]->failwith("no "^s)|x1::x2::_->failwith("more than one "^s)|[x]->x))letmax_address(as':Nat_big_num.num):Nat_big_num.num=(if(Nat_big_num.equalas'((Nat_big_num.of_int4)))then(natural_of_hex"0xffffffff")else(if(Nat_big_num.equalas'((Nat_big_num.of_int8)))then(natural_of_hex"0xffffffffffffffff")else(failwith"max_address size not 4 or 8")))(** lookup of encodings *)(*val lookup_Ab_b : forall 'a 'b. Eq 'a => 'a -> list ('a * 'b) -> maybe 'b*)letreclookup_Ab_bdict_Basic_classes_Eq_ax0xys:'boption=((matchxyswith|[]->None|(x,y)::xys'->ifdict_Basic_classes_Eq_a.isEqual_methodxx0thenSomeyelselookup_Ab_bdict_Basic_classes_Eq_ax0xys'))(*val lookup_aB_a : forall 'a 'b. Eq 'b => 'b -> list ('a * 'b) -> maybe 'a*)letreclookup_aB_adict_Basic_classes_Eq_by0xys:'aoption=((matchxyswith|[]->None|(x,y)::xys'->ifdict_Basic_classes_Eq_b.isEqual_methodyy0thenSomexelselookup_aB_adict_Basic_classes_Eq_by0xys'))(*val lookup_aBc_a : forall 'a 'b 'c. Eq 'b => 'b -> list ('a * 'b * 'c) -> maybe 'a*)letreclookup_aBc_adict_Basic_classes_Eq_by0xyzs:'aoption=((matchxyzswith|[]->None|(x,y,_)::xyzs'->ifdict_Basic_classes_Eq_b.isEqual_methodyy0thenSomexelselookup_aBc_adict_Basic_classes_Eq_by0xyzs'))(*val lookup_aBc_ac : forall 'a 'b 'c. Eq 'b => 'b -> list ('a * 'b * 'c) -> maybe ('a*'c)*)letreclookup_aBc_acdict_Basic_classes_Eq_by0xyzs:('a*'c)option=((matchxyzswith|[]->None|(x,y,z)::xyzs'->ifdict_Basic_classes_Eq_b.isEqual_methodyy0thenSome(x,z)elselookup_aBc_acdict_Basic_classes_Eq_by0xyzs'))(*val lookup_Abc_b : forall 'a 'b 'c. Eq 'a => 'a -> list ('a * 'b * 'c) -> maybe 'b*)letreclookup_Abc_bdict_Basic_classes_Eq_ax0xyzs:'boption=((matchxyzswith|[]->None|(x,y,_)::xyzs'->ifdict_Basic_classes_Eq_a.isEqual_methodxx0thenSomeyelselookup_Abc_bdict_Basic_classes_Eq_ax0xyzs'))(*val lookup_aBcd_a : forall 'a 'b 'c 'd. Eq 'b => 'b -> list ('a * 'b * 'c * 'd) -> maybe 'a*)letreclookup_aBcd_adict_Basic_classes_Eq_by0xyzws:'aoption=((matchxyzwswith|[]->None|(x,y,_,_)::xyzws'->ifdict_Basic_classes_Eq_b.isEqual_methodyy0thenSomexelselookup_aBcd_adict_Basic_classes_Eq_by0xyzws'))(*val lookup_aBcd_acd : forall 'a 'b 'c 'd. Eq 'b => 'b -> list ('a * 'b * 'c * 'd) -> maybe ('a * 'c * 'd)*)letreclookup_aBcd_acddict_Basic_classes_Eq_by0xyzws:('a*'c*'d)option=((matchxyzwswith|[]->None|(x,y,z,w)::xyzws'->ifdict_Basic_classes_Eq_b.isEqual_methodyy0thenSome(x,z,w)elselookup_aBcd_acddict_Basic_classes_Eq_by0xyzws'))(*val lookup_abCde_de : forall 'a 'b 'c 'd 'e. Eq 'c => 'c -> list ('a * 'b * 'c * 'd * 'e) -> maybe ('d * 'e)*)letreclookup_abCde_dedict_Basic_classes_Eq_cz0xyzwus:('d*'e)option=((matchxyzwuswith|[]->None|(x,y,z,w,u)::xyzwus'->ifdict_Basic_classes_Eq_c.isEqual_methodzz0thenSome(w,u)elselookup_abCde_dedict_Basic_classes_Eq_cz0xyzwus'))letpp_maybeppfn:string=((matchppfnwithSomes->s|None->"Unknown AT value: "^pphexplainn(*encoding not found: "" ^ pphex n*)))letpp_tag_encodingn:string=(pp_maybe(funn->lookup_aB_ainstance_Basic_classes_Eq_Num_natural_dictntag_encodings)n)letpp_attribute_encodingn:string=(pp_maybe(funn->lookup_aBc_ainstance_Basic_classes_Eq_Num_natural_dictnattribute_encodings)n)letpp_attribute_form_encodingn:string=(pp_maybe(funn->lookup_aBc_ainstance_Basic_classes_Eq_Num_natural_dictnattribute_form_encodings)n)letpp_operation_encodingn:string=(pp_maybe(funn->lookup_aBcd_ainstance_Basic_classes_Eq_Num_natural_dictnoperation_encodings)n)lettag_encode(s:string):Nat_big_num.num=((matchlookup_Ab_binstance_Basic_classes_Eq_string_dictstag_encodingswith|Somen->n|None->failwith("tag_encode: \""^(s^"\""))))letattribute_encode(s:string):Nat_big_num.num=((matchlookup_Abc_binstance_Basic_classes_Eq_string_dictsattribute_encodingswith|Somen->n|None->failwith("attribute_encode: \""^(s^"\""))))letattribute_form_encode(s:string):Nat_big_num.num=((matchlookup_Abc_binstance_Basic_classes_Eq_string_dictsattribute_form_encodingswith|Somen->n|None->failwith"attribute_form_encode"))letbase_type_attribute_encode(s:string):Nat_big_num.num=((matchlookup_Ab_binstance_Basic_classes_Eq_string_dictsbase_type_attribute_encodingswith|Somen->n|None->failwith"base_type_attribute_encode"))(** ************************************************************ *)(** ** parser combinators and primitives ********************* *)(** ************************************************************ *)(* parsing combinators *)typeparse_context={pc_bytes:byte_sequence0;pc_offset:Nat_big_num.num}type'aparse_result=|PR_successof'a*parse_context|PR_failofstring*parse_contexttype'aparser=parse_context->'aparse_resultletpp_parse_contextpc:string=("pc_offset = "^pphexpc.pc_offset)letpp_parse_failspc:string=("Parse fail\n"^(s^(" at "^(pp_parse_contextpc^"\n"))))letpp_parse_resultppapr:string=((matchprwith|PR_success(x,pc)->"Parse success\n"^(ppax^("\n"^(pp_parse_contextpc^"\n")))|PR_fail(s,pc)->pp_parse_failspc))(* [(>>=)] should be the monadic binding function for [parse_result]. *)(* but there's a type clash if we use >>=, and lem seems to output bad ocaml for >>>=. So we just use a non-infix version for now *)(*val pr_bind : forall 'a 'b. parse_result 'a -> ('a -> parser 'b) -> parse_result 'b*)letpr_bindxf:'bparse_result=((matchxwith|PR_success(v,pc)->fvpc|PR_fail(err,pc)->PR_fail(err,pc)))(*val pr_return : forall 'a. 'a -> (parser 'a)*)letpr_returnxpc:'aparse_result=(PR_success(x,pc))(*val pr_map : forall 'a 'b. ('a -> 'b) -> parse_result 'a -> parse_result 'b*)letpr_mapfx:'bparse_result=((matchxwith|PR_success(v,pc)->PR_success((fv),pc)|PR_fail(err,pc)->PR_fail(err,pc)))(*val pr_map2 : forall 'a 'b. ('a -> 'b) -> (parser 'a) -> (parser 'b)*)letpr_map2fp:parse_context->'bparse_result=(funpc->pr_mapf(ppc))(*val pr_post_map1 : forall 'a 'b. (parse_result 'a) -> ('a -> 'b) -> (parse_result 'b)*)letpr_post_map1xf:'bparse_result=(pr_mapfx)(*
val pr_post_map : forall 'a 'b 'c. ('c -> parse_result 'a) -> ('a -> 'b) -> ('c -> parse_result 'b)
let pr_post_map g f = fun x -> pr_map f (g x)
*)(*val pr_post_map : forall 'a 'b. (parser 'a) -> ('a -> 'b) -> (parser 'b)*)letpr_post_mappf:parse_context->'bparse_result=(fun(pc:parse_context)->pr_mapf(ppc))(*val pr_with_pos : forall 'a. (parser 'a) -> (parser (natural * 'a))*)letpr_with_posp:parse_context->(Nat_big_num.num*'a)parse_result=(funpc->pr_map(funx->(pc.pc_offset,x))(ppc))(*val parse_pair : forall 'a 'b. (parser 'a) -> (parser 'b) -> (parser ('a * 'b))*)letparse_pairp1p2:parse_context->('a*'b)parse_result=(funpc->let_=(my_debug"pair ")inpr_bind(p1pc)(funxpc'->(matchp2pc'with|PR_success(y,pc'')->PR_success((x,y),pc'')|PR_fail(s,pc'')->PR_fail(s,pc''))))(*val parse_triple : forall 'a 'b 'c. (parser 'a) -> (parser 'b) -> (parser 'c) -> parser ('a * ('b * 'c))*)letparse_triplep1p2p3:parse_context->('a*('b*'c))parse_result=(parse_pairp1(parse_pairp2p3))(*val parse_quadruple : forall 'a 'b 'c 'd. (parser 'a) -> (parser 'b) -> (parser 'c) -> (parser 'd) -> parser ('a * ('b * ('c * 'd)))*)letparse_quadruplep1p2p3p4:parse_context->('a*('b*('c*'d)))parse_result=(parse_pairp1(parse_pairp2(parse_pairp3p4)))(*val parse_pentuple : forall 'a 'b 'c 'd 'e. (parser 'a) -> (parser 'b) -> (parser 'c) -> (parser 'd) -> (parser 'e) -> parser ('a * ('b * ('c * ('d * 'e))))*)letparse_pentuplep1p2p3p4p5:parse_context->('a*('b*('c*('d*'e))))parse_result=(parse_pairp1(parse_pairp2(parse_pairp3(parse_pairp4p5))))(*val parse_sextuple : forall 'a 'b 'c 'd 'e 'f. (parser 'a) -> (parser 'b) -> (parser 'c) -> (parser 'd) -> (parser 'e) -> (parser 'f) -> parser ('a * ('b * ('c * ('d * ('e * 'f)))))*)letparse_sextuplep1p2p3p4p5p6:parse_context->('a*('b*('c*('d*('e*'f)))))parse_result=(parse_pairp1(parse_pairp2(parse_pairp3(parse_pairp4(parse_pairp5p6)))))(*val parse_dependent_pair : forall 'a 'b. (parser 'a) -> ('a -> parser 'b) -> (parser ('a * 'b))*)letparse_dependent_pairp1p2:parse_context->('a*'b)parse_result=(funpc->pr_bind(p1pc)(funxpc'->(matchp2xpc'with|PR_success(y,pc'')->PR_success((x,y),pc'')|PR_fail(s,pc'')->PR_fail(s,pc''))))(*val parse_dependent : forall 'a 'b. (parser 'a) -> ('a -> parser 'b) -> (parser 'b)*)letparse_dependentp1p2:parse_context->'bparse_result=(funpc->pr_bind(p1pc)(funxpc'->p2xpc'))(*val parse_list' : forall 'a. (parser (maybe 'a)) -> (list 'a -> parser (list 'a))*)letrecparse_list'p1:'alist->parse_context->('alist)parse_result=(funaccpc->let_=(my_debug"list' ")inpr_bind(p1pc)(funmxpc'->(matchmxwith|None->PR_success(acc,pc')|Somex->parse_list'p1(x::acc)pc')))(*val parse_list : forall 'a. (parser (maybe 'a)) -> (parser (list 'a))*)letparse_listp1:parse_context->('alist)parse_result=(pr_post_map(parse_list'p1[])(List.rev))(*val parse_parser_list : forall 'a. (list (parser 'a)) -> (parser (list 'a))*)letrecparse_parser_listps:parse_context->('alist)parse_result=((matchpswith|[]->pr_return[]|p::ps'->(funpc->pr_bind(ppc)(funxpc'->(matchparse_parser_listps'pc'with|PR_success(xs,pc'')->PR_success((x::xs),pc'')|PR_fail(s,pc'')->PR_fail(s,pc''))))))(*val parse_maybe : forall 'a. parser 'a -> parser (maybe 'a)*)letparse_maybep:parse_context->('aoption)parse_result=(funpc->if(Nat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0)))then(pr_returnNonepc)else((matchppcwith|PR_success(v,pc'')->PR_success((Somev),pc'')|PR_fail(s,pc'')->PR_fail(s,pc''))))(*val parse_demaybe : forall 'a. string ->parser (maybe 'a) -> parser 'a*)letparse_demaybesp:parse_context->'aparse_result=(funpc->(matchppcwith|PR_success((Somev),pc'')->PR_success(v,pc'')|PR_success((None),pc'')->PR_fail(s,pc'')|PR_fail(s,pc'')->PR_fail(s,pc'')))(*val parse_restrict_length : forall 'a. natural -> parser 'a -> parser 'a*)letparse_restrict_lengthnp:parse_context->'aparse_result=(funpc->(matchpartition0npc.pc_byteswith|Fail_->failwith"parse_restrict_length not given enough bytes"|Success(xs,ys)->letpc'=({pc_bytes=xs;pc_offset=(pc.pc_offset)})inppc'))(* parsing of basic types *)letparse_byte:(char)parser=(fun(pc:parse_context)->(matchread_charpc.pc_byteswith|Fail_->PR_fail("parse_byte",pc)|Success(b,bs)->PR_success(b,({pc_bytes=bs;pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int1)))}))))letparse_n_bytes(n:Nat_big_num.num):(byte_sequence0)parser=(fun(pc:parse_context)->(matchpartition0npc.pc_byteswith|Fail_->PR_fail(("parse_n_bytes n="^pphexn),pc)|Success(xs,bs)->PR_success(xs,({pc_bytes=bs;pc_offset=(Nat_big_num.addpc.pc_offset(Byte_sequence.length0xs))}))))letbzero:char=(Char.chr(Nat_big_num.to_int((Nat_big_num.of_int0))))letparse_string:(byte_sequence0)parser=(fun(pc:parse_context)->(matchfind_bytepc.pc_bytesbzerowith|None->PR_fail("parse_string",pc)|Somen->pr_bind(parse_n_bytesnpc)(funrespc->pr_bind(parse_bytepc)(fun_pc->pr_returnrespc))))(* parse a null-terminated string; return Nothing if it is empty, Just s otherwise *)letparse_non_empty_string:(byte_sequence0option)parser=(fun(pc:parse_context)->pr_bind(parse_stringpc)(funstrpc->ifNat_big_num.equal(Byte_sequence.length0str)((Nat_big_num.of_int0))thenpr_returnNonepcelsepr_return(Somestr)pc))letparse_uint8:Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"uint8 ")in(matchread_charpc.pc_byteswith|Success(b,bytes)->letv=(natural_of_byteb)inPR_success(v,({pc_bytes=bytes;pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int1)))}))|_->PR_fail("parse_uint32 not given enough bytes",pc)))letparse_uint8_constant(v:Nat_big_num.num):Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"uint8_constant ")inPR_success(v,pc))letparse_uint16c:Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"uint16 ")in(matchread_2_bytes_bepc.pc_byteswith|Success((b0,b1),bytes')->letv=(ifc.endianness=LittlethenNat_big_num.add(natural_of_byteb0)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb1))elseNat_big_num.add(natural_of_byteb1)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb0)))inPR_success(v,({pc_bytes=bytes';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int2)))}))|_->PR_fail("parse_uint32 not given enough bytes",pc)))letparse_uint32c:Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"uint32 ")in(matchread_4_bytes_bepc.pc_byteswith|Success((b0,b1,b2,b3),bytes')->letv=(ifc.endianness=LittlethenNat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb0)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb1)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb2)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb3))elseNat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb3)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb2)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb1)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb0)))inPR_success(v,({pc_bytes=bytes';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int4)))}))|_->PR_fail("parse_uint32 not given enough bytes",pc)))letparse_uint64c:Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"uint64 ")in(matchread_8_bytes_bepc.pc_byteswith|Success((b0,b1,b2,b3,b4,b5,b6,b7),bytes')->letv=(ifc.endianness=LittlethenNat_big_num.add(Nat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb0)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb1)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb2)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb3)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(Nat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb4)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb5)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb6)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb7))))elseNat_big_num.add(Nat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb7)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb6)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb5)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb4)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(Nat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb3)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb2)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))(natural_of_byteb1)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(natural_of_byteb0)))))inPR_success(v,({pc_bytes=bytes';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int8)))}))|_->PR_fail("parse_uint64 not given enough bytes",pc)))letintegerFromTwosComplementNatural(n:Nat_big_num.num)(half:Nat_big_num.num)(all:Nat_big_num.num):Nat_big_num.num=(ifNat_big_num.lessnhalfthennelseNat_big_num.sub(n)all)letpartialTwosComplementNaturalFromInteger(i:Nat_big_num.num)(half:Nat_big_num.num)(all:Nat_big_num.num):Nat_big_num.num=(ifNat_big_num.greater_equali((Nat_big_num.of_int0))&&Nat_big_num.lessi(half)thenpartialNaturalFromIntegerielseifNat_big_num.greater_equali(Nat_big_num.sub((Nat_big_num.of_int0))(half))&&Nat_big_num.lessi((Nat_big_num.of_int0))thenpartialNaturalFromInteger(Nat_big_num.addalli)elsefailwith"partialTwosComplementNaturalFromInteger")letparse_sint8:Nat_big_num.numparser=(pr_post_map(parse_uint8)(funn->integerFromTwosComplementNaturaln((Nat_big_num.of_int128))((Nat_big_num.of_int256))))letparse_sint16c:Nat_big_num.numparser=(pr_post_map(parse_uint16c)(funn->integerFromTwosComplementNaturaln(Nat_big_num.mul((Nat_big_num.of_int128))((Nat_big_num.of_int256)))(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))))letparse_sint32c:Nat_big_num.numparser=(pr_post_map(parse_uint32c)(funn->integerFromTwosComplementNaturaln(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int128))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))))letparse_sint64c:Nat_big_num.numparser=(pr_post_map(parse_uint64c)(funn->integerFromTwosComplementNaturaln(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int128))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int256))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))((Nat_big_num.of_int256)))))letrecparse_ULEB128'(acc:Nat_big_num.num)(shift_factor:Nat_big_num.num):Nat_big_num.numparser=(fun(pc:parse_context)->let_=(my_debug"ULEB128' ")in(matchread_charpc.pc_byteswith|Success(b,bytes')->letn=(natural_of_byteb)inletacc'=(Nat_big_num.add(Nat_big_num.mul(Nat_big_num.bitwise_andn((Nat_big_num.of_int127)))shift_factor)acc)inletfinished=(Nat_big_num.equal(Nat_big_num.bitwise_andn((Nat_big_num.of_int128)))((Nat_big_num.of_int0)))inletpc'=({pc_bytes=bytes';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int1)))})iniffinishedthenPR_success(acc',pc')elseparse_ULEB128'acc'(Nat_big_num.mulshift_factor((Nat_big_num.of_int128)))pc'|_->PR_fail("parse_ULEB128' not given enough bytes",pc)))letparse_ULEB128:Nat_big_num.numparser=(fun(pc:parse_context)->parse_ULEB128'((Nat_big_num.of_int0))((Nat_big_num.of_int1))pc)letrecparse_SLEB128'(acc:Nat_big_num.num)(shift_factor:Nat_big_num.num):(bool*Nat_big_num.num*Nat_big_num.num)parser=(fun(pc:parse_context)->let_=(my_debug"SLEB128' ")in(matchread_charpc.pc_byteswith|Success(b,bytes')->letn=(natural_of_byteb)inletacc'=(Nat_big_num.addacc(Nat_big_num.mul(Nat_big_num.bitwise_andn((Nat_big_num.of_int127)))shift_factor))inletshift_factor'=(Nat_big_num.mulshift_factor((Nat_big_num.of_int128)))inletfinished=(Nat_big_num.equal(Nat_big_num.bitwise_andn((Nat_big_num.of_int128)))((Nat_big_num.of_int0)))inletpositive=(Nat_big_num.equal(Nat_big_num.bitwise_andn((Nat_big_num.of_int64)))((Nat_big_num.of_int0)))inletpc'=({pc_bytes=bytes';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int1)))})iniffinishedthenPR_success((positive,shift_factor',acc'),pc')elseparse_SLEB128'acc'shift_factor'pc'|_->PR_fail("parse_SLEB128' not given enough bytes",pc)))letparse_SLEB128:Nat_big_num.numparser=(pr_post_map(parse_SLEB128'((Nat_big_num.of_int0))((Nat_big_num.of_int1)))(fun(positive,shift_factor,acc)->ifpositivethenaccelseNat_big_num.sub(acc)(shift_factor)))letparse_nonzero_ULEB128_pair:((Nat_big_num.num*Nat_big_num.num)option)parser=(let_=(my_debug"nonzero_ULEB128_pair ")inpr_post_map(parse_pairparse_ULEB128parse_ULEB128)(fun(n1,n2)->ifNat_big_num.equaln1((Nat_big_num.of_int0))&&Nat_big_num.equaln2((Nat_big_num.of_int0))thenNoneelseSome(n1,n2)))letparse_zero_terminated_ULEB128_pair_list:((Nat_big_num.num*Nat_big_num.num)list)parser=(let_=(my_debug"zero_terminated_ULEB128_pair_list ")inparse_listparse_nonzero_ULEB128_pair)letparse_uintDwarfNc(df:dwarf_format):Nat_big_num.numparser=((matchdfwith|Dwarf32->(parse_uint32c)|Dwarf64->(parse_uint64c)))letparse_uint_address_sizec(as':Nat_big_num.num):Nat_big_num.numparser=(if(Nat_big_num.equalas'((Nat_big_num.of_int4)))then(parse_uint32c)else(if(Nat_big_num.equalas'((Nat_big_num.of_int8)))then(parse_uint64c)else(failwith("cuh_address_size not 4 or 8: "^Nat_big_num.to_stringas'))))letparse_uint_segment_selector_sizec(ss:Nat_big_num.num):(Nat_big_num.numoption)parser=(if(Nat_big_num.equalss((Nat_big_num.of_int0)))then(pr_returnNone)else(if(Nat_big_num.equalss((Nat_big_num.of_int1)))then(pr_post_map(parse_uint8)(funn->Somen))else(if(Nat_big_num.equalss((Nat_big_num.of_int2)))then(pr_post_map(parse_uint16c)(funn->Somen))else(if(Nat_big_num.equalss((Nat_big_num.of_int4)))then(pr_post_map(parse_uint32c)(funn->Somen))else(if(Nat_big_num.equalss((Nat_big_num.of_int8)))then(pr_post_map(parse_uint64c)(funn->Somen))else(failwith"cuh_address_size not 4 or 8"))))))(** ************************************************************ *)(** ** parsing and pretty printing of .debug_* sections ****** *)(** ************************************************************ *)(** abbreviations table: pp and parsing *)letpp_abbreviation_declaration(x:abbreviation_declaration):string=(" "^(Nat_big_num.to_stringx.ad_abbreviation_code^(" "^(pp_tag_encodingx.ad_tag^(" "^((ifx.ad_has_childrenthen"[has children]"else"[no children]")^("\n"(* ^ " "^show (List.length x.ad_attribute_specifications) ^ " attributes\n"*)^(String.concat""(Lem_list.map(fun(n1,n2)->" "^(right_space_padded_to((Nat_big_num.of_int18))(pp_attribute_encodingn1)^(" "^(pp_attribute_form_encodingn2^"\n"))))x.ad_attribute_specifications)^" DW_AT value: 0 DW_FORM value: 0\n"))))))))letpp_abbreviations_table(x:abbreviations_table):string=("offset: "^(pphexx.at_offset^("\n"^String.concat""(Lem_list.map(pp_abbreviation_declaration)x.at_table))))(* print the distinct abbreviation tables used by all compilation units *)letrecremove_duplicatesdict_Basic_classes_Eq_axysxys_acc:('a*'b)list=((matchxyswith|[]->List.revxys_acc|(x,y)::xys'->ifList.exists(fun(x',y')->dict_Basic_classes_Eq_a.isEqual_methodx'x)xys_accthenremove_duplicatesdict_Basic_classes_Eq_axys'xys_accelseremove_duplicatesdict_Basic_classes_Eq_axys'((x,y)::xys_acc)))letpp_abbreviations_tables(d:dwarf):string=(letxs:(Nat_big_num.num*abbreviations_table)list=(Lem_list.map(funcu->(cu.cu_header.cuh_debug_abbrev_offset,cu.cu_abbreviations_table))d.d_compilation_units)inletys=(remove_duplicatesinstance_Basic_classes_Eq_Num_natural_dictxs[])inString.concat"*********************\n"(Lem_list.map(fun(x,y)->pp_abbreviations_tabley)ys))letparse_abbreviation_declarationc:(abbreviation_declarationoption)parser=(fun(pc:parse_context)->pr_bind(parse_ULEB128pc)(funn1pc'->ifNat_big_num.equaln1((Nat_big_num.of_int0))thenPR_success(None,pc')elsepr_bind(parse_ULEB128pc')(funn2pc''->pr_bind(parse_uint8pc'')(funcpc'''->pr_post_map1(parse_zero_terminated_ULEB128_pair_listpc''')(funl->Some(letad=({ad_abbreviation_code=n1;ad_tag=n2;ad_has_children=(not(Nat_big_num.equalc((Nat_big_num.of_int0))));ad_attribute_specifications=l;})in(* let _ = my_debug2 (pp_abbreviation_declaration ad) in *)ad))))))letparse_abbreviations_tablec:parse_context->((abbreviation_declaration)list)parse_result=(parse_list(parse_abbreviation_declarationc))(** debug_str entry *)letrecnull_terminated_bs(bs:byte_sequence0):byte_sequence0=((matchfind_bytebsbzerowith|Somei->(matchtakebytesibswith|Successbs'->bs'|Fail_->failwith"find_byte or take_byte is broken")|None->bs))letpp_debug_str_entry(str:byte_sequence0)(n:Nat_big_num.num):string=((matchdropbytesnstrwith|Fail_->"strp beyond .debug_str extent"|Successbs->string_of_byte_sequence(null_terminated_bsbs)))(** operations: pp and parsing *)letpp_operation_argument_value(oav:operation_argument_value):string=((matchoavwith|OAV_naturaln->pphexn|OAV_integern->pphex_integern(* show n*)|OAV_block(n,bs)->pphexn^(" "^ppbytesbs)))letpp_operation_semantics(os:operation_semantics):string=((matchoswith|OpSem_lit->"OpSem_lit"|OpSem_deref->"OpSem_deref"|OpSem_stack_->"OpSem_stack ..."|OpSem_not_supported->"OpSem_not_supported"|OpSem_binary_->"OpSem_binary ..."|OpSem_unary_->"OpSem_unary ..."|OpSem_opcode_lit_->"OpSem_opcode_lit ..."|OpSem_reg->"OpSem_reg"|OpSem_breg->"OpSem_breg"|OpSem_bregx->"OpSem_bregx"|OpSem_fbreg->"OpSem_fbreg"|OpSem_deref_size->"OpSem_deref_size"|OpSem_nop->"OpSem_nop"|OpSem_piece->"OpSem_piece"|OpSem_bit_piece->"OpSem_bitpiece"|OpSem_implicit_value->"OpSem_implicit_value"|OpSem_stack_value->"OpSem_stack_value"|OpSem_call_frame_cfa->"OpSem_call_frame_cfa"))letpp_operation_semantics_brief(os:operation_semantics):string=((matchoswith|OpSem_not_supported->" (OpSem_not_supported)"|_->""))letpp_operation(op:operation):string=(op.op_string^(((matchop.op_argument_valueswith[]->""|_->" "^String.concat" "(Lem_list.mappp_operation_argument_valueop.op_argument_values)))^pp_operation_semantics_briefop.op_semantics))letpp_operations(ops:operationlist):string=(String.concat"; "(Lem_list.mappp_operationops))(*val parser_of_operation_argument_type : p_context -> compilation_unit_header -> operation_argument_type -> (parser operation_argument_value)*)letparser_of_operation_argument_typeccuhoat:parse_context->(operation_argument_value)parse_result=((matchoatwith|OAT_addr->pr_map2(funn->OAV_naturaln)(parse_uint_address_sizeccuh.cuh_address_size)|OAT_dwarf_format_t->pr_map2(funn->OAV_naturaln)(parse_uintDwarfNccuh.cuh_dwarf_format)|OAT_uint8->pr_map2(funn->OAV_naturaln)(parse_uint8)|OAT_uint16->pr_map2(funn->OAV_naturaln)(parse_uint16c)|OAT_uint32->pr_map2(funn->OAV_naturaln)(parse_uint32c)|OAT_uint64->pr_map2(funn->OAV_naturaln)(parse_uint64c)|OAT_sint8->pr_map2(funn->OAV_integern)(parse_sint8)|OAT_sint16->pr_map2(funn->OAV_integern)(parse_sint16c)|OAT_sint32->pr_map2(funn->OAV_integern)(parse_sint32c)|OAT_sint64->pr_map2(funn->OAV_integern)(parse_sint64c)|OAT_ULEB128->pr_map2(funn->OAV_naturaln)parse_ULEB128|OAT_SLEB128->pr_map2(funn->OAV_integern)parse_SLEB128|OAT_block->(funpc->pr_bind(parse_ULEB128pc)(funnpc'->pr_map(funbs->OAV_block(n,bs))(parse_n_bytesnpc')))))(*val parse_operation : p_context -> compilation_unit_header -> parser (maybe operation)*)letparse_operationccuhpc:((operation)option)parse_result=((matchparse_uint8pcwith|PR_fail(s,pc')->PR_success(None,pc)|PR_success(code,pc')->(matchlookup_aBcd_acdinstance_Basic_classes_Eq_Num_natural_dictcodeoperation_encodingswith|None->PR_fail(("encoding not found: "^pphexcode),pc)|Some(s,oats,opsem)->letps=(Lem_list.map(parser_of_operation_argument_typeccuh)oats)in(pr_post_map(parse_parser_listps)(funoavs->Some{op_code=code;op_string=s;op_argument_values=oavs;op_semantics=opsem}))pc')))(*val parse_operations : p_context -> compilation_unit_header -> parser (list operation)*)letparse_operationsccuh:parse_context->((operation)list)parse_result=(parse_list(parse_operationccuh))letparse_operations_bsccuhbs:operationlist=(letpc=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_operationsccuhpcwith|PR_fail(s,pc')->failwith("parse_operations_bs fail: "^pp_parse_failspc')|PR_success(ops,pc')->let_=(ifnot(Nat_big_num.equal(Byte_sequence.length0pc'.pc_bytes)((Nat_big_num.of_int0)))thenfailwith("parse_operations_bs extra non-parsed bytes")else())inops))(*val parse_and_pp_operations : p_context -> compilation_unit_header -> byte_sequence -> string*)letparse_and_pp_operationsccuhbs:string=(letpc=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_operationsccuhpcwith|PR_fail(s,pc')->"parse_operations fail: "^pp_parse_failspc'|PR_success(ops,pc')->pp_operationsops^(ifnot(Nat_big_num.equal(Byte_sequence.length0pc'.pc_bytes)((Nat_big_num.of_int0)))then" Warning: extra non-parsed bytes"else"")))(** attribute values: pp and parsing *)(*val pp_attribute_value_plain : attribute_value -> string*)letpp_attribute_value_plainav:string=((matchavwith|AV_addrx->"AV_addr "^pphexx|AV_block(n,bs)->"AV_block "^(Nat_big_num.to_stringn^(" "^ppbytesbs))|AV_constantN(n,bs)->"AV_constantN "^(Nat_big_num.to_stringn^(" "^ppbytesbs))|AV_constant_SLEB128i->"AV_constant_SLEB128 "^Nat_big_num.to_stringi|AV_constant_ULEB128n->"AV_constant_ULEB128 "^Nat_big_num.to_stringn|AV_exprloc(n,bs)->String.concat" "["AV_exprloc";Nat_big_num.to_stringn;ppbytesbs]|AV_flagb->"AV_flag "^string_of_boolb|AV_refn->"AV_ref "^pphexn|AV_ref_addrn->"AV_ref_addr "^pphexn|AV_ref_sig8n->"AV_ref_sig8 "^pphexn|AV_sec_offsetn->"AV_sec_offset "^pphexn|AV_stringbs->string_of_byte_sequencebs|AV_strpn->"AV_sec_offset "^(pphexn^" ")))(*val pp_attribute_value : p_context -> compilation_unit_header -> byte_sequence -> natural (*attribute tag*) -> attribute_value -> string*)letpp_attribute_valueccuhstratav:string=((matchavwith|AV_addrx->"AV_addr "^pphexx|AV_block(n,bs)->"AV_block "^(Nat_big_num.to_stringn^(" "^(ppbytesbs^(ifNat_big_num.equalat(attribute_encode"DW_AT_location")then" "^parse_and_pp_operationsccuhbselse""))))|AV_constantN(n,bs)->"AV_constantN "^(Nat_big_num.to_stringn^(" "^ppbytesbs))|AV_constant_SLEB128i->"AV_constant_SLEB128 "^Nat_big_num.to_stringi|AV_constant_ULEB128n->"AV_constant_ULEB128 "^Nat_big_num.to_stringn|AV_exprloc(n,bs)->String.concat" "["AV_exprloc";Nat_big_num.to_stringn;ppbytesbs;parse_and_pp_operationsccuhbs]|AV_flagb->"AV_flag "^string_of_boolb|AV_refn->"AV_ref "^pphexn|AV_ref_addrn->"AV_ref_addr "^pphexn|AV_ref_sig8n->"AV_ref_sig8 "^pphexn|AV_sec_offsetn->"AV_sec_offset "^pphexn|AV_stringbs->string_of_byte_sequencebs|AV_strpn->"AV_sec_offset "^(pphexn^(" "^pp_debug_str_entrystrn))))(*val pp_attribute_value_like_objdump : p_context -> compilation_unit_header -> byte_sequence -> natural (*attribute tag*) -> attribute_value -> string*)letpp_attribute_value_like_objdumpccuhstratav:string=((matchavwith|AV_addrx->(*"AV_addr " ^*)pphexx|AV_block(n,bs)->(*"AV_block " ^ show n ^ " " ^ ppbytes bs
^ if at = attribute_encode "DW_AT_location" then " " ^ parse_and_pp_operations c cuh bs else ""*)(* show n ^ " byte block: " *)ppbytesplaincnbs^(ifNat_big_num.equalat(attribute_encode"DW_AT_location")then" "^parse_and_pp_operationsccuhbselse"")|AV_constantN(n,bs)->ppbytesbs(*"AV_constantN " ^ show n ^ " " ^ ppbytes bs*)|AV_constant_SLEB128i->(*"AV_constant_SLEB128 " ^*)Nat_big_num.to_stringi|AV_constant_ULEB128n->(*"AV_constant_ULEB128 " ^*)Nat_big_num.to_stringn|AV_exprloc(n,bs)->(*"AV_exprloc " ^ show n ^ " " ^*)ppbytesbs^(" "^parse_and_pp_operationsccuhbs)|AV_flagb->(*"AV_flag " ^*)ifbthen"1"else"0"|AV_refn->(*"AV_ref " ^*)"<"^(pphex(Nat_big_num.addncuh.cuh_offset)^">")|AV_ref_addrn->(*"AV_ref_addr " ^*)"<"^(pphexn^">")|AV_ref_sig8n->"AV_ref_sig8 "^pphexn|AV_sec_offsetn->(*"AV_sec_offset " ^*)pphexn^(ifNat_big_num.equalat(attribute_encode"DW_AT_location")then" (location list)"else"")|AV_stringbs->string_of_byte_sequencebs|AV_strpn->(*"AV_sec_offset " ^ pphex n ^ " "
^ pp_debug_str_entry str n*)"(indirect string, offset: "^(pphexn^("): "^pp_debug_str_entrystrn))))(*val parser_of_attribute_form_non_indirect : p_context -> compilation_unit_header -> natural -> parser attribute_value*)letparser_of_attribute_form_non_indirectccuhn:parse_context->(attribute_value)parse_result=((* address*)ifNat_big_num.equaln(attribute_form_encode"DW_FORM_addr")thenpr_map2(funn->AV_addrn)(parse_uint_address_sizeccuh.cuh_address_size)(* block *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_block1")then(funpc->pr_bind(parse_uint8pc)(funnpc'->pr_map(funbs->AV_block(n,bs))(parse_n_bytesnpc')))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_block2")then(funpc->pr_bind(parse_uint16cpc)(funnpc'->pr_map(funbs->AV_block(n,bs))(parse_n_bytesnpc')))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_block4")then(funpc->pr_bind(parse_uint32cpc)(funnpc'->pr_map(funbs->AV_block(n,bs))(parse_n_bytesnpc')))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_block")then(funpc->pr_bind(parse_ULEB128pc)(funnpc'->pr_map(funbs->AV_block(n,bs))(parse_n_bytesnpc')))(* constant *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_data1")thenpr_map2(funbs->AV_block(((Nat_big_num.of_int1)),bs))(parse_n_bytes((Nat_big_num.of_int1)))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_data2")thenpr_map2(funbs->AV_block(((Nat_big_num.of_int2)),bs))(parse_n_bytes((Nat_big_num.of_int2)))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_data4")thenpr_map2(funbs->AV_block(((Nat_big_num.of_int4)),bs))(parse_n_bytes((Nat_big_num.of_int4)))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_data8")thenpr_map2(funbs->AV_block(((Nat_big_num.of_int8)),bs))(parse_n_bytes((Nat_big_num.of_int8)))elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_sdata")thenpr_map2(funi->AV_constant_SLEB128i)parse_SLEB128elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_udata")thenpr_map2(funn->AV_constant_ULEB128n)parse_ULEB128(* exprloc *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_exprloc")then(funpc->pr_bind(parse_ULEB128pc)(funnpc'->pr_map(funbs->AV_exprloc(n,bs))(parse_n_bytesnpc')))(* flag *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_flag")thenpr_map2(funn->AV_flag(not(Nat_big_num.equaln((Nat_big_num.of_int0)))))(parse_uint8)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_flag_present")thenpr_map2(fun()->AV_flagtrue)(pr_return())(* lineptr, loclistptr, macptr, rangelistptr *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_sec_offset")thenpr_map2(funn->AV_sec_offsetn)(parse_uintDwarfNccuh.cuh_dwarf_format)(* reference - first type *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref1")thenpr_map2(funn->AV_refn)(parse_uint8)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref2")thenpr_map2(funn->AV_refn)(parse_uint16c)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref4")thenpr_map2(funn->AV_refn)(parse_uint32c)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref8")thenpr_map2(funn->AV_refn)(parse_uint64c)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref_udata")thenpr_map2(funn->AV_refn)parse_ULEB128(* reference - second type *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref_addr")thenpr_map2(funn->AV_ref_addrn)(parse_uintDwarfNccuh.cuh_dwarf_format)(* reference - third type *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_ref_sig8")thenpr_map2(funn->AV_ref_sig8n)(parse_uint64c)(* string *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_string")thenpr_map2(funbs->AV_stringbs)parse_stringelseifNat_big_num.equaln(attribute_form_encode"DW_FORM_strp")thenpr_map2(funn->AV_strpn)(parse_uintDwarfNccuh.cuh_dwarf_format)(* indirect (cycle detection) *)elseifNat_big_num.equaln(attribute_form_encode"DW_FORM_indirect")thenfailwith"DW_FORM_INDIRECT cycle"(* unknown *)elsefailwith"parser_of_attribute_form_non_indirect: unknown attribute form")letparser_of_attribute_formccuhn:parse_context->(attribute_value)parse_result=(ifNat_big_num.equaln(attribute_form_encode"DW_FORM_indirect")then(funpc->pr_bind(parse_ULEB128pc)(funn->parser_of_attribute_form_non_indirectccuhn))elseparser_of_attribute_form_non_indirectccuhn)(* *** where to put this? *)letpp_pospos:string=("<"^(pphexplainpos^">"))letpp_cupdie(cu,parents,die1):string=(pp_poscu.cu_header.cuh_offset^("/"^pp_posdie1.die_offset))letpp_cupdie3(cu,parents,die1):string=(pp_posdie1.die_offset^("/"^(String.concat"/"(Lem_list.map(funp->pp_posp.die_offset)parents)^("/"^pp_poscu.cu_header.cuh_offset))))(** ************************************************************ *)(** ** finding things in the die tree *)(** ************************************************************ *)(*val find_maybe : forall 'a 'b. ('a -> maybe 'b) -> list 'a -> maybe 'b*)letrecfind_maybefl:'boption=((matchlwith|[]->None|x::xs->(matchfxwith|Somey->Somey|None->find_maybefxs)))letrecfind_die_by_offset_in_cuoffsetcu:cupdieoption=((matchPmap.lookupoffsetcu.cu_indexwith|Some(parents,die1)->Some(cu,parents,die1)|None->None))letfind_die_by_offset_in_alloffsetd:cupdieoption=(find_maybe(funcu->find_die_by_offset_in_cuoffsetcu)d.d_compilation_units)(*val find_dies_in_die : (die->bool) -> compilation_unit -> list die -> die -> list cupdie*)letrecfind_dies_in_die(p:die->bool)(cu:compilation_unit)(parents:dielist)(d:die):(compilation_unit*(die)list*die)list=(letds=(List.concat(map(find_dies_in_diepcu(d::parents))d.die_children))inifpdthen(cu,parents,d)::dselseds)letfind_dies(p:die->bool)(d:dwarf):cupdielist=(List.concat(map(funcu->find_dies_in_diepcu[]cu.cu_die)d.d_compilation_units))(** convert attribute values to usable Lem types *)letstring_of_string_attribute_valuestrav:string=((matchavwith|AV_stringbs->string_of_byte_sequencebs|AV_strpn->pp_debug_str_entrystrn|_->"find_string_attribute_value_of_die AV not understood"))letmaybe_natural_of_constant_attribute_valuedie1cav:Nat_big_num.numoption=((matchavwith|AV_constantN(n,bs)->Somen|AV_constant_ULEB128n->Somen|AV_block(n,bs)->Some(natural_of_bytesc.endiannessbs)|_->None))letnatural_of_constant_attribute_valuedie1cav:Nat_big_num.num=((matchmaybe_natural_of_constant_attribute_valuedie1cavwith|Somen->n|None->failwith("natural_of_constant_attribute_value fail at "^(pp_posdie1.die_offset^(" with av= "^pp_attribute_value_plainav)))))letinteger_of_constant_attribute_valuecav:Nat_big_num.num=((matchavwith|AV_constantN(n,bs)->n|AV_constant_ULEB128n->n|AV_constant_SLEB128n->n|AV_block(n,bs)->(natural_of_bytesc.endiannessbs)|_->failwith("integer_of_constant_attribute_value fail")))letbool_of_flag_attribute_valueav:bool=((matchavwith|AV_flagb->b|_->failwith("bool_of_maybe_flag_attribute_value fail")))letreference_of_reference_attribute_valuecdcustrav:(compilation_unit*(dielist)*die)option=((matchavwith(* "offset from the first byte of the compilation header for the compilation unit containing the reference" *)|AV_refn->letn'=(Nat_big_num.addncu.cu_header.cuh_offset)in(matchfind_die_by_offset_in_alln'd(*cu.cu_die*)with|Some(cu',parents',die')->Some(cu',parents',die')|None->None(* Fail ("find_reference_attribute_of_die AV_ref failed (cuh="^pphex cu.cu_header.cuh_offset ^" n'="^pphex n'^")"^"\n"^ppd())*))(* offset in .debug_info *)|AV_ref_addrn->(matchfind_die_by_offset_in_allndwith|Some(cu',parents',die')->Some(cu',parents',die')|None->None(*Fail ("find_reference_attribute_of_die AV_ref_addr failed\n"^ppd())*))|_->None(*Fail ("reference_of_reference_attribute AV ("^pp_attribute_value c cu.cu_header str (attribute_encode an) av^") not supported\n"^ppd() )*)(* TODO: handle the AV_ref_sig8 case for type signature references *)))(** attribute find *)letfind_attribute_value(an:string)(die1:die):attribute_valueoption=(letat=(attribute_encodean)inletats=(Lem_list.list_combinedie1.die_abbreviation_declaration.ad_attribute_specificationsdie1.die_attribute_values)inmyfindmaybe(fun(((at':Nat_big_num.num),(af:Nat_big_num.num)),((pos:Nat_big_num.num),(av:attribute_value)))->ifNat_big_num.equalat'atthenSomeavelseNone)ats)letfind_string_attribute_value_of_die(an:string)str(die1:die):stringoption=((matchfind_attribute_valueandie1with|Someav->lets=(string_of_string_attribute_valuestrav)inSomes|None->None))letfind_natural_attribute_value_of_diec(an:string)(die1:die):Nat_big_num.numoption=((matchfind_attribute_valueandie1with|Someav->letn=(natural_of_constant_attribute_valuedie1cav)inSomen|None->None))letfind_integer_attribute_value_of_diec(an:string)(die1:die):Nat_big_num.numoption=((matchfind_attribute_valueandie1with|Someav->letn=(integer_of_constant_attribute_valuecav)inSomen|None->None))letfind_flag_attribute_value_of_die(an:string)(die1:die):booloption=(Lem.option_mapbool_of_flag_attribute_value(find_attribute_valueandie1))letfind_flag_attribute_value_of_die_default_false(an:string)(die1:die):bool=((matchfind_flag_attribute_value_of_dieandie1with|Someb->b|None->false))letfind_name_of_diestrdie1:stringoption=(find_string_attribute_value_of_die"DW_AT_name"strdie1)letfind_reference_attribute_of_diecdcustrandie1:(compilation_unit*(dielist)*die)option=(letppd()=(pp_posdie1.die_offset)(*pp_die c cuh str true 0 false die ^ "\n"*)in(matchfind_attribute_valueandie1with|None->None(*Fail ("find_reference_attribute_of_die found no " ^ an ^ "\n" ^ ppd())*)|Someav->reference_of_reference_attribute_valuecdcustrav))letfind_DW_AT_type_of_diecdcustrdie1:(compilation_unit*(dielist)*die)option=(find_reference_attribute_of_diecdcustr"DW_AT_type"die1)(* look up "an" in die. If not found, see if die has an abstract origin, and if so, look up "an" in that. Return the relevant cu, too *)letfind_attribute_value_using_abstract_origincdcustrandie1:(compilation_unit*attribute_value)option=((matchfind_attribute_valueandie1with|Someav->Some(cu,av)|None->(matchfind_reference_attribute_of_diecdcustr"DW_AT_abstract_origin"die1with|None->None(*s ^ " and no DW_AT_abstract_origin"*)|Some(cu',parents',die')->(matchfind_attribute_valueandie'with|Someav->Some(cu',av)|None->None))))letfind_name_of_die_using_abstract_origincdcustrdie1:stringoption=((matchfind_attribute_value_using_abstract_origincdcustr"DW_AT_name"die1with|None->None|Some(cu',av)->Some(string_of_string_attribute_valuestrav)))(* TODO: not sure how DW_AT_specification should interact with abstract origins *)letfind_name_of_die_using_abstract_origin_and_speccdcustrdie1mcupdie_spec:stringoption=((matchfind_name_of_die_using_abstract_origincdcustrdie1with|Somename1->Somename1|None->(matchmcupdie_specwith|Some(((cu_spec,parents_spec,die_spec)ascupdie_spec))->find_name_of_die_using_abstract_origincdcu_specstrdie_spec|None->None)))letfind_reference_attribute_using_abstract_origincdcustrandie1:(compilation_unit*(dielist)*die)option=((matchfind_attribute_value_using_abstract_origincdcustrandie1with|None->None|Some(cu',av)->reference_of_reference_attribute_valuecdcu'strav))letfind_DW_AT_type_of_die_using_abstract_origincdcustrdie1:(compilation_unit*(dielist)*die)option=(find_reference_attribute_using_abstract_origincdcustr"DW_AT_type"die1)letfind_flag_attribute_value_of_die_using_abstract_origind(an:string)((cu,parents,die1):cupdie):booloption=(letc=(p_context_of_dd)in(matchfind_attribute_value_using_abstract_origincdcud.d_strandie1with|None->None|Some(cu',av)->Some(bool_of_flag_attribute_valueav)))(** compilation unit header: pp and parsing *)letpp_dwarf_formatdf:string=((matchdfwithDwarf32->"(32-bit)"|Dwarf64->"(64-bit)"))letpp_unit_header(s:string)(x:compilation_unit_header):string=("**"^(s^(" Unit @ offset "^(pphexx.cuh_offset^("\n"^(" "^(s^(" Unit @ offset "^(pphexx.cuh_offset^(":\n"^(" Length: "^(pphexx.cuh_unit_length^(" "^(pp_dwarf_formatx.cuh_dwarf_format^("\n"^(" Version: "^(Nat_big_num.to_stringx.cuh_version^("\n"^(" Abbrev Offset: "^(pphexx.cuh_debug_abbrev_offset^("\n"^(" Pointer Size: "^(Nat_big_num.to_stringx.cuh_address_size^"\n")))))))))))))))))))))))letpp_compilation_unit_header(x:compilation_unit_header):string=(pp_unit_header"Compilation"x)letparse_unit_lengthc:(dwarf_format*Nat_big_num.num)parser=(fun(pc:parse_context)->pr_bind(parse_uint32cpc)(funxpc'->ifNat_big_num.lessx(natural_of_hex"0xfffffff0")thenPR_success((Dwarf32,x),pc')elseifnot(Nat_big_num.equalx(natural_of_hex"0xffffffff"))thenPR_fail("bad unit_length",pc)elsepr_bind(parse_uint64cpc')(funx'pc''->PR_success((Dwarf64,x'),pc'))))letparse_compilation_unit_headerc:compilation_unit_headerparser=(pr_post_map(pr_with_pos(parse_dependent_pair(parse_unit_lengthc)(fun(df,ul)->parse_triple(parse_uint16c)(* version *)(parse_uintDwarfNcdf)(* debug abbrev offset *)(parse_uint8)(* address_size *))))(fun(offset,((df,ul),(v,(dao,as'))))->{cuh_offset=offset;cuh_dwarf_format=df;cuh_unit_length=ul;cuh_version=v;cuh_debug_abbrev_offset=dao;cuh_address_size=as';}))(** type unit header: pp and parsing *)(* the test binaries don't have a .debug_types section, so this isn't tested *)letpp_type_unit_header(x:type_unit_header):string=(pp_unit_header"Type"x.tuh_cuh^(" Type Signature: "^(pphexx.tuh_type_signature^("\n"^(" Type Offset: "^(pphexx.tuh_type_offset^"\n"))))))letparse_type_unit_headerc:type_unit_headerparser=(pr_post_map(parse_dependent_pair(parse_compilation_unit_headerc)(funcuh->parse_pair(parse_uint64c)(* type signature *)(parse_uintDwarfNccuh.cuh_dwarf_format)(* type offset *)))(fun(cuh,(ts,to'))->{tuh_cuh=cuh;tuh_type_signature=ts;tuh_type_offset=to';}))(** debugging information entries: pp and parsing *)(* example pp from readelf
<2><51>: Abbrev Number: 3 (DW_TAG_variable)
<52> DW_AT_name : x
<54> DW_AT_decl_file : 1
<55> DW_AT_decl_line : 2
<56> DW_AT_type : <0x6a>
<5a> DW_AT_location : 2 byte block: 91 6c (DW_OP_fbreg: -20)
*)(** debugging information entries: pp and parsing *)letindent_level(indent:bool)(level:Nat_big_num.num):string=(ifindentthen(Xstring.implode(replicate0(Nat_big_num.mul((Nat_big_num.of_int3))level)' '))else" ")letindent_level_plus_oneindentlevel:string=(ifindentthenindent_levelindent(Nat_big_num.addlevel((Nat_big_num.of_int1)))else" "^" ")letpp_die_attributec(cuh:compilation_unit_header)(str:byte_sequence0)(indent:bool)(level:Nat_big_num.num)(((at:Nat_big_num.num),(af:Nat_big_num.num)),((pos:Nat_big_num.num),(av:attribute_value))):string=(indent_level_plus_oneindentlevel^(pp_pospos^(" "^(right_space_padded_to((Nat_big_num.of_int18))(pp_attribute_encodingat)^(": "^(ifindentthen"("^(pp_attribute_form_encodingaf^(") "^(pp_attribute_valueccuhstratav^"\n")))elsepp_attribute_value_like_objdumpccuhstratav^"\n"))))))(*val pp_die : p_context -> compilation_unit_header -> byte_sequence -> bool -> natural -> bool -> die -> string*)letrecpp_dieccuhstrindentlevel(pp_children:bool)die1:string=(indent_levelindentlevel^("<"^(Nat_big_num.to_stringlevel^(">"^(pp_posdie1.die_offset^(": Abbrev Number: "^(Nat_big_num.to_stringdie1.die_abbreviation_code^(" ("^(pp_tag_encodingdie1.die_abbreviation_declaration.ad_tag^(")\n"^(letats=(Lem_list.list_combinedie1.die_abbreviation_declaration.ad_attribute_specificationsdie1.die_attribute_values)in(String.concat""(Lem_list.map(pp_die_attributeccuhstrindentlevel)ats))^(ifpp_childrenthenString.concat""(Lem_list.map(pp_dieccuhstrindent(Nat_big_num.addlevel((Nat_big_num.of_int1)))pp_children)die1.die_children)else""))))))))))))(*val pp_die_abbrev : p_context -> compilation_unit_header -> byte_sequence -> natural -> bool -> (list die) -> die -> string*)letrecpp_die_abbrevccuhstrlevel(pp_children:bool)parentsdie1:string=(indent_leveltruelevel^(pp_tag_encodingdie1.die_abbreviation_declaration.ad_tag^(" ("^(pp_posdie1.die_offset^(") "(* ^ ": Abbrev Number: " ^ show die.die_abbreviation_code *)^(((matchfind_name_of_diestrdie1withSomes->s|None->"-"))^(" : "^(String.concat" : "(Lem_list.map(fundie'->pp_tag_encodingdie'.die_abbreviation_declaration.ad_tag)parents)^("\n"^((*(String.concat "" (List.map (pp_die_abbrev_attribute c cuh str) ats))*)ifpp_childrenthenString.concat""(Lem_list.map(pp_die_abbrevccuhstr(Nat_big_num.addlevel((Nat_big_num.of_int1)))pp_children(die1::parents))die1.die_children)else""))))))))))(* condensed pp for variables *)(*val pp_die_abbrev_var : p_context -> dwarf -> compilation_unit -> byte_sequence -> bool -> (list die) -> die -> (string (*name*) * string (*offset*) * string (*kind*))*)letrecpp_die_abbrev_varcdcustr(pp_children:bool)parentsdie1:string*string*string=(* (indent_level true level*)(* ^ pp_tag_encoding die.die_abbreviation_declaration.ad_tag*)(* ^ ": Abbrev Number: " ^ show die.die_abbreviation_code *)(((matchfind_name_of_die_using_abstract_origincdcustrdie1with|Somes->s|None->"?")),pp_posdie1.die_offset,(ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_variable")then"var"elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_formal_parameter")then"param"else"other"))(* condensed pp for variable parents *)(*val pp_die_abbrev_var_parent : p_context -> dwarf -> compilation_unit -> byte_sequence -> die -> string*)letpp_die_abbrev_var_parentcdcustrdie1:string=((* (indent_level true level*)(* ^ pp_tag_encoding die.die_abbreviation_declaration.ad_tag*)(* ^ ": Abbrev Number: " ^ show die.die_abbreviation_code *)letname1=((matchfind_name_of_die_using_abstract_origincdcustrdie1withSomes->s|None->""))inletoffset=(pp_posdie1.die_offset)in(ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_compile_unit")thenname1elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subprogram")thenname1(*"subprogram"*)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_inlined_subroutine")thenname1^"(inlined)"elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_lexical_block")then"block"elsename1^("("^(pp_tag_encodingdie1.die_abbreviation_declaration.ad_tag^")"))))(*val pp_die_abbrev_var_parents : p_context -> dwarf -> compilation_unit -> byte_sequence -> list die -> string*)letpp_die_abbrev_var_parentscdcustrparents:string=(String.concat":"(Lem_list.map(fundie1->pp_die_abbrev_var_parentcdcustrdie1)parents))(* ^ " : " ^ String.concat " : " (List.map (fun die' -> pp_tag_encoding die'.die_abbreviation_declaration.ad_tag) parents)*)(* ^ "\n"*)(* ^ (*(String.concat "" (List.map (pp_die_abbrev_attribute c cuh str) ats))*)*)(* if pp_children then String.concat "" (List.map (pp_die_abbrev c cuh str (level +1) pp_children (die::parents)) die.die_children) else ""*)(*val parse_die : p_context -> byte_sequence -> compilation_unit_header -> (natural->abbreviation_declaration) -> parser (maybe die)*)letrecparse_diecstrcuhfind_abbreviation_declaration:parse_context->((die)option)parse_result=(fun(pc:parse_context)->(* let _ = my_debug3 ("parse_die called at " ^ pp_parse_context pc ^ "\n") in *)pr_bind(parse_ULEB128pc)(funabbreviation_codepc'->ifNat_big_num.equalabbreviation_code((Nat_big_num.of_int0))thenPR_success(None,pc')else(* let _ = my_debug3 ("parse_die abbreviation code "^pphex abbreviation_code ^"\n") in *)letad=(find_abbreviation_declarationabbreviation_code)inletattribute_value_parsers=(Lem_list.map(fun(at,af)->pr_with_pos(parser_of_attribute_formccuhaf))ad.ad_attribute_specifications)inpr_bind(parse_parser_listattribute_value_parserspc')(funavspc''->(*
let die_header =
<|
die_offset = pc.pc_offset;
die_abbreviation_code = abbreviation_code;
die_abbreviation_declaration = ad;
die_attribute_values = avs;
die_children = [];
|> in let _ = my_debug3 ("die_header " ^ pp_die cuh str true 999 die_header) in
*)pr_bind(ifad.ad_has_childrenthenparse_list(parse_diecstrcuhfind_abbreviation_declaration)pc''elsepr_return[]pc'')(fundiespc'''->PR_success((Some(letdie1=({die_offset=(pc.pc_offset);die_abbreviation_code=abbreviation_code;die_abbreviation_declaration=ad;die_attribute_values=avs;die_children=dies;})inlet_=(my_debug3("die entire "^pp_dieccuhstrtrue((Nat_big_num.of_int0))falsedie1))indie1)),pc''')))))lethas_attribute(an:string)(die1:die):bool=(Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dict(attribute_encodean)(Lem_list.mapfstdie1.die_abbreviation_declaration.ad_attribute_specifications))(** compilation units: pp and parsing *)letpp_compilation_unitc(indent:bool)(debug_str_section_body:byte_sequence0)cu:string=(""(* "*** compilation unit header ***\n"*)^(pp_compilation_unit_headercu.cu_header^("\n*** compilation unit abbreviation table\n"^(pp_abbreviations_tablecu.cu_abbreviations_table^("\n"^("*** compilation unit die tree\n"^(pp_dieccu.cu_headerdebug_str_section_bodyindent((Nat_big_num.of_int0))truecu.cu_die^"\n")))))))letpp_compilation_unitsc(indent:bool)debug_string_section_body(compilation_units1:compilation_unitlist):string=(String.concat""(Lem_list.map(pp_compilation_unitcindentdebug_string_section_body)compilation_units1))letpp_compilation_unit_abbrevc(debug_str_section_body:byte_sequence0)cu:string=(pp_compilation_unit_headercu.cu_header(* ^ pp_abbreviations_table cu.cu_abbreviations_table*)^pp_die_abbrevccu.cu_headerdebug_str_section_body((Nat_big_num.of_int0))true[]cu.cu_die)letpp_compilation_units_abbrevcdebug_string_section_body(compilation_units1:compilation_unitlist):string=(String.concat""(Lem_list.map(pp_compilation_unit_abbrevcdebug_string_section_body)compilation_units1))(*val add_die_to_index : die_index -> list die -> die -> die_index*)letrecadd_die_to_indexaccparentsdie1:((Nat_big_num.num),((die)list*die))Pmap.map=(letnacc:die_index=(Pmap.adddie1.die_offset(parents,die1)acc)inList.fold_left(funaccndie->add_die_to_indexacc(die1::parents)ndie)naccdie1.die_children)letparse_compilation_unitc(debug_str_section_body:byte_sequence0)(debug_abbrev_section_body:byte_sequence0):(compilation_unitoption)parser=(fun(pc:parse_context)->ifNat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0))thenPR_success(None,pc)elselet(cuh,pc')=((matchparse_compilation_unit_headercpcwith|PR_fail(s,pc')->failwith("parse_cuh_header fail: "^pp_parse_failspc')|PR_success(cuh,pc')->(cuh,pc')))in(*let _ = my_debug4 (pp_compilation_unit_header cuh) in*)ifNat_big_num.equalcuh.cuh_unit_length((Nat_big_num.of_int0))thenPR_success(None,pc')elseletpc_abbrev=({pc_bytes=((matchdropbytescuh.cuh_debug_abbrev_offsetdebug_abbrev_section_bodywithSuccessbs->bs|Fail_->failwith"mydrop of debug_abbrev"));pc_offset=(cuh.cuh_debug_abbrev_offset)})in(* todo: this is reparsing the abbreviations table for each cu *)letabbreviations_table1=((matchparse_abbreviations_tablecpc_abbrevwith|PR_fail(s,pc_abbrev')->failwith("parse_abbrevations_table fail: "^pp_parse_failspc_abbrev')|PR_success(at,pc_abbrev')->{at_offset=(pc_abbrev.pc_offset);at_table=at}))in(* let _ = my_debug4 (pp_abbreviations_table abbreviations_table) in *)letfind_abbreviation_declaration(ac:Nat_big_num.num):abbreviation_declaration=((* let _ = my_debug4 ("find_abbreviation_declaration "^pphex ac) in *)myfindNonPure(funad->Nat_big_num.equalad.ad_abbreviation_codeac)abbreviations_table1.at_table)in(* let _ = my_debug3 (pp_abbreviations_table abbreviations_table) in *)(matchparse_diecdebug_str_section_bodycuhfind_abbreviation_declarationpc'with|PR_fail(s,pc'')->failwith("parse_die fail: "^pp_parse_failspc'')|PR_success((None),pc'')->failwith("parse_die returned Nothing: "^pp_parse_contextpc'')|PR_success((Somedie1),pc'')->letcu=({cu_header=cuh;cu_abbreviations_table=abbreviations_table1;cu_die=die1;cu_index=(add_die_to_index(Pmap.emptyNat_big_num.compare)[]die1)})inPR_success((Somecu),pc'')))letparse_compilation_unitsc(debug_str_section_body:byte_sequence0)(debug_abbrev_section_body:byte_sequence0):(compilation_unitlist)parser=(parse_list(parse_compilation_unitcdebug_str_section_bodydebug_abbrev_section_body))(** type units: pp and parsing *)letpp_type_unitc(debug_str_section_body:byte_sequence0)tu:string=(pp_type_unit_headertu.tu_header^(pp_abbreviations_tabletu.tu_abbreviations_table^pp_diectu.tu_header.tuh_cuhdebug_str_section_bodytrue((Nat_big_num.of_int0))truetu.tu_die))letpp_type_unitscdebug_string_section_body(type_units1:type_unitlist):string=(String.concat""(Lem_list.map(pp_type_unitcdebug_string_section_body)type_units1))letparse_type_unitc(debug_str_section_body:byte_sequence0)(debug_abbrev_section_body:byte_sequence0):(type_unitoption)parser=(fun(pc:parse_context)->ifNat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0))thenPR_success(None,pc)elselet(tuh,pc')=((matchparse_type_unit_headercpcwith|PR_fail(s,pc')->failwith("parse_tuh_header fail: "^pp_parse_failspc')|PR_success(tuh,pc')->(tuh,pc')))in(* let _ = my_debug4 (pp_type_unit_header tuh) in *)letpc_abbrev=(letn=(tuh.tuh_cuh.cuh_debug_abbrev_offset)in{pc_bytes=((matchdropbytesndebug_abbrev_section_bodywithSuccessbs->bs|Fail_->failwith"mydrop of debug_abbrev"));pc_offset=n})inletabbreviations_table1=((matchparse_abbreviations_tablecpc_abbrevwith|PR_fail(s,pc_abbrev')->failwith("parse_abbrevations_table fail: "^pp_parse_failspc_abbrev')|PR_success(at,pc_abbrev')->{at_offset=(pc_abbrev.pc_offset);at_table=at}))in(* let _ = my_debug4 (pp_abbreviations_table abbreviations_table) in *)letfind_abbreviation_declaration(ac:Nat_big_num.num):abbreviation_declaration=((* let _ = my_debug4 ("find_abbreviation_declaration "^pphex ac) in *)myfindNonPure(funad->Nat_big_num.equalad.ad_abbreviation_codeac)abbreviations_table1.at_table)in(* let _ = my_debug3 (pp_abbreviations_table abbreviations_table) in *)(matchparse_diecdebug_str_section_bodytuh.tuh_cuhfind_abbreviation_declarationpc'with|PR_fail(s,pc'')->failwith("parse_die fail: "^pp_parse_failspc'')|PR_success((None),pc'')->failwith("parse_die returned Nothing: "^pp_parse_contextpc'')|PR_success((Somedie1),pc'')->lettu=({tu_header=tuh;tu_abbreviations_table=abbreviations_table1;tu_die=die1;})inPR_success((Sometu),pc'')))letparse_type_unitsc(debug_str_section_body:byte_sequence0)(debug_abbrev_section_body:byte_sequence0):(type_unitlist)parser=(parse_list(parse_type_unitcdebug_str_section_bodydebug_abbrev_section_body))(** location lists, pp and parsing *)(* readelf example
Contents of the .debug_loc section:
Offset Begin End Expression
00000000 0000000000400168 0000000000400174 (DW_OP_reg0 (r0))
00000000 0000000000400174 0000000000400184 (DW_OP_GNU_entry_value: (DW_OP_reg0 (r0)); DW_OP_stack_value)
00000000 <End of list>
00000039 000000000040017c 0000000000400180 (DW_OP_lit1; DW_OP_stack_value)
*)letpp_location_list_entryc(cuh:compilation_unit_header)(offset:Nat_big_num.num)(x:location_list_entry):string=(" "^(pphexoffset^(" "^(pphexx.lle_beginning_address_offset^(" "^(pphexx.lle_ending_address_offset^(" ("^(parse_and_pp_operationsccuhx.lle_single_location_description^(")"^"\n")))))))))letpp_base_address_selection_entryc(cuh:compilation_unit_header)(offset:Nat_big_num.num)(x:base_address_selection_entry):string=(" "^(pphexoffset^(" "^(pphexx.base_address^"\n"))))letpp_location_list_itemc(cuh:compilation_unit_header)(offset:Nat_big_num.num)(x:location_list_item):string=((matchxwith|LLI_llelle->pp_location_list_entryccuhoffsetlle|LLI_basebase->pp_base_address_selection_entryccuhoffsetbase))letpp_location_listc(cuh:compilation_unit_header)((offset:Nat_big_num.num),(llis:location_list_itemlist)):string=(String.concat""(Lem_list.map(pp_location_list_itemccuhoffset)llis))(* ^ " " ^ pphex offset ^ " <End of list>\n"*)letpp_locc(cuh:compilation_unit_header)(lls:location_listlist):string=(" Offset Begin End Expression\n"^String.concat""(Lem_list.map(pp_location_listccuh)lls))(* Note that this is just pp'ing the raw location list data - Section
3.1.1 says: The applicable base address of a location list entry is
determined by the closest preceding base address selection entry in
the same location list. If there is no such selection entry, then the
applicable base address defaults to the base address of the
compilation unit. That is handled by the interpret_location_list below *)letparse_location_list_itemc(cuh:compilation_unit_header):(location_list_itemoption)parser=(fun(pc:parse_context)->pr_bind(parse_pair(parse_uint_address_sizeccuh.cuh_address_size)(parse_uint_address_sizeccuh.cuh_address_size)pc)(fun((a1:Nat_big_num.num),(a2:Nat_big_num.num))pc'->(* let _ = my_debug4 ("offset="^pphex pc.pc_offset ^ " begin=" ^ pphex a1 ^ " end=" ^ pphex a2) in *)ifNat_big_num.equala1((Nat_big_num.of_int0))&&Nat_big_num.equala2((Nat_big_num.of_int0))thenPR_success(None,pc')elseifNat_big_num.equala1(max_addresscuh.cuh_address_size)thenletx=(LLI_base{(*base_offset=pc.pc_offset;*)base_address=a1})inPR_success((Somex(*(pc.pc_offset, x)*)),pc')elsepr_bind(parse_uint16cpc')(funnpc''->pr_post_map1(parse_n_bytesnpc'')(funbs->letx=(LLI_lle{(*lle_offset = pc.pc_offset;*)lle_beginning_address_offset=a1;lle_ending_address_offset=a2;lle_single_location_description=bs;})inSomex(*(pc.pc_offset, x)*)))))letparse_location_listccuh:(location_listoption)parser=(fun(pc:parse_context)->ifNat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0))thenPR_success(None,pc)elsepr_post_map1(parse_list(parse_location_list_itemccuh)pc)(funllis->(Some(pc.pc_offset,llis))))letparse_location_list_listccuh:location_list_listparser=(parse_list(parse_location_listccuh))letfind_location_listdlocn:location_list=(myfindNonPure(fun(n',_)->Nat_big_num.equaln'n)dloc)(* fails if location list not found *)(* interpretation of a location list applies the base_address and LLI_base offsets to give a list indexed by concrete address ranges *)letrecinterpret_location_list(base_address1:Nat_big_num.num)(llis:location_list_itemlist):(Nat_big_num.num*Nat_big_num.num*single_location_description)list=((matchlliswith|[]->[]|LLI_basebase::llis'->interpret_location_listbase.base_addressllis'|LLI_llelle::llis'->(Nat_big_num.addbase_address1lle.lle_beginning_address_offset,Nat_big_num.addbase_address1lle.lle_ending_address_offset,lle.lle_single_location_description)::interpret_location_listbase_address1llis'))(** range lists, pp and parsing *)(* example output from: aarch64-linux-gnu-objdump --dwarf=Ranges
Contents of the .debug_ranges section:
Offset Begin End
00000000 00000000004000fc 0000000000400114
00000000 000000000040011c 0000000000400128
00000000 <End of list>
...
00000380 0000000000400598 000000000040059c
00000380 00000000004005a0 00000000004005a4
00000380 00000000004005b4 00000000004005b8
00000380 00000000004005bc 00000000004005bc (start == end)
00000380 00000000004005c0 00000000004005c4
00000380 <End of list>
*)letpp_range_list_entryc(cuh:compilation_unit_header)(offset:Nat_big_num.num)(x:range_list_entry):string=(" "^(pphexoffset^(" "^(pphexx.rle_beginning_address_offset^(" "^(pphexx.rle_ending_address_offset^((ifNat_big_num.equalx.rle_beginning_address_offsetx.rle_ending_address_offsetthen" (start == end)"else"")^"\n")))))))letpp_range_list_itemc(cuh:compilation_unit_header)(offset:Nat_big_num.num)(x:range_list_item):string=((matchxwith|RLI_rlerle->pp_range_list_entryccuhoffsetrle|RLI_basebase->pp_base_address_selection_entryccuhoffsetbase))letpp_range_listc(cuh:compilation_unit_header)((offset:Nat_big_num.num),(rlis:range_list_itemlist)):string=(String.concat""(Lem_list.map(pp_range_list_itemccuhoffset)rlis)^(" "^(pphexoffset^" <End of list>\n")))letpp_rangesc(cuh:compilation_unit_header)(rls:range_listlist):string=(" Offset Begin End\n"^String.concat""(Lem_list.map(pp_range_listccuh)rls))(* Note that this is just pp'ing the raw range list data - see also
the interpret_range_list below *)letparse_range_list_itemc(cuh:compilation_unit_header):(range_list_itemoption)parser=(fun(pc:parse_context)->pr_bind(parse_pair(parse_uint_address_sizeccuh.cuh_address_size)(parse_uint_address_sizeccuh.cuh_address_size)pc)(fun((a1:Nat_big_num.num),(a2:Nat_big_num.num))pc'->(* let _ = my_debug4 ("offset="^pphex pc.pc_offset ^ " begin=" ^ pphex a1 ^ " end=" ^ pphex a2) in *)ifNat_big_num.equala1((Nat_big_num.of_int0))&&Nat_big_num.equala2((Nat_big_num.of_int0))thenPR_success(None,pc')elseifNat_big_num.equala1(max_addresscuh.cuh_address_size)thenletx=(RLI_base{base_address=a2})inPR_success((Somex),pc')elseletx=(RLI_rle{rle_beginning_address_offset=a1;rle_ending_address_offset=a2;})inPR_success((Somex(*(pc.pc_offset, x)*)),pc')))(* compiler output includes DW_AT_ranges attributes that point to proper suffixes of range lists. We support that by explicitly including each suffix - though one could be more efficient *)letrecexpand_range_list_suffixescuh(offset,(rlis:range_list_itemlist)):range_listlist=((matchrliswith|[]->[]|[rli]->[(offset,rlis)]|rli::rlis'->(offset,rlis)::expand_range_list_suffixescuh((Nat_big_num.addoffset(Nat_big_num.mul((Nat_big_num.of_int2))cuh.cuh_address_size)),rlis')))letparse_range_listccuh:((range_listlist)option)parser=(fun(pc:parse_context)->ifNat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0))thenPR_success(None,pc)elsepr_post_map1(parse_list(parse_range_list_itemccuh)pc)(funrlis->(Some(expand_range_list_suffixescuh(pc.pc_offset,rlis)))))letparse_range_list_listccuh:range_list_listparser=(pr_map2List.concat(parse_list(parse_range_listccuh)))letfind_range_listdrangesn:range_listoption=(Lem_list.list_find_opt(fun(n',_)->Nat_big_num.equaln'n)dranges)(* fails if range list not found *)(* interpretation of a range list applies the base_address and RLI_base offsets to give a list of concrete address ranges *)letrecinterpret_range_list(base_address1:Nat_big_num.num)(rlis:range_list_itemlist):(Nat_big_num.num*Nat_big_num.num)list=((matchrliswith|[]->[]|RLI_basebase::rlis'->interpret_range_listbase.base_addressrlis'|RLI_rlerle::rlis'->(Nat_big_num.addbase_address1rle.rle_beginning_address_offset,Nat_big_num.addbase_address1rle.rle_ending_address_offset)::interpret_range_listbase_address1rlis'))(** frame information, pp and parsing *)(* readelf example
Contents of the .debug_frame section:
00000000 0000000c ffffffff CIE
Version: 1
Augmentation: ""
Code alignment factor: 4
Data alignment factor: -8
Return address column: 65
DW_CFA_def_cfa: r1 ofs 0
00000010 00000024 00000000 FDE cie=00000000 pc=100000b0..10000120
DW_CFA_advance_loc: 8 to 100000b8
DW_CFA_def_cfa_offset: 80
DW_CFA_offset: r31 at cfa-8
DW_CFA_advance_loc: 4 to 100000bc
DW_CFA_def_cfa_register: r31
DW_CFA_advance_loc: 80 to 1000010c
DW_CFA_def_cfa: r1 ofs 0
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
DW_CFA_nop
00000038 00000024 00000000 FDE cie=00000000 pc=10000120..100001a4
DW_CFA_advance_loc: 16 to 10000130
DW_CFA_def_cfa_offset: 144
DW_CFA_offset_extended_sf: r65 at cfa+16
DW_CFA_offset: r31 at cfa-8
DW_CFA_advance_loc: 4 to 10000134
DW_CFA_def_cfa_register: r31
DW_CFA_advance_loc: 84 to 10000188
DW_CFA_def_cfa: r1 ofs 0
*)letpp_cfa_addressa:string=(pphexa)letpp_cfa_blockb:string=(ppbytesb)letpp_cfa_deltad:string=(pphexd)(*let pp_cfa_offset n = pphex n
let pp_cfa_register r = show r*)letpp_cfa_sfoffsetdict_Show_Show_ai:string=(dict_Show_Show_a.show_methodi)letpp_cfa_registerdict_Show_Show_ar:string=("r"^dict_Show_Show_a.show_methodr)(*TODO: arch-specific register names *)letpp_cfa_offset(i:Nat_big_num.num):string=(ifNat_big_num.equali((Nat_big_num.of_int0))then""elseifNat_big_num.lessi((Nat_big_num.of_int0))thenNat_big_num.to_stringielse"+"^Nat_big_num.to_stringi)letpp_cfa_rule(cr:cfa_rule):string=((matchcrwith|CR_undefined->"u"|CR_register(r,i)->pp_cfa_registerinstance_Show_Show_Num_natural_dictr^pp_cfa_offseti|CR_expressionbs->"exp"))letpp_register_rule(rr:register_rule):string=((*TODO make this more readelf-like *)(matchrrwith|RR_undefined->"u"|RR_same_value->"s"|RR_offseti->"c"^pp_cfa_offseti|RR_val_offseti->"val(c"^(pp_cfa_offseti^")")|RR_registerr->pp_cfa_registerinstance_Show_Show_Num_natural_dictr|RR_expressionbs->"exp"|RR_val_expressionbs->"val(exp)"|RR_architectural->""))letpp_call_frame_instructioni:string=((matchiwith|DW_CFA_advance_locd->"DW_CFA_advance_loc"^(" "^pp_cfa_deltad)|DW_CFA_offset(r,n)->"DW_CFA_offset"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_offset(n))))|DW_CFA_restorer->"DW_CFA_restore"^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr)|DW_CFA_nop->"DW_CFA_nop"|DW_CFA_set_loca->"DW_CFA_set_loc"^(" "^pp_cfa_addressa)|DW_CFA_advance_loc1d->"DW_CFA_advance_loc1"^(" "^pp_cfa_deltad)|DW_CFA_advance_loc2d->"DW_CFA_advance_loc2"^(" "^pp_cfa_deltad)|DW_CFA_advance_loc4d->"DW_CFA_advance_loc4"^(" "^pp_cfa_deltad)|DW_CFA_offset_extended(r,n)->"DW_CFA_offset_extended"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_offset(n))))|DW_CFA_restore_extendedr->"DW_CFA_restore_extended"^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr)|DW_CFA_undefinedr->"DW_CFA_undefined"^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr)|DW_CFA_same_valuer->"DW_CFA_same_value"^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr)|DW_CFA_register(r1,r2)->"DW_CFA_register"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr1^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr2)))|DW_CFA_remember_state->"DW_CFA_remember_state"|DW_CFA_restore_state->"DW_CFA_restore_state"|DW_CFA_def_cfa(r,n)->"DW_CFA_def_cfa"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_offset(n))))|DW_CFA_def_cfa_registerr->"DW_CFA_def_cfa_register"^(" "^pp_cfa_registerinstance_Show_Show_Num_natural_dictr)|DW_CFA_def_cfa_offsetn->"DW_CFA_def_cfa_offset"^(" "^pp_cfa_offset(n))|DW_CFA_def_cfa_expressionb->"DW_CFA_def_cfa_expression"^(" "^pp_cfa_blockb)|DW_CFA_expression(r,b)->"DW_CFA_expression"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_blockb)))|DW_CFA_offset_extended_sf(r,i)->"DW_CFA_offset_extended_sf"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_sfoffsetinstance_Show_Show_Num_integer_dicti)))|DW_CFA_def_cfa_sf(r,i)->"DW_CFA_def_cfa_sf"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_sfoffsetinstance_Show_Show_Num_integer_dicti)))|DW_CFA_def_cfa_offset_sfi->"DW_CFA_def_cfa_offset_sf"^(" "^pp_cfa_sfoffsetinstance_Show_Show_Num_integer_dicti)|DW_CFA_val_offset(r,n)->"DW_CFA_val_offset"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_offset(n))))|DW_CFA_val_offset_sf(r,i)->"DW_CFA_val_offset_sf"^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_sfoffsetinstance_Show_Show_Num_integer_dicti))|DW_CFA_val_expression(r,b)->"DW_CFA_val_expression"^(" "^(pp_cfa_registerinstance_Show_Show_Num_natural_dictr^(" "^pp_cfa_blockb)))|DW_CFA_AARCH64_negate_ra_state->"DW_CFA_AARCH64_negate_ra_state"|DW_CFA_unknownbt->"DW_CFA_unknown"^(" "^hex_string_of_bytebt)))letpp_call_frame_instructionsis:string=(String.concat""(Lem_list.map(funi->" "^(pp_call_frame_instructioni^"\n"))is))letparser_of_call_frame_argument_typeccuh(cfat:call_frame_argument_type):call_frame_argument_valueparser=((matchcfatwith|CFAT_address->pr_map2(funn->CFAV_addressn)(parse_uint_address_sizeccuh.cuh_address_size)|CFAT_delta1->pr_map2(funn->CFAV_deltan)(parse_uint8)|CFAT_delta2->pr_map2(funn->CFAV_deltan)(parse_uint16c)|CFAT_delta4->pr_map2(funn->CFAV_deltan)(parse_uint32c)|CFAT_delta_ULEB128->pr_map2(funn->CFAV_deltan)(parse_ULEB128)|CFAT_offset->pr_map2(funn->CFAV_offsetn)(parse_ULEB128)|CFAT_sfoffset->pr_map2(funn->CFAV_sfoffsetn)(parse_SLEB128)|CFAT_register->pr_map2(funn->CFAV_registern)(parse_ULEB128)|CFAT_block->(funpc->pr_bind(parse_ULEB128pc)(funnpc'->pr_map(funbs->CFAV_blockbs)(parse_n_bytesnpc')))))letparse_call_frame_instructionccuh:(call_frame_instructionoption)parser=(funpc->(matchread_charpc.pc_byteswith|Fail_->PR_success(None,pc)|Success(b,bs')->letpc'=({pc_bytes=bs';pc_offset=(Nat_big_num.addpc.pc_offset((Nat_big_num.of_int1)))})inletch=(Uint32_wrapper.of_int(Char.codeb))inlethigh_bits=(Uint32_wrapper.logandch(Uint32_wrapper.of_bigint((Nat_big_num.of_int192))))inletlow_bits=(Uint32_wrapper.to_bigint(Uint32_wrapper.logandch(Uint32_wrapper.of_bigint((Nat_big_num.of_int63)))))inifhigh_bits=Uint32_wrapper.of_bigint((Nat_big_num.of_int0))then(matchlookup_abCde_deinstance_Basic_classes_Eq_Num_natural_dictlow_bitscall_frame_instruction_encodingwith|Some((args:call_frame_argument_typelist),result)->letps=(Lem_list.map(parser_of_call_frame_argument_typeccuh)args)inletp=(pr_post_map(parse_parser_listps)result)in(matchppc'with|PR_success((Somecfi),pc'')->PR_success((Somecfi),pc'')|PR_success((None),pc'')->failwith"bad call frame instruction argument 1"|PR_fail(s,pc'')->failwith"bad call frame instruction argument 2")|None->(*Assert_extra.failwith ("can't parse " ^ show b ^ " as call frame instruction")*)PR_success((Some(DW_CFA_unknownb)),pc'))elseifhigh_bits=Uint32_wrapper.of_bigint((Nat_big_num.of_int64))thenPR_success((Some(DW_CFA_advance_loclow_bits)),pc')elseifhigh_bits=Uint32_wrapper.of_bigint((Nat_big_num.of_int192))thenPR_success((Some(DW_CFA_restorelow_bits)),pc')elseletp=(parser_of_call_frame_argument_typeccuhCFAT_offset)in(matchppc'with|PR_success((CFAV_offsetn),pc'')->PR_success((Some(DW_CFA_offset(low_bits,n))),pc'')|PR_success(_,pc'')->failwith"bad call frame instruction argument 3"|PR_fail(s,pc'')->failwith"bad call frame instruction argument 4")))letparse_call_frame_instructionsccuh:(call_frame_instructionlist)parser=(parse_list(parse_call_frame_instructionccuh))(*val parse_and_pp_call_frame_instructions : p_context -> compilation_unit_header -> byte_sequence -> string*)letparse_and_pp_call_frame_instructionsccuhbs:string=(letpc=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_call_frame_instructionsccuhpcwith|PR_fail(s,pc')->"parse_call_frame_instructions fail: "^pp_parse_failspc'|PR_success(is,pc')->pp_call_frame_instructionsis^(ifnot(Nat_big_num.equal(Byte_sequence.length0pc'.pc_bytes)((Nat_big_num.of_int0)))then" Warning: extra non-parsed bytes"else"")))letpp_call_frame_instructions'ccuhbs:string=((* ppbytes bs ^ "\n" *)parse_and_pp_call_frame_instructionsccuhbs)letpp_cieccuhcie1:string=(pphexcie1.cie_offset^(" "^(pphexcie1.cie_length^(" "^(pphexcie1.cie_id^(" CIE\n"^(" Version: "^(Nat_big_num.to_stringcie1.cie_version^("\n"^(" Augmentation: \""^(string_of_string(string_of_byte_sequencecie1.cie_augmentation)^("\"\n"^(" Code alignment factor: "^(Nat_big_num.to_stringcie1.cie_code_alignment_factor^("\n"^(" Data alignment factor: "^(Nat_big_num.to_stringcie1.cie_data_alignment_factor^("\n"^(" Return address column: "^(Nat_big_num.to_stringcie1.cie_return_address_register^("\n"^("\n"^(ppbytescie1.cie_initial_instructions_bytes^("\n"^pp_call_frame_instructionscie1.cie_initial_instructions))))))))))))))))))))))))(* cie_address_size: natural; (* not shown by readelf - must match compilation unit *)*)(* cie_segment_size: natural; (* not shown by readelf *)*)(* readelf says "Return address column", but the DWARF spec says "Return address register" *)letpp_fdeccuhfde1:string=(pphexfde1.fde_offset^(" "^(pphexfde1.fde_length^(" "^(pphexfde1.fde_cie_pointer(* not what this field of readelf output is *)^(" FDE"^(" cie="^(pphexfde1.fde_cie_pointer(* duplicated?? *)^(" pc="^((matchfde1.fde_initial_location_segment_selectorwithNone->""|Somesegment_selector->"("^(pphexsegment_selector^")"))^(pphexfde1.fde_initial_location_address^(".."^(pphex(Nat_big_num.addfde1.fde_initial_location_addressfde1.fde_address_range)^("\n"^(ppbytesfde1.fde_instructions_bytes^("\n"^pp_call_frame_instructionsfde1.fde_instructions))))))))))))))))letpp_frame_info_elementccuhfie:string=((matchfiewith|FIE_ciecie1->pp_cieccuhcie1|FIE_fdefde1->pp_fdeccuhfde1))letpp_frame_infoccuhfi:string=("Contents of the .debug_frame section:\n\n"^(String.concat"\n"(Lem_list.map(pp_frame_info_elementccuh)fi)^"\n"))letrecfind_cieficie_id1:cie=((matchfiwith|[]->failwith"find_cie: cie_id not found"|FIE_fde_::fi'->find_ciefi'cie_id1|FIE_ciecie1::fi'->ifNat_big_num.equalcie_id1cie1.cie_offsetthencie1elsefind_ciefi'cie_id1))letparse_initial_locationccuhmssmas':((Nat_big_num.numoption)*Nat_big_num.num)parser=((*(segment selector and target address)*)(* assume segment selector size is zero unless given explicitly. Probably we need to do something architecture-specific for earlier dwarf versions?*)parse_pair(parse_uint_segment_selector_sizec((matchmsswithSomen->n|None->(Nat_big_num.of_int0))))(parse_uint_address_sizec((matchmas'withSomen->n|None->cuh.cuh_address_size))))letparse_call_frame_instruction_bytesoffset'ul:parse_context->(Byte_sequence_wrapper.byte_sequence)parse_result=(fun(pc:parse_context)->parse_n_bytes(Nat_big_num.sub_natul(Nat_big_num.sub_natpc.pc_offsetoffset'))pc)letparse_frame_info_elementccuh(fi:frame_info_elementlist):frame_info_elementparser=(parse_dependent(pr_with_pos(parse_dependent_pair(parse_unit_lengthc)(fun(df,ul)->pr_with_pos(parse_uintDwarfNcdf)(* CIE_id (cie) or CIE_pointer (fde) *))))(fun(offset,((df,ul),(offset',cie_id1)))->if(Nat_big_num.equalcie_id1(matchdfwith|Dwarf32->natural_of_hex"0xffffffff"|Dwarf64->natural_of_hex"0xffffffffffffffff"))then(* parse cie *)pr_post_map(parse_pair(parse_dependent_pairparse_uint8(* version *)(funv->parse_tripleparse_string(* augmentation *)(ifNat_big_num.equalv((Nat_big_num.of_int4))||Nat_big_num.equalv((Nat_big_num.of_int46))thenpr_post_mapparse_uint8(funi->Somei)elsepr_returnNone)(* address_size *)(ifNat_big_num.equalv((Nat_big_num.of_int4))||Nat_big_num.equalv((Nat_big_num.of_int46))thenpr_post_mapparse_uint8(funi->Somei)elsepr_returnNone)))(* segment_size *)(parse_quadrupleparse_ULEB128(* code_alignment_factor *)parse_SLEB128(* data_alignment_factor *)parse_ULEB128(* return address register *)(parse_call_frame_instruction_bytesoffset'ul)))(fun((v,(aug,(mas',mss))),(caf,(daf,(rar,bs))))->letpc=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_call_frame_instructionsccuhpcwith|PR_success(is,_)->FIE_cie({cie_offset=offset;cie_length=ul;cie_id=cie_id1;cie_version=v;cie_augmentation=aug;cie_address_size=mas';cie_segment_size=mss;cie_code_alignment_factor=caf;cie_data_alignment_factor=daf;cie_return_address_register=rar;cie_initial_instructions_bytes=bs;cie_initial_instructions=is;})|PR_fail(s,_)->failwiths))else(* parse fde *)letcie1=(find_cieficie_id1)in(* let _ = my_debug4 (pp_cie c cuh cie) in *)pr_post_map(parse_triple(parse_initial_locationccuhcie1.cie_segment_sizecie1.cie_address_size)(*(segment selector and target address)*)(parse_uint_address_sizec((matchcie1.cie_address_sizewithSomen->n|None->cuh.cuh_address_size)))(* address_range (target address) *)(parse_call_frame_instruction_bytesoffset'ul))(fun((ss,adr),(ar,bs))->letpc=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_call_frame_instructionsccuhpcwith|PR_success(is,_)->FIE_fde({fde_offset=offset;fde_length=ul;fde_cie_pointer=cie_id1;fde_initial_location_segment_selector=ss;fde_initial_location_address=adr;fde_address_range=ar;fde_instructions_bytes=bs;fde_instructions=is;})|PR_fail(s,_)->failwiths))))(* you can't even parse an fde without accessing the cie it refers to
(to determine the segment selector size). Gratuitous complexity or what?
Hence the following, which should be made more tail-recursive. *)(*val parse_dependent_list' : forall 'a. (list 'a -> parser 'a) -> list 'a -> parser (list 'a)*)letrecparse_dependent_list'p1acc:parse_context->('alist)parse_result=(funpc->ifNat_big_num.equal(Byte_sequence.length0pc.pc_bytes)((Nat_big_num.of_int0))thenPR_success((List.revacc),pc)elsepr_bind(p1accpc)(funxpc'->parse_dependent_list'p1(x::acc)pc'))(*val parse_dependent_list : forall 'a. (list 'a -> parser 'a) -> parser (list 'a)*)letparse_dependent_listp1:parse_context->('alist)parse_result=(parse_dependent_list'p1[])letparse_frame_infoccuh:frame_infoparser=(parse_dependent_list(parse_frame_info_elementccuh))(** line numbers .debug_line, pp and parsing *)letpp_line_number_file_entrylnfe:string=("lnfe_path = "^(string_of_byte_sequencelnfe.lnfe_path^("\n"^("lnfe_directory_index "^(Nat_big_num.to_stringlnfe.lnfe_directory_index^("\n"^("lnfe_last_modification = "^(Nat_big_num.to_stringlnfe.lnfe_last_modification^("\n"^("lnfe_length = "^(Nat_big_num.to_stringlnfe.lnfe_length^"\n")))))))))))letpp_line_number_headerlnh:string=("offset = "^(pphexlnh.lnh_offset^("\n"^("dwarf_format = "^(pp_dwarf_formatlnh.lnh_dwarf_format^("\n"^("unit_length = "^(Nat_big_num.to_stringlnh.lnh_unit_length^("\n"^("version = "^(Nat_big_num.to_stringlnh.lnh_version^("\n"^("header_length = "^(Nat_big_num.to_stringlnh.lnh_header_length^("\n"^("minimum_instruction_length = "^(Nat_big_num.to_stringlnh.lnh_minimum_instruction_length^("\n"^("maximum_operations_per_instruction = "^(Nat_big_num.to_stringlnh.lnh_maximum_operations_per_instruction^("\n"^("default_is_stmt = "^(string_of_boollnh.lnh_default_is_stmt^("\n"^("line_base = "^(Nat_big_num.to_stringlnh.lnh_line_base^("\n"^("line_range = "^(Nat_big_num.to_stringlnh.lnh_line_range^("\n"^("opcode_base = "^(Nat_big_num.to_stringlnh.lnh_opcode_base^("\n"^("standard_opcode_lengths = "^(string_of_listinstance_Show_Show_Num_natural_dictlnh.lnh_standard_opcode_lengths^("\n"^("comp_dir = "^(string_of_maybeinstance_Show_Show_string_dictlnh.lnh_comp_dir^("\n"^("include_directories = "^(String.concat", "(Lem_list.mapstring_of_byte_sequencelnh.lnh_include_directories)^("\n"^("file_entries = \n\n"^(String.concat"\n"(Lem_list.mappp_line_number_file_entrylnh.lnh_file_entries)^"\n"))))))))))))))))))))))))))))))))))))))))))))letpp_line_number_operationlno:string=((matchlnowith|DW_LNS_copy->"DW_LNS_copy"|DW_LNS_advance_pcn->"DW_LNS_advance_pc"^(" "^Nat_big_num.to_stringn)|DW_LNS_advance_linei->"DW_LNS_advance_line"^(" "^Nat_big_num.to_stringi)|DW_LNS_set_filen->"DW_LNS_set_file"^(" "^Nat_big_num.to_stringn)|DW_LNS_set_columnn->"DW_LNS_set_column"^(" "^Nat_big_num.to_stringn)|DW_LNS_negate_stmt->"DW_LNS_negate_stmt"|DW_LNS_set_basic_block->"DW_LNS_set_basic_block"|DW_LNS_const_add_pc->"DW_LNS_const_add_pc"|DW_LNS_fixed_advance_pcn->"DW_LNS_fixed_advance_pc"^(" "^Nat_big_num.to_stringn)|DW_LNS_set_prologue_end->"DW_LNS_set_prologue_end"|DW_LNS_set_epilogue_begin->"DW_LNS_set_epilogue_begin"|DW_LNS_set_isan->"DW_LNS_set_isa"^(" "^Nat_big_num.to_stringn)|DW_LNE_end_sequence->"DW_LNE_end_sequence"|DW_LNE_set_addressn->"DW_LNE_set_address"^(" "^pphexn)|DW_LNE_define_file(s,n1,n2,n3)->"DW_LNE_define_file"^(" "^(Byte_sequence_wrapper.to_strings^(" "^(Nat_big_num.to_stringn1^(" "^(Nat_big_num.to_stringn2^(" "^Nat_big_num.to_stringn3)))))))|DW_LNE_set_discriminatorn->"DW_LNE_set_discriminator"^(" "^Nat_big_num.to_stringn)|DW_LN_specialn->"DW_LN_special"^(" "^Nat_big_num.to_stringn)))letpp_line_number_programlnp:string=(pp_line_number_headerlnp.lnp_header^("["^(String.concat", "(Lem_list.mappp_line_number_operationlnp.lnp_operations)^"]\n")))letparse_line_number_file_entry:(line_number_file_entryoption)parser=(parse_dependent(parse_non_empty_string)(funms->(matchmswith|None->pr_returnNone|Somes->pr_post_map(parse_tripleparse_ULEB128parse_ULEB128parse_ULEB128)(fun(n1,(n2,n3))->(Some{lnfe_path=s;lnfe_directory_index=n1;lnfe_last_modification=n2;lnfe_length=n3;})))))letparse_line_number_headerc(comp_dir:stringoption):line_number_headerparser=(parse_dependent((pr_with_pos(parse_unit_lengthc)))(fun(pos,(df,ul))->(*
parse_dependent_pair
(parse_pair
(parse_triple
(parse_uint16 c) (* version *)
(parse_uintDwarfN c df) (* header_length *)
(parse_uint8) (* minimum_instruction_length *)
(* (parse_uint8) (* maximum_operations_per_instruction NOT IN DWARF 2*)*)
)
(parse_quadruple
(parse_uint8) (* default_is_stmt *)
(parse_sint8) (* line_base *)
(parse_uint8) (* line_range *)
(parse_uint8) (* opcode_base *)
))
(fun ((v,(hl,(minil(*,maxopi*)))),(dis,(lb,(lr,ob)))) ->
*)(parse_dependent(parse_dependent_pair(parse_uint16c)(* version *)(funv->(parse_pair(parse_triple(parse_uintDwarfNcdf)(* header_length *)(parse_uint8)(* minimum_instruction_length *)(ifNat_big_num.lessv((Nat_big_num.of_int4))then(* maximum_operations_per_instruction*)(* NOT IN DWARF 2 or 3; in DWARF 4*)(parse_uint8_constant((Nat_big_num.of_int1)))else(parse_uint8)))(parse_quadruple(parse_uint8)(* default_is_stmt *)(parse_sint8)(* line_base *)(parse_uint8)(* line_range *)(parse_uint8)(* opcode_base *)))))(fun((v,(((hl,(minil,maxopi))),(dis,(lb,(lr,ob))))))->pr_post_map(parse_triple(pr_post_map(parse_n_bytes(Nat_big_num.sub_natob((Nat_big_num.of_int1))))(funbs->Lem_list.mapnatural_of_byte(byte_list_of_byte_sequencebs)))(* standard_opcode_lengths *)((*pr_return [[]]*)parse_listparse_non_empty_string)(* include_directories *)(parse_listparse_line_number_file_entry)(* file names *))(fun(sols,(ids,fns))->{lnh_offset=pos;lnh_dwarf_format=df;lnh_unit_length=ul;lnh_version=v;lnh_header_length=hl;lnh_minimum_instruction_length=minil;lnh_maximum_operations_per_instruction=maxopi;lnh_default_is_stmt=(not(Nat_big_num.equaldis((Nat_big_num.of_int0))));lnh_line_base=lb;lnh_line_range=lr;lnh_opcode_base=ob;lnh_standard_opcode_lengths=sols;lnh_include_directories=ids;lnh_file_entries=fns;lnh_comp_dir=comp_dir;})))))letparser_of_line_number_argument_typec(cuh:compilation_unit_header)(lnat:line_number_argument_type):line_number_argument_valueparser=((matchlnatwith|LNAT_address->pr_map2(funn->LNAV_addressn)(parse_uint_address_sizeccuh.cuh_address_size)|LNAT_ULEB128->pr_map2(funn->LNAV_ULEB128n)(parse_ULEB128)|LNAT_SLEB128->pr_map2(funi->LNAV_SLEB128i)(parse_SLEB128)|LNAT_uint16->pr_map2(funn->LNAV_uint16n)(parse_uint16c)|LNAT_string->pr_map2(funs->LNAV_strings)(parse_string)))letparse_line_number_operationc(cuh:compilation_unit_header)(lnh:line_number_header):line_number_operationparser=(parse_dependentparse_uint8(funopcode->ifNat_big_num.equalopcode((Nat_big_num.of_int0))then(* parse extended opcode *)parse_dependent(parse_pairparse_ULEB128parse_uint8)(fun(size2,opcode')->(matchlookup_aBcd_acdinstance_Basic_classes_Eq_Num_natural_dictopcode'line_number_extended_encodingswith|Some(_,arg_types,result)->letps=(Lem_list.map(parser_of_line_number_argument_typeccuh)arg_types)inparse_demaybe("parse_line_number_operation fail")(pr_post_map(parse_parser_listps)result)|None->failwith("parse_line_number_operation extended opcode not found: "^Nat_big_num.to_stringopcode')))(* it's not clear what the ULEB128 size field is for, as the extended opcides all seem to have well-defined sizes. perhaps there can be extra padding that needs to be absorbed? *)elseifNat_big_num.greater_equalopcodelnh.lnh_opcode_basethen(* parse special opcode *)letadjusted_opcode=(Nat_big_num.sub_natopcodelnh.lnh_opcode_base)inpr_return(DW_LN_specialadjusted_opcode)else(* parse standard opcode *)(matchlookup_aBcd_acdinstance_Basic_classes_Eq_Num_natural_dictopcodeline_number_standard_encodingswith|Some(_,arg_types,result)->letps=(Lem_list.map(parser_of_line_number_argument_typeccuh)arg_types)inparse_demaybe("parse_line_number_operation fail")(pr_post_map(parse_parser_listps)result)|None->failwith("parse_line_number_operation standard opcode not found: "^Nat_big_num.to_stringopcode)(* the standard_opcode_lengths machinery is intended to allow vendor specific extension instructions to be parsed and ignored, but here we couldn't usefully process such instructions in any case, so we just fail *))))letparse_line_number_operationsc(cuh:compilation_unit_header)(lnh:line_number_header):(line_number_operationlist)parser=(parse_list(parse_maybe(parse_line_number_operationccuhlnh)))(* assume operations start immediately after the header - not completely clear in DWARF whether the header_length is just an optimisation or whether it's intended to allow the operations to start later *)(* line number operations have no no-op and no termination operation, so we have to cut down the available bytes to the right length *)letparse_line_number_programc(cuh:compilation_unit_header)(comp_dir:stringoption):line_number_programparser=(parse_dependent(parse_line_number_headerccomp_dir)(funlnh->letbyte_count_of_operations=(Nat_big_num.sub_natlnh.lnh_unit_length(Nat_big_num.add(Nat_big_num.addlnh.lnh_header_length((Nat_big_num.of_int2)))((matchlnh.lnh_dwarf_formatwithDwarf32->(Nat_big_num.of_int4)|Dwarf64->(Nat_big_num.of_int8)))))inpr_post_map(parse_restrict_lengthbyte_count_of_operations(parse_line_number_operationsccuhlnh))(funops->{lnp_header=lnh;lnp_operations=ops;})))(*TODO: this should use find_natural_attribute_value_of_die *)letline_number_offset_of_compilation_unitccu:Nat_big_num.num=((matchfind_attribute_value"DW_AT_stmt_list"cu.cu_diewith|Some(AV_sec_offsetn)->n|Some(AV_block(n,bs))->natural_of_bytesc.endiannessbs(* a 32-bit MIPS example used a 4-byte AV_block not AV_sec_offset *)|Some_->(failwith("compilation unit DW_AT_stmt_list attribute was not an AV_sec_offset"^pp_compilation_unit_headercu.cu_header))|_->failwith("compilation unit did not have a DW_AT_stmt_list attribute\n"^(pp_compilation_unit_headercu.cu_header^"\n"))))letline_number_program_of_compilation_unitdcu:line_number_program=(letc=(p_context_of_dd)inletoffset=(line_number_offset_of_compilation_unitccu)in(matchLem_list.list_find_opt(funlnp->Nat_big_num.equallnp.lnp_header.lnh_offsetoffset)d.d_line_infowith|None->failwith"compilation unit line number offset not found"|Somelnp->lnp))letfilenamedcun:(string)option=(letlnp=(line_number_program_of_compilation_unitdcu)inifNat_big_num.equaln((Nat_big_num.of_int0))thenNoneelse(matchmynth(Nat_big_num.sub_natn((Nat_big_num.of_int1)))lnp.lnp_header.lnh_file_entrieswith|Somelnfe->Some(string_of_byte_sequencelnfe.lnfe_path)|None->failwith("line number file entry not found")))letunpack_file_entrylnhfile:unpacked_file_entry=((matchmynth(Nat_big_num.sub_natfile((Nat_big_num.of_int1)))lnh.lnh_file_entrieswith|Somelnfe->letdirectory=(ifNat_big_num.equallnfe.lnfe_directory_index((Nat_big_num.of_int0))thenNoneelse(matchmynth(Nat_big_num.sub_natlnfe.lnfe_directory_index((Nat_big_num.of_int1)))lnh.lnh_include_directorieswith|Somed->Some(string_of_byte_sequenced)|None->Some"<unpack_file_entry: directory entry not found>"))in(lnh.lnh_comp_dir,directory,string_of_byte_sequencelnfe.lnfe_path)|None->(None,None,"<unpack_file_entry: file entry not found>")))letpp_ufe(((mcomp_dir,mdir,file)asufe):unpacked_file_entry):string=(file^(" dir="^((matchmdirwith|Somes->s|None->"<none>")^(" comp_dir="^(matchmcomp_dirwith|Somes->s|None->"<none>")))))letpp_ud(((((mcomp_dir,mdir,file)asufe):unpacked_file_entry),(line:int),(subprogram_name:string)):unpacked_decl):string=(file^(":"^(Stdlib.string_of_intline^(" "^(subprogram_name^(" dir="^((matchmdirwith|Somes->s|None->"<none>")^(" comp_dir="^(matchmcomp_dirwith|Somes->s|None->"<none>")))))))))letpp_ufe_brief(((mcomp_dir,mdir,file)asufe):unpacked_file_entry):string=file(*
^ " dir=" ^ match mdir with | Just s->s|Nothing->"<none>" end
^ " comp_dir=" ^ match mcomp_dir with | Just s->s|Nothing->"<none>" end
*)letparse_line_number_infocstr(d_line:byte_sequence0)(cu:compilation_unit):line_number_program=(letcomp_dir=(find_string_attribute_value_of_die"DW_AT_comp_dir"strcu.cu_die)inletfn=(letd_line'=((matchdropbytesnd_linewithSuccessxs->xs|Fail_->failwith"parse_line_number_info drop"))inletpc=({pc_bytes=d_line';pc_offset=n})in(matchparse_line_number_programccu.cu_headercomp_dirpcwith|PR_success(lnp,pc')->(*let _ = print_endline (pp_line_number_program lnp) in*)lnp|PR_fail(s,pc')->failwith("parse_line_number_header failed: "^s)))inf(line_number_offset_of_compilation_unitccu))letparse_line_number_infoscstrdebug_line_section_bodycompilation_units1:(line_number_program)list=(Lem_list.map(parse_line_number_infocstrdebug_line_section_body)compilation_units1)letpp_line_infoli:string=(String.concat"\n"(Lem_list.map(pp_line_number_program)li))(** all dwarf info: pp and parsing *)(* roughly matching objdump --dwarf=abbrev,info *)letpp_dwarf_like_objdumpd:string=(letc=(p_context_of_dd)in""(* ^ "\n*** compilation unit abbreviation table ***\n" *)^("Contents of the .debug_abbrev section:\n\n"^(" Number TAG (0x0)\n"^(pp_abbreviations_tablesd(* ^ "\n*** compilation unit die tree ***\n"*)(* "\n************** .debug_info section - abbreviated *****************\n"
^ pp_compilation_units_abbrev c d.d_str d.d_compilation_units
^*)(* ^"\n************** .debug_info section - full ************************\n"*)^("\nContents of the .debug_info section:\n\n"^pp_compilation_unitscfalse(*false for no indent, like objdump; true for nice indent *)d.d_strd.d_compilation_units)))))letpp_dwarfd:string=(letc=(p_context_of_dd)in(* "\n************** .debug_info section - abbreviated *****************\n"
^ pp_compilation_units_abbrev c d.d_str d.d_compilation_units
^*)"\n************** .debug_info section - full ************************\n"^(pp_compilation_unitsctrued.d_strd.d_compilation_units^("\n************** .debug_loc section: location lists ****************\n"^(let(cuh_default:compilation_unit_header)=(letcu=(myheadd.d_compilation_units)incu.cu_header)inpp_locccuh_defaultd.d_loc^("\n************** .debug_ranges section: range lists ****************\n"^(pp_rangesccuh_defaultd.d_ranges^("\n************** .debug_frame section: frame info ****************\n"^(pp_frame_infoccuh_defaultd.d_frame_info^("\n************** .debug_line section: line number info ****************\n"^pp_line_infod.d_line_info)))))))))(* TODO: don't use lists of bytes here! *)letparse_dwarfc(debug_info_section_body:byte_sequence0)(debug_abbrev_section_body:byte_sequence0)(debug_str_section_body:byte_sequence0)(debug_loc_section_body:byte_sequence0)(debug_ranges_section_body:byte_sequence0)(debug_frame_section_body:byte_sequence0)(debug_line_section_body:byte_sequence0):dwarf=(letpc_info=({pc_bytes=debug_info_section_body;pc_offset=((Nat_big_num.of_int0))})inletcompilation_units1=((matchparse_compilation_unitscdebug_str_section_bodydebug_abbrev_section_bodypc_infowith|PR_fail(s,pc_info')->failwith("parse_compilation_units: "^pp_parse_failspc_info')|PR_success(cus,pc_info')->cus))in(*let _ = my_debug5 (pp_compilation_units c debug_str_section_body compilation_units) in*)(* the DWARF4 spec doesn't seem to specify the address size used in the .debug_loc section, so we (hackishly) take it from the first compilation unit *)let(cuh_default:compilation_unit_header)=(letcu=(myheadcompilation_units1)incu.cu_header)inletpc_loc=({pc_bytes=debug_loc_section_body;pc_offset=((Nat_big_num.of_int0))})inletloc=((matchparse_location_list_listccuh_defaultpc_locwith|PR_fail(s,pc_info')->failwith("parse_location_list: "^pp_parse_failspc_info')|PR_success(loc,pc_loc')->loc))inletpc_ranges=({pc_bytes=debug_ranges_section_body;pc_offset=((Nat_big_num.of_int0))})inletranges=((matchparse_range_list_listccuh_defaultpc_rangeswith|PR_fail(s,pc_info')->failwith("parse_range_list: "^pp_parse_failspc_info')|PR_success(r,pc_loc')->r))inletpc_frame=({pc_bytes=debug_frame_section_body;pc_offset=((Nat_big_num.of_int0))})inletfi=((* let _ = my_debug5 ("debug_frame_section_body:\n" ^ ppbytes2 0 debug_frame_section_body) in *)(matchparse_frame_infoccuh_defaultpc_framewith|PR_fail(s,pc_info')->failwith("parse_frame_info: "^pp_parse_failspc_info')|PR_success(fi,pc_loc')->fi))inletli=(parse_line_number_infoscdebug_str_section_bodydebug_line_section_bodycompilation_units1)in{d_endianness=(c.endianness);d_str=debug_str_section_body;d_compilation_units=compilation_units1;d_type_units=([]);d_loc=loc;d_ranges=ranges;d_frame_info=fi;d_line_info=li;})(*val extract_section_body : elf_file -> string -> bool -> p_context * natural * byte_sequence*)letextract_section_body(f:elf_file)(section_name:string)(strict1:bool):p_context*Nat_big_num.num*Byte_sequence_wrapper.byte_sequence=(let(en:Endianness.endianness)=((matchfwith|ELF_File_32f32->Elf_header.get_elf32_header_endiannessf32.Elf_file.elf32_file_header|ELF_File_64f64->Elf_header.get_elf64_header_endiannessf64.Elf_file.elf64_file_header))inlet(c:p_context)=({endianness=en})in(matchfwith|ELF_File_32f32->letsections=(List.filter(funx->x.Elf_interpreted_section.elf32_section_name_as_string=section_name)f32.elf32_file_interpreted_sections)in(matchsectionswith|[section]->letsection_addr=(section.Elf_interpreted_section.elf32_section_addr)inletsection_body=(section.Elf_interpreted_section.elf32_section_body)in(* let _ = my_debug4 (section_name ^ (": \n" ^ (Elf_interpreted_section.string_of_elf32_interpreted_section section ^ "\n"
* ^ " body = " ^ ppbytes2 0 section_body ^ "\n"))) in *)(c,section_addr,section_body)|[]->ifstrict1thenfailwith(""^(section_name^" section not present"))else(c,(Nat_big_num.of_int0),Byte_sequence.empty)|_->failwith("multiple "^(section_name^" sections present")))|ELF_File_64f64->letsections=(List.filter(funx->x.Elf_interpreted_section.elf64_section_name_as_string=section_name)f64.elf64_file_interpreted_sections)in(matchsectionswith|[section]->letsection_addr=(section.Elf_interpreted_section.elf64_section_addr)inletsection_body=(section.Elf_interpreted_section.elf64_section_body)in(c,section_addr,section_body)|[]->ifstrict1thenfailwith(""^(section_name^" section not present"))else(c,(Nat_big_num.of_int0),Byte_sequence.empty)|_->failwith("multiple "^(section_name^" sections present")))))(*val extract_dwarf : elf_file -> maybe dwarf*)letextract_dwarff:(dwarf)option=(let(c,_,debug_info_section_body)=(extract_section_bodyf".debug_info"true)inlet(c,_,debug_abbrev_section_body)=(extract_section_bodyf".debug_abbrev"false)inlet(c,_,debug_str_section_body)=(extract_section_bodyf".debug_str"false)inlet(c,_,debug_loc_section_body)=(extract_section_bodyf".debug_loc"false)inlet(c,_,debug_ranges_section_body)=(extract_section_bodyf".debug_ranges"false)inlet(c,_,debug_frame_section_body)=(extract_section_bodyf".debug_frame"false)inlet(c,_,debug_line_section_body)=(extract_section_bodyf".debug_line"false)inletd=(parse_dwarfcdebug_info_section_bodydebug_abbrev_section_bodydebug_str_section_bodydebug_loc_section_bodydebug_ranges_section_bodydebug_frame_section_bodydebug_line_section_body)inSomed)(*val extract_text : elf_file -> p_context * natural * byte_sequence*)(* (p_context, elf32/64_section_addr, elf32/64_section_body) *)letextract_textf:p_context*Nat_big_num.num*byte_sequence0=(extract_section_bodyf".text"true)(** ************************************************************ *)(** ****** location evaluation ******************************** *)(** ************************************************************ *)(** pp of locations *)(*val pp_simple_location : simple_location -> string*)letpp_simple_locationsl:string=((matchslwith|SL_memory_addressn->pphexn|SL_registern->"reg"^Nat_big_num.to_stringn|SL_implicitbs->"value: "^ppbytesbs|SL_empty->"<empty>"))(*val pp_composite_location_piece : composite_location_piece -> string*)letpp_composite_location_piececlp:string=((matchclpwith|CLP_piece(n,sl)->"piece ("^(Nat_big_num.to_stringn^(") "^pp_simple_locationsl))|CLP_bit_piece(n1,n2,sl)->"bit_piece ("^(Nat_big_num.to_stringn1^(","^(Nat_big_num.to_stringn2^(") "^pp_simple_locationsl))))))(*val pp_single_location: single_location -> string*)letpp_single_locationsl:string=((matchslwith|SL_simplesl->pp_simple_locationsl|SL_compositeclps->"composite: "^String.concat", "(Lem_list.mappp_composite_location_piececlps)))(** evaluation of location expressions *)(* cf dwarflist, btw: https://fedorahosted.org/elfutils/wiki/DwarfLint?format=txt *)(*
location description ::=
| single location description
| location list
single location description ::=
| simple location description
| composite location description
simple location description ::=
| memory location description : non-empty dwarf expr, value is address of all or part of object in memory
| register location description : single DW_OP_regN or DW_OP_regx, naming a register in which all the object is
| implicit location description : single DW_OP_implicit_value or a non-empty dwarf expr ending in DW_OP_stack_value, giving the value of all/part of object
| empty location description : an empty dwarf expr, indicating a part or all of an object that is not represented
composite location description : a list of simple location descriptions, each followed by a DW_OP_piece or DW_OP_bitpiece
(the simple location description can be a register location description: https://www.mail-archive.com/dwarf-discuss@lists.dwarfstd.org/msg00271.html)
(contradicting "A register location description must stand alone as the entire description of an object or a piece of an object.")
location list entry : a list of address ranges (possibly overlapping), each with a single location description
Dwarf expressions can include data-dependent control flow choices
(though we don't see that in the examples?), so we can't statically
determine which kind of single location description or simple location
description we have. We can distinguish:
- empty -> simple.empty
- DW_OP_regN/DW_OP_regx -> simple.register
- DW_OP_implicit_value -> simple.implicit
- any of those followed by DW_OP_piece or DW_OP_bitpiece, perhaps followed by more composite parts -> composite part :: composite
otherwise run to the end, or a DW_OP_stack_value at the end, or to
anything (except a DO_OP_regN/DW_OP_regx) followed by a
DW_OP_piece/DW_OP_bitpiece. Pfeh.
actually used in our examples (ignoring GNU extentions):
DW_OP_addr literal
DW_OP_lit1 literal
DW_OP_const4u literal
DW_OP_breg3 (r3) read register value and add offset
DW_OP_and bitwise and
DW_OP_plus addition (mod whatever)
DW_OP_deref_size
DW_OP_fbreg evaluate location description from DW_AT_frame_base attribute of the current function (which is DW_OP_call_frame_cfa in our examples) and add offset
DW_OP_implicit_value the argument block is the actual value (not location) of the entity in question
DW_OP_stack_value use the value at top of stack as the actual value (not location) of the entity in question
DW_OP_reg0 (r0)) read register value
DW_OP_call_frame_cfa go off to 6.4 and pull info out of .debug_frame (possibly involving other location expressions)
*)letinitial_state:state=({s_stack=([]);s_value=SL_empty;s_location_pieces=([]);})(* the main location expression evaluation function *)(* location expression evaluation is basically a recursive function
down a list of operations, maintaining an operation_stack (a list of
naturals representing machine-address-size words), the current
simple_location, and a list of any composite_location_piece's
accumulated so far *)letarithmetic_context_of_cuhcuh:arithmetic_context=(if(Nat_big_num.equalcuh.cuh_address_size((Nat_big_num.of_int8)))then({ac_bitwidth=((Nat_big_num.of_int64));ac_half=(Nat_big_num.pow_int((Nat_big_num.of_int2))32);ac_all=(Nat_big_num.pow_int((Nat_big_num.of_int2))64);ac_max=(Nat_big_num.sub_nat(Nat_big_num.pow_int((Nat_big_num.of_int2))64)((Nat_big_num.of_int1)));})else(if(Nat_big_num.equalcuh.cuh_address_size((Nat_big_num.of_int4)))then({ac_bitwidth=((Nat_big_num.of_int32));ac_half=(Nat_big_num.pow_int((Nat_big_num.of_int2))16);ac_all=(Nat_big_num.pow_int((Nat_big_num.of_int2))32);ac_max=(Nat_big_num.sub_nat(Nat_big_num.pow_int((Nat_big_num.of_int2))32)((Nat_big_num.of_int1)));})else(failwith"arithmetic_context_of_cuh given non-4/8 size")))letfind_cfa_table_row_for_pc(evaluated_frame_info1:evaluated_frame_info)(pc:Nat_big_num.num):cfa_table_row=((matchmyfind(fun(fde1,rows)->Nat_big_num.greater_equalpcfde1.fde_initial_location_address&&Nat_big_num.lesspc(Nat_big_num.addfde1.fde_initial_location_addressfde1.fde_address_range))evaluated_frame_info1with|Some(fde1,rows)->(matchmyfind(funrow->Nat_big_num.greater_equalpcrow.ctr_loc)rowswith|Somerow->row|None->failwith"evaluate_cfa: no matchine row")|None->failwith"evaluate_cfa: no fde encloding pc"))letrecevaluate_operation_list(c:p_context)(dloc:location_list_list)(evaluated_frame_info1:evaluated_frame_info)(cuh:compilation_unit_header)(ac:arithmetic_context)(ev:evaluation_context)(mfbloc:attribute_valueoption)(pc:Nat_big_num.num)(s:state)(ops:operationlist):single_locationerror=(letpush_memory_addressvvs'=(Success{swiths_stack=(v::vs');s_value=(SL_memory_addressv)})inletpush_memory_address_maybe(mv:Nat_big_num.numoption)vs'(err:string)op=((matchmvwith|Somev->push_memory_addressvvs'|None->Fail(err^pp_operationop)))inletbregxiri=((matchev.read_registerrwith|RRR_resultv->push_memory_address(partialNaturalFromInteger(Nat_big_num.modulus(Nat_big_num.add(v)i)(ac.ac_all)))s.s_stack|RRR_not_currently_available->Fail"RRR_not_currently_available"|RRR_bad_register_number->Fail("RRR_bad_register_number "^Nat_big_num.to_stringr)))inletderef_sizen=((matchs.s_stackwith|v::vs'->(matchev.read_memoryvnwith|MRR_resultv'->push_memory_addressv'vs'|MRR_not_currently_available->Fail"MRR_not_currently_available"|MRR_bad_address->Fail"MRR_bad_address")|_->Fail"OpSem unary not given an element on stack"))in(matchopswith|[]->if(listEqualBy(=)s.s_location_pieces[])thenSuccess(SL_simples.s_value)elseifs.s_value=SL_emptythenSuccess(SL_composites.s_location_pieces)else(* unclear what's supposed to happen in this case *)Fail"unfinished part of composite expression"|op::ops'->letes'=((match(op.op_semantics,op.op_argument_values)with|(OpSem_nop,[])->Successs|(OpSem_lit,[OAV_naturaln])->push_memory_addressns.s_stack|(OpSem_lit,[OAV_integeri])->push_memory_address(partialTwosComplementNaturalFromIntegeriac.ac_half(ac.ac_all))s.s_stack|(OpSem_stackf,[])->(matchfacs.s_stackop.op_argument_valueswith|Somestack'->letvalue':simple_location=((matchstack'with[]->SL_empty|v'::_->SL_memory_addressv'))inSuccess{swiths_stack=stack';s_value=value'}|None->Fail"OpSem_stack failed")|(OpSem_not_supported,[])->Fail("OpSem_not_supported: "^pp_operationop)|(OpSem_binaryf,[])->(matchs.s_stackwith|v1::v2::vs'->push_memory_address_maybe(facv1v2)vs'"OpSem_binary error: "op|_->Fail"OpSem binary not given two elements on stack")|(OpSem_unaryf,[])->(matchs.s_stackwith|v1::vs'->push_memory_address_maybe(facv1)vs'"OpSem_unary error: "op|_->Fail"OpSem unary not given an element on stack")|(OpSem_opcode_litbase,[])->ifNat_big_num.greater_equalop.op_codebase&&Nat_big_num.lessop.op_code(Nat_big_num.addbase((Nat_big_num.of_int32)))thenpush_memory_address(Nat_big_num.sub_natop.op_codebase)s.s_stackelseFail"OpSem_opcode_lit opcode not within [base,base+32)"|(OpSem_reg,[])->(* TODO: unclear whether this should push the register id or not *)letr=(Nat_big_num.sub_natop.op_codevDW_OP_reg0)inSuccess{swiths_stack=(r::s.s_stack);s_value=(SL_registerr)}|(OpSem_breg,[OAV_integeri])->letr=(Nat_big_num.sub_natop.op_codevDW_OP_breg0)inbregxiri|(OpSem_bregx,[OAV_naturalr;OAV_integeri])->bregxiri|(OpSem_deref,[])->deref_sizecuh.cuh_address_size|(OpSem_deref_size,[OAV_naturaln])->deref_sizen|(OpSem_fbreg,[OAV_integeri])->(matchmfblocwith|Somefbloc->(*let _ = my_debug5 ("OpSem_fbreg (" ^ show i ^ ")\n") in*)(matchevaluate_location_descriptioncdlocevaluated_frame_info1cuhacev(*mfbloc*)Nonepcfblocwith(* what to do if the recursive call also uses fbreg? for now assume that's not allowed *)|Successl->(matchlwith|SL_simple(SL_memory_addressa)->(*let _ = my_debug5 ("OpSem_fbreg: a = "^ pphex a ^ "\n") in*)letvi=(Nat_big_num.modulus(Nat_big_num.add(a)i)(ac.ac_all))in(*let _ = my_debug5 ("OpSem_fbreg: v = "^ show vi ^ "\n") in*)letv=(partialNaturalFromIntegervi)(*ac.ac_half (integerFromNatural ac.ac_all)*)inpush_memory_addressvs.s_stack|_->Fail"OpSem_fbreg got a non-SL_simple (SL_memory_address _) result"(* "The DW_OP_fbreg operation provides a signed LEB128
offset from the address specified by the location
description in the DW_AT_frame_base attribute of the
current function. "
- so what to do if the location description returns a non-memory-address location? *))|Faile->Fail("OpSem_fbreg failure: "^e))|None->Fail"OpSem_fbreg: no frame base location description given")|(OpSem_piece,[OAV_naturalsize_bytes])->letpiece=(CLP_piece(size_bytes,s.s_value))in(* we allow a piece (or bit_piece) to be any simple_location, including implicit and stack values. Unclear if this is intended, esp. the latter *)letstack'=([])inletvalue'=SL_emptyinSuccess{s_stack=stack';s_value=value';s_location_pieces=(List.rev_append(List.revs.s_location_pieces)[piece])}|(OpSem_bit_piece,[OAV_naturalsize_bits;OAV_naturaloffset_bits])->letpiece=(CLP_bit_piece(size_bits,offset_bits,s.s_value))inletstack'=([])inletvalue'=SL_emptyinSuccess{s_stack=stack';s_value=value';s_location_pieces=(List.rev_append(List.revs.s_location_pieces)[piece])}|(OpSem_implicit_value,[OAV_block(size2,bs)])->letstack'=([])inletvalue'=(SL_implicitbs)inSuccess{swiths_stack=stack';s_value=value'}|(OpSem_stack_value,[])->(* "The DW_OP_stack_value operation terminates the expression." - does
this refer to just the subexpression, ie allowing a stack value to be
a piece of a composite location, or necessarily the whole expression?
Why does DW_OP_stack_value have this clause while DW_OP_implicit_value
does not? *)(* why doesn't DW_OP_stack_value have a size argument? *)(matchs.s_stackwith|v::vs'->letstack'=([])inletvalue'=(SL_implicit(bytes_of_naturalc.endiannesscuh.cuh_address_sizev))inSuccess{swiths_stack=stack';s_value=value'}|_->Fail"OpSem_stack_value not given an element on stack")|(OpSem_call_frame_cfa,[])->letrow=(find_cfa_table_row_for_pcevaluated_frame_info1pc)in(matchrow.ctr_cfawith|CR_undefined->failwith"evaluate_cfa of CR_undefined"|CR_register(r,i)->bregxiri(* same behaviour as an OpSem_bregx *)|CR_expressionbs->failwith"CR_expression"(*TODO: fix result type - not this evaluate_location_description_bytes c dloc evaluated_frame_info cuh ac ev mfbloc pc bs*)(* TODO: restrict allowed OpSem_* in that recursive call *))|(_,_)->Fail("bad OpSem invocation: op="^(pp_operationop^(" arguments="^String.concat""(Lem_list.mappp_operation_argument_valueop.op_argument_values))))))in(matches'with|Successs'->evaluate_operation_listcdlocevaluated_frame_info1cuhacevmfblocpcs'ops'|Faile->Faile)))andevaluate_location_description_bytes(c:p_context)(dloc:location_list_list)(evaluated_frame_info1:evaluated_frame_info)(cuh:compilation_unit_header)(ac:arithmetic_context)(ev:evaluation_context)(mfbloc:attribute_valueoption)(pc:Nat_big_num.num)(bs:byte_sequence0):single_locationerror=(letparse_context1=({pc_bytes=bs;pc_offset=((Nat_big_num.of_int0))})in(matchparse_operationsccuhparse_context1with|PR_fail(s,pc')->Fail("evaluate_location_description_bytes: parse_operations fail: "^pp_parse_failspc')|PR_success(ops,pc')->ifnot(Nat_big_num.equal(Byte_sequence.length0pc'.pc_bytes)((Nat_big_num.of_int0)))thenFail"evaluate_location_description_bytes: extra non-parsed bytes"elseevaluate_operation_listcdlocevaluated_frame_info1cuhacevmfblocpcinitial_stateops))andevaluate_location_description(c:p_context)(dloc:location_list_list)(evaluated_frame_info1:evaluated_frame_info)(cuh:compilation_unit_header)(ac:arithmetic_context)(ev:evaluation_context)(mfbloc:attribute_valueoption)(pc:Nat_big_num.num)(loc:attribute_value):single_locationerror=((matchlocwith|AV_exprloc(n,bs)->evaluate_location_description_bytescdlocevaluated_frame_info1cuhacevmfblocpcbs|AV_block(n,bs)->evaluate_location_description_bytescdlocevaluated_frame_info1cuhacevmfblocpcbs|AV_sec_offsetn->letlocation_list1=(find_location_listdlocn)inlet(offset,(llis:location_list_itemlist))=location_list1inletf(lli:location_list_item):single_location_descriptionoption=((matchlliwith|LLI_llelle->ifNat_big_num.greater_equalpclle.lle_beginning_address_offset&&Nat_big_num.lesspclle.lle_ending_address_offsetthenSomelle.lle_single_location_descriptionelseNone|LLI_base_->None(* TODO: either refactor to do offset during parsing or update base offsets here. Should refactor to use "interpreted". *)))in(matchmyfindmaybeflliswith|Somebs->evaluate_location_description_bytescdlocevaluated_frame_info1cuhacevmfblocpcbs|None->Fail"evaluate_location_description didn't find pc in location list ranges")|_->Fail"evaluate_location_description av_location not understood"))(** ************************************************************ *)(** **** evaluation of frame information ********************** *)(** ************************************************************ *)(** register maps *)(*val rrp_update : register_rule_map -> cfa_register -> register_rule -> register_rule_map*)letrrp_updaterrprrr:(Nat_big_num.num*register_rule)list=((r,rr)::rrp)(*val rrp_lookup : cfa_register -> register_rule_map -> register_rule*)letrrp_lookuprrrp:register_rule=((match(lookupByNat_big_num.equalrrrp)with|Somerr->rr|None->RR_undefined))(*val rrp_empty : register_rule_map*)letrrp_empty:(cfa_register*register_rule)list=([])(** pp of evaluated cfa information from .debug_frame *)(* readelf --debug-dump=frames-interp test/a.out
Contents of the .eh_frame section:
00000000 00000014 00000000 CIE "zR" cf=1 df=-8 ra=16
LOC CFA ra
0000000000000000 rsp+8 c-8
00000018 00000024 0000001c FDE cie=00000000 pc=004003b0..004003d0
LOC CFA ra
00000000004003b0 rsp+16 c-8
00000000004003b6 rsp+24 c-8
00000000004003c0 exp c-8
00000040 0000001c 00000044 FDE cie=00000000 pc=004004b4..004004ba
LOC CFA rbp ra
00000000004004b4 rsp+8 u c-8
00000000004004b5 rsp+16 c-16 c-8
00000000004004b8 rbp+16 c-16 c-8
00000000004004b9 rsp+8 c-16 c-8
00000060 00000024 00000064 FDE cie=00000000 pc=004004c0..00400549
LOC CFA rbx rbp r12 r13 r14 r15 ra
00000000004004c0 rsp+8 u u u u u u c-8
00000000004004d1 rsp+8 u c-48 c-40 u u u c-8
00000000004004f0 rsp+64 c-56 c-48 c-40 c-32 c-24 c-16 c-8
0000000000400548 rsp+8 c-56 c-48 c-40 c-32 c-24 c-16 c-8
00000088 00000014 0000008c FDE cie=00000000 pc=00400550..00400552
LOC CFA ra
0000000000400550 rsp+8 c-8
000000a0 ZERO terminator
*)(*val mytoList : forall 'a. SetType 'a => set 'a -> list 'a*)letregister_footprint_rrp(rrp:register_rule_map):cfa_registerPset.set=(Pset.from_listNat_big_num.compare(Lem_list.mapfstrrp))letregister_footprint(rows:cfa_table_rowlist):cfa_registerlist=(Pset.elements(bigunionListMapinstance_Basic_classes_SetType_Num_natural_dict(funrow->register_footprint_rrprow.ctr_regs)rows))(*val max_lengths : list (list string) -> list natural*)letrecmax_lengthsxss:(Nat_big_num.num)list=((matchxsswith|[]->failwith"max_lengths"|xs::xss'->letlens=(Lem_list.map(funx->Nat_big_num.of_int(String.lengthx))xs)inif(listEqualBy(listEqualBy(=))xss'[])thenlenselseletlens'=(max_lengthsxss')inletz=(Lem_list.list_combinelenslens')inletlens''=(Lem_list.map(fun(l1,l2)->Nat_big_num.maxl1l2)z)inlens''))letrecpad_rowxslens:(string)list=((match(xs,lens)with|([],[])->[]|([x],[len])->[x]|(x::(((_::_)asxs')),len::(((_::_)aslens')))->right_space_padded_tolenx::pad_rowxs'lens'))letpad_rows(xss:(stringlist)list):string=((matchxsswith|[]->""|_->letlens=(max_lengthsxss)inString.concat""(Lem_list.map(funxs->String.concat" "(pad_rowxslens)^"\n")xss)))letpp_evaluated_fde(fde1,(rows:cfa_table_rowlist)):string=(letregs=(register_footprintrows)inletheader:stringlist=("LOC"::("CFA"::Lem_list.map(pp_cfa_registerinstance_Show_Show_Num_natural_dict)regs))inletppd_rows:(stringlist)list=(Lem_list.map(funrow->pphexrow.ctr_loc::(pp_cfa_rulerow.ctr_cfa::Lem_list.map(funr->pp_register_rule(rrp_lookuprrow.ctr_regs))regs))rows)inpad_rows(header::ppd_rows))letsemi_pp_evaluated_fde(fde1,(rows:cfa_table_rowlist)):(Nat_big_num.num(*address*)*string(*cfa*)*(string*string)list(*register rules*))list=(letregs=(register_footprintrows)inletppd_rows=(Lem_list.map(funrow->(row.ctr_loc,pp_cfa_rulerow.ctr_cfa,Lem_list.map(funr->(pp_cfa_registerinstance_Show_Show_Num_natural_dictr,pp_register_rule(rrp_lookuprrow.ctr_regs)))regs))rows)inppd_rows)(*val semi_pp_evaluated_frame_info : evaluated_frame_info -> list (natural (*address*) * string (*cfa*) * list (string*string) (*register rules*) )*)letsemi_pp_evaluated_frame_infoefi:(Nat_big_num.num*string*(string*string)list)list=(List.concat(Lem_list.mapsemi_pp_evaluated_fdeefi))(** evaluation of cfa information from .debug_frame *)letevaluate_call_frame_instruction(fi:frame_info)(cie1:cie)(state1:cfa_state)(cfi:call_frame_instruction):cfa_state=(letcreate_row(loc:Nat_big_num.num)=(letrow=({state1.cs_current_rowwithctr_loc=loc})in{state1withcs_current_row=row;cs_previous_rows=(state1.cs_current_row::state1.cs_previous_rows)})inletupdate_cfa(cr:cfa_rule)=(letrow=({state1.cs_current_rowwithctr_cfa=cr})in{state1withcs_current_row=row})inletupdate_regrrr=(letrow=({state1.cs_current_rowwithctr_regs=(rrp_updatestate1.cs_current_row.ctr_regsrrr)})in{state1withcs_current_row=row})in(matchcfiwith(* Row Creation Instructions *)|DW_CFA_set_loca->create_rowa|DW_CFA_advance_locd->create_row(Nat_big_num.addstate1.cs_current_row.ctr_loc(Nat_big_num.muldcie1.cie_code_alignment_factor))|DW_CFA_advance_loc1d->create_row(Nat_big_num.addstate1.cs_current_row.ctr_loc(Nat_big_num.muldcie1.cie_code_alignment_factor))|DW_CFA_advance_loc2d->create_row(Nat_big_num.addstate1.cs_current_row.ctr_loc(Nat_big_num.muldcie1.cie_code_alignment_factor))|DW_CFA_advance_loc4d->create_row(Nat_big_num.addstate1.cs_current_row.ctr_loc(Nat_big_num.muldcie1.cie_code_alignment_factor))(* CFA Definition Instructions *)|DW_CFA_def_cfa(r,n)->update_cfa(CR_register(r,(n)))|DW_CFA_def_cfa_sf(r,i)->update_cfa(CR_register(r,(Nat_big_num.mulicie1.cie_data_alignment_factor)))|DW_CFA_def_cfa_registerr->(matchstate1.cs_current_row.ctr_cfawith|CR_register(r',i)->update_cfa(CR_register(r,i))|CR_undefined->(* FIXME: this is to handle a bug in riscv64-gcc.
gcc generates "DW_CFA_def_cfa_register: r2 (sp)" as the first instruction.
Dwarf5 documentation seems to suggest this is not valid.
We think what gcc meant to generate is "DW_CFA_def_cfa: r2 (sp) ofs 0" *)update_cfa(CR_register(r,((Nat_big_num.of_int0))))|CR_expression_->failwith"DW_CFA_def_cfa_register: current rule is CR_expression")|DW_CFA_def_cfa_offsetn->(matchstate1.cs_current_row.ctr_cfawith|CR_register(r,i)->update_cfa(CR_register(r,(n)))|_->failwith"DW_CFA_def_cfa_offset: current rule is not CR_register")|DW_CFA_def_cfa_offset_sfi->(matchstate1.cs_current_row.ctr_cfawith|CR_register(r,i')->update_cfa(CR_register(r,(Nat_big_num.muli'cie1.cie_data_alignment_factor)))|_->failwith"DW_CFA_def_cfa_offset_sf: current rule is not CR_register")|DW_CFA_def_cfa_expressionb->update_cfa(CR_expressionb)(* Register Rule Instrutions *)|DW_CFA_undefinedr->update_regr(RR_undefined)|DW_CFA_same_valuer->update_regr(RR_same_value)|DW_CFA_offset(r,n)->update_regr(RR_offset(Nat_big_num.mul(n)cie1.cie_data_alignment_factor))|DW_CFA_offset_extended(r,n)->update_regr(RR_offset(Nat_big_num.mul(n)cie1.cie_data_alignment_factor))|DW_CFA_offset_extended_sf(r,i)->update_regr(RR_offset(Nat_big_num.mulicie1.cie_data_alignment_factor))|DW_CFA_val_offset(r,n)->update_regr(RR_val_offset(Nat_big_num.mul(n)cie1.cie_data_alignment_factor))|DW_CFA_val_offset_sf(r,i)->update_regr(RR_val_offset(Nat_big_num.mulicie1.cie_data_alignment_factor))|DW_CFA_register(r1,r2)->update_regr1(RR_registerr2)|DW_CFA_expression(r,b)->update_regr(RR_expressionb)|DW_CFA_val_expression(r,b)->update_regr(RR_val_expressionb)|DW_CFA_restorer->update_regr(rrp_lookuprstate1.cs_initial_instructions_row.ctr_regs)(* RR_undefined if the lookup fails? *)|DW_CFA_restore_extendedr->update_regr(rrp_lookuprstate1.cs_initial_instructions_row.ctr_regs)(* Row State Instructions *)(* do these also push and restore the CFA rule? *)|DW_CFA_remember_state->{state1withcs_row_stack=(state1.cs_current_row::state1.cs_row_stack)}|DW_CFA_restore_state->(matchstate1.cs_row_stackwith|r::rs->{state1withcs_current_row=r;cs_row_stack=rs}|[]->failwith"DW_CFA_restore_state: empty row stack")(* Padding Instruction *)|DW_CFA_nop->state1(* DW_CFA_AARCH64_negate_ra_state Instruction *)|DW_CFA_AARCH64_negate_ra_state->state1(* Unknown *)|DW_CFA_unknownb->failwith("evaluate_call_frame_instruction: DW_CFA_unknown "^hex_string_of_byteb)))letrecevaluate_call_frame_instructions(fi:frame_info)(cie1:cie)(state1:cfa_state)(cfis:call_frame_instructionlist):cfa_state=((matchcfiswith|[]->state1|cfi::cfis'->letstate'=(evaluate_call_frame_instructionficie1state1cfi)inevaluate_call_frame_instructionsficie1state'cfis'))letevaluate_fde(fi:frame_info)(fde1:fde):cfa_table_rowlist=(letcie1=(find_ciefifde1.fde_cie_pointer)inletfinal_location=(Nat_big_num.addfde1.fde_initial_location_addressfde1.fde_address_range)inletinitial_cfa_state=(letinitial_row=({ctr_loc=(fde1.fde_initial_location_address);ctr_cfa=CR_undefined;ctr_regs=rrp_empty;})in{cs_current_row=initial_row;cs_previous_rows=([]);cs_initial_instructions_row=initial_row;cs_row_stack=([]);})inletstate'=(evaluate_call_frame_instructionsficie1initial_cfa_statecie1.cie_initial_instructions)inletinitial_row'=(state'.cs_current_row)inletstate''=({initial_cfa_statewithcs_current_row=initial_row';cs_initial_instructions_row=initial_row'})inletstate'''=(evaluate_call_frame_instructionsficie1(*final_location*)state''fde1.fde_instructions)inList.rev(state'''.cs_current_row::state'''.cs_previous_rows))(*val evaluate_frame_info : dwarf -> evaluated_frame_info*)letevaluate_frame_info(d:dwarf):evaluated_frame_info=(Lem_list.mapMaybe(funfie->(matchfiewithFIE_fdefde1->Some(fde1,(evaluate_fded.d_frame_infofde1))|FIE_cie_->None))d.d_frame_info)letpp_evaluated_frame_info(efi:evaluated_frame_info):string=(String.concat"\n"(Lem_list.mappp_evaluated_fdeefi))(** ************************************************************ *)(** ** pp of type info *)(** ************************************************************ *)(* partial analysis and pp of type info - incomplete, but enough for some C code *)(* analyse top level of C type structure, without recursing into type subterms *)letstrictsx:'a=((matchxwith|Somey->y|None->failwith("analyse_type_info_die strict failure on \n"^(s()^"\n"))))letanalyse_type_info_topc(d:dwarf)(r:bool(*recurse into members*))(cupdie1:cupdie):cupdiec_type_top=(let(cu,parents,die1)=cupdie1inletmname=(find_name_of_died.d_strdie1)inletmtyp=(find_DW_AT_type_of_diecdcud.d_strdie1)inlets()=(pp_dieccu.cu_headerd.d_strtrue((Nat_big_num.of_int0))falsedie1)inifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_base_type")thenletencoding=(letn=(stricts(find_natural_attribute_value_of_diec"DW_AT_encoding"die1))inifnot(List.exists(fun(s,n')->Nat_big_num.equalnn')base_type_attribute_encodings)thenstrictsNoneelsen)in(* TODO: handle user encodings correctly *)letmbyte_size=(find_natural_attribute_value_of_diec"DW_AT_byte_size"die1)inCT_base(cupdie1,(strictsmname),encoding,mbyte_size)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_pointer_type")thenCT_pointer(cupdie1,mtyp)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_const_type")thenCT_const(cupdie1,mtyp)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_volatile_type")then(* CT_volatile cupdie (strict s mtyp')*)(* TODO: this is a temporary hack, while we figure out what DW_TAG_volatile without a DW_AT_type is supposed to mean *)(matchmtypwith|Sometyp->CT_volatile(cupdie1,typ)|None->CT_missingcupdie1)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_restrict_type")thenCT_restrict(cupdie1,(strictsmtyp))elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_typedef")thenletdecl1=({decl_file=None;(* TODO *)decl_line=None;(* TODO *)})inCT_typedef(cupdie1,(strictsmname),(strictsmtyp),decl1)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_array_type")thenletdims=(letsubranges=(List.filter(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subrange_type"))die1.die_children)inLem_list.map(fundie'->(*WAS: let mcount = find_natural_attribute_value_of_die c "DW_AT_count" die' in*)letmcount=((matchfind_attribute_value"DW_AT_count"die'with|None->None|Someav->(matchmaybe_natural_of_constant_attribute_valuedie'cavwith|None->None(* DWARF seems to sometimes use an AV_ref* attribute value for DW_AT_count, referring to a variable die, for a VLA length. In this case for the moment we will just forget the length information, which is what this clause does *)|Somen->Somen)))inletmsubrange_type=(find_DW_AT_type_of_diecdcud.d_strdie')in(mcount,msubrange_type))subranges)inCT_array(cupdie1,(strictsmtyp),dims)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_structure_type")||Nat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_union_type")thenletatk=(ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_structure_type")thenAtk_structureelseAtk_union)inletmbyte_size=(find_natural_attribute_value_of_diec"DW_AT_byte_size"die1)inletdecl1=({decl_file=None;(* TODO *)decl_line=None;(* TODO *)})inletmembers=(ifrthenletmembers_raw=(List.filter(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_member"))die1.die_children)inSome(Lem_list.map(fundie'->letcupdie'=(cu,(die1::parents),die')inletmname'=(find_name_of_died.d_strdie')inlettyp'=(stricts(find_DW_AT_type_of_diecdcud.d_strdie'))inletmdata_member_location'=((matchatkwith|Atk_structure->Some(stricts(find_natural_attribute_value_of_diec"DW_AT_data_member_location"die'))|Atk_union->(find_natural_attribute_value_of_diec"DW_AT_data_member_location"die')))in(cupdie',mname',typ',mdata_member_location'))members_raw)elseNone)inCT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,members)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_enumeration_type")thenletmbyte_size=(find_natural_attribute_value_of_diec"DW_AT_byte_size"die1)inletdecl1=({decl_file=None;(* TODO *)decl_line=None;(* TODO *)})inletmembers=(ifrthenletmembers_raw=(List.filter(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_enumerator"))die1.die_children)inSome(Lem_list.map(fundie'->letcupdie'=(cu,(die1::parents),die')inletmname'=(find_name_of_died.d_strdie')in(*let _ = my_debug5 (s ()) in *)letconst_value=(stricts(find_integer_attribute_value_of_diec"DW_AT_const_value"die'))in(*let _ = my_debug5 "ok" in*)(cupdie',mname',const_value))members_raw)elseNone)inCT_enumeration(cupdie1,mname,mtyp,mbyte_size,decl1,members)elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subroutine_type")then(* let prototyped = strict s (find_flag_attribute_value_of_die "DW_AT_prototyped" die) in*)letprototyped=(find_flag_attribute_value_of_die_default_false"DW_AT_prototyped"die1)inletmresult_type=mtypinletparameter_types=(letparameter_types_raw=(List.filter(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_formal_parameter"))die1.die_children)in(Lem_list.map(fundie'->letcupdie'=(cu,(die1::parents),die')inletmname'=(find_name_of_died.d_strdie')inlettyp'=(stricts(find_DW_AT_type_of_diecdcud.d_strdie'))intyp')parameter_types_raw))inlet(variable_parameter_list:bool)=(List.exists(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_unspecified_parameters"))die1.die_children)inCT_subroutine(cupdie1,prototyped,mresult_type,parameter_types,variable_parameter_list)elsefailwith("analyse_type_info_top didn't recognise tag: "^(pphexdie1.die_abbreviation_declaration.ad_tag^(" for DIE "^pp_cupdie3cupdie1))))letrecanalyse_type_info_deep(d:dwarf)(r:bool(*recurse_into_members*))cupdie1:c_type=(letc=(p_context_of_dd)inlet(cu,parents,die1)=cupdie1inlet(typ:cupdiec_type_top)=(analyse_type_info_topc(d:dwarf)rcupdie1)in(matchtypwith|CT_missingcupdie1->CT(CT_missingcupdie1)|CT_base(cupdie1,name1,encoding,mbyte_size)->CT(CT_base(cupdie1,name1,encoding,mbyte_size))|CT_pointer(cupdie1,mtyp')->CT(CT_pointer(cupdie1,(Lem.option_map(analyse_type_info_deepdr)mtyp')))|CT_const(cupdie1,mtyp')->CT(CT_const(cupdie1,(Lem.option_map(analyse_type_info_deepdr)mtyp')))|CT_volatile(cupdie1,typ')->CT(CT_volatile(cupdie1,(analyse_type_info_deepdrtyp')))|CT_restrict(cupdie1,typ')->CT(CT_restrict(cupdie1,(analyse_type_info_deepdrtyp')))|CT_typedef(cupdie1,name1,typ',decl1)->CT(CT_typedef(cupdie1,name1,(analyse_type_info_deepdrtyp'),decl1))|CT_array(cupdie1,typ',dims)->CT(CT_array(cupdie1,(analyse_type_info_deepdrtyp'),(Lem_list.map(fun(mcount,msubrange_typ)->(mcount,(Lem.option_map(analyse_type_info_deepdr)msubrange_typ)))dims)))|CT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,mmembers)->CT(CT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,(Lem.option_map(funmembers->(Lem_list.map(fun(((cupdie1,mname,typ,mdata_member_location)asam))->(cupdie1,mname,(analyse_type_info_deepdfalsetyp),mdata_member_location))members))mmembers)))|CT_enumeration(cupdie1,mname,mtyp',mbyte_size,decl1,mmembers)->CT(CT_enumeration(cupdie1,mname,(Lem.option_map(analyse_type_info_deepdr)mtyp'),mbyte_size,decl1,mmembers))|CT_subroutine(cupdie1,prototyped,mresult_type,parameter_types,variable_parameter_list)->CT(CT_subroutine(cupdie1,prototyped,(Lem.option_map(analyse_type_info_deepdr)mresult_type),(Lem_list.map(funtyp->analyse_type_info_deepdrtyp)parameter_types),variable_parameter_list))))letfind_DW_AT_type_of_die_deepdcupdie1:c_typeoption=(letc=(p_context_of_dd)inlet(cu,parents,die1)=cupdie1in(matchfind_reference_attribute_of_diecdcud.d_str"DW_AT_type"die1with|None->None|Somecupdie'->Some(analyse_type_info_deepdfalsecupdie')))letfind_DW_AT_type_of_die_deep_using_abstract_origindcupdie1:c_typeoption=(letc=(p_context_of_dd)inlet(cu,parents,die1)=cupdie1in(matchfind_reference_attribute_using_abstract_origincdcud.d_str"DW_AT_type"die1with|None->None|Somecupdie'->Some(analyse_type_info_deepdfalsecupdie')))(* analyse and pp C type structure, but without going into the definitions of struct_union or enumeration types *)letpp_struct_union_type_kindatk:string=((matchatkwith|Atk_structure->"struct"|Atk_union->"union"))letpp_mbyte_sizedict_Show_Show_ambyte_size:string=("size:"^(matchmbyte_sizewith|Somen->dict_Show_Show_a.show_methodn|None->"?"))(* pp the top-level structure of a C type, omitting struct_union-type and enum member definitions*)letpp_type_info_top(ppa:'a->string)(typ:'ac_type_top):string=((matchtypwith|CT_missingcupdie1->"missing at "^pp_cupdiecupdie1|CT_base(cupdie1,name1,encoding,mbyte_size)->name1^(" (base type, "^((matchlookup_aB_ainstance_Basic_classes_Eq_Num_natural_dictencodingbase_type_attribute_encodingswithSomes->s|None->Nat_big_num.to_stringencoding)^(" "^(pp_mbyte_sizeinstance_Show_Show_Num_natural_dictmbyte_size^")"))))|CT_pointer(cupdie1,mtyp')->"pointer("^((matchmtyp'with|Sometyp'->ppatyp'|None->"no type")^")")|CT_const(cupdie1,mtyp')->"const("^((matchmtyp'withSometyp'->ppatyp'|None->"no type")^")")|CT_volatile(cupdie1,typ')->"volatile("^(ppatyp'^")")|CT_restrict(cupdie1,typ')->"restrict("^(ppatyp'^")")|CT_typedef(cupdie1,name1,typ',decl1)->"typedef("^(name1^("="^(ppatyp'^")")))|CT_array(cupdie1,typ',dims)->ppatyp'^String.concat""(Lem_list.map(fun(mcount,msubrange_typ)->"["^((matchmcountwith|Somecount->Nat_big_num.to_stringcount|None->"no count")^"]"))dims)|CT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,mmembers)->pp_struct_union_type_kindatk^(" "^(((matchmnamewith|Somes->s|None->"noname"))^pp_cupdiecupdie1))|CT_enumeration(cupdie1,mname,mtyp',mbyte_size,decl1,mmembers)->"enum"^(" "^(((matchmnamewith|Somes->s|None->"noname"))^pp_cupdiecupdie1))|CT_subroutine(cupdie1,prototyped,mresult_type,parameter_types,variable_parameter_list)->"subroutine("^((ifprototypedthen"prototyped"else"not-prototyped")^(" "^(((matchmresult_typewithNone->"no type"|Someresult_type->pparesult_type))^("("^(String.concat","(List.rev_append(List.rev(Lem_list.mapppaparameter_types))(ifvariable_parameter_listthen["..."]else[]))^")")))))))letrecpp_type_info_deep(ctyp:c_type):string=(letppa=pp_type_info_deepin(matchctypwith|CTtyp->pp_type_info_topppatyp))letrecpp_type_info_diec(d:dwarf)cupdie1:string=(let(typ:cupdiec_type_top)=(analyse_type_info_topc(d:dwarf)falsecupdie1)inletppa=(pp_type_info_diecd)inpp_type_info_topppatyp)letpp_struct_union_type_membercd(am:cupdiestruct_union_member):stringlist=(let(cupdie1,mname,typ,mdata_member_location)=amin[" ";((matchmnamewith|Somes->s|None->"noname"));(" @ "^((matchmdata_member_locationwithNone->"nodatamemberlocation"|Somedata_member_location->Nat_big_num.to_stringdata_member_location)));(" : "^pp_type_info_diecdtyp)])letpp_struct_union_type_defncdcupdie1:string=(let(typ:cupdiec_type_top)=(analyse_type_info_topc(d:dwarf)truecupdie1)in(matchtypwith|CT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,mmembers)->((matchmnamewith|Somes->s|None->"noname"))^(" "^(pp_cupdiecupdie1^(" "^(pp_mbyte_sizeinstance_Show_Show_Num_natural_dictmbyte_size^("\n"^pad_rows((matchmmemberswithSomemembers->(Lem_list.map(pp_struct_union_type_membercd)members)|None->[])))))))|_->failwith"pp_struct_union_type_defn called on non-struct_union"))letpp_struct_union_type_member'(am:c_typestruct_union_member):stringlist=(let(cupdie1,mname,ctyp,mdata_member_location)=amin[" ";((matchmnamewith|Somes->s|None->"noname"));(" @ "^((matchmdata_member_locationwithNone->"nodatamemberlocation"|Somedata_member_location->Nat_big_num.to_stringdata_member_location)));(" : "^pp_type_info_deepctyp)])letpp_enum_type_member'(em:enumeration_member):stringlist=(let(cupdie1,mname,const_value)=emin[" ";((matchmnamewith|Somes->s|None->"noname"));(" = "^Nat_big_num.to_stringconst_value)])letpp_struct_union_type_defn'(ctyp:c_type):string=(letpreamblemnamekindcupdie1mbyte_size=(((matchmnamewith|Somes->s|None->"noname"))^(" "^(kind^(" "^(pp_cupdiecupdie1^(" "^pp_mbyte_sizeinstance_Show_Show_Num_natural_dictmbyte_size))))))in(matchctypwith|CT(CT_struct_union(cupdie1,atk,mname,mbyte_size,decl1,mmembers))->preamblemname(pp_struct_union_type_kindatk)cupdie1mbyte_size^("\n"^pad_rows((matchmmemberswithSomemembers->(Lem_list.map(pp_struct_union_type_member')members)|None->[["warning: no members list"]])))|CT(CT_enumeration(cupdie1,mname,mtyp,mbyte_size,decl1,mmembers))->preamblemname"enum"cupdie1mbyte_size^(" "^(((matchmtypwithSometyp->pp_type_info_deeptyp|None->"no representation type"))^("\n"^pad_rows((matchmmemberswithSomemembers->(Lem_list.map(pp_enum_type_member')members)|None->[["warning: no members list"]])))))|_->failwith"pp_struct_union_type_defn called on non-struct_union"))(*
match typ with
| CT_base cupdie name encoding mbyte_size ->
name ^ " (base type, " ^ match lookup_aB_a encoding base_type_attribute_encodings with Just s -> s | Nothing -> show encoding end ^ " " ^ pp_mbyte_size mbyte_size ^ ")"
| CT_pointer cupdie mtyp' -> "pointer(" ^ match mtyp' with | Just typ' -> pp_type_info_die c d typ' | Nothing -> "no type" end ^ ")"
| CT_const cupdie mtyp' -> "const(" ^ match mtyp' with Just typ'->pp_type_info_die c d typ' | Nothing -> "no type" end ^ ")"
| CT_volatile cupdie typ' -> "volatile(" ^ pp_type_info_die c d typ' ^ ")"
| CT_restrict cupdie typ' -> "restrict(" ^ pp_type_info_die c d typ' ^ ")"
| CT_typedef cupdie name typ' decl -> "typedef("^name^"="^pp_type_info_die c d typ' ^ ")"
| CT_array cupdie typ' dims ->
pp_type_info_die c d typ' ^ String.concat "" (List.map (fun (mcount,subrange_typ) -> "["^match mcount with | Just count -> show count | Nothing -> "no count" end ^"]") dims)
| CT_struct_union cupdie atk mname mbyte_size decl members -> pp_struct_union_type_kind atk ^ " " ^ (match mname with | Just s -> s | Nothing -> "noname" end) ^ pp_cupdie cupdie
| CT_enumeration cupdie mname mtyp' mbyte_size decl members -> "enum" ^ " " ^ (match mname with | Just s -> s | Nothing -> "noname" end) ^ pp_cupdie cupdie
end
*)(* expect the die to have a DW_AT_type, and pp it *)letpp_type_info_die_DW_AT_typec(d:dwarf)custrdie1:string=((matchfind_DW_AT_type_of_die_using_abstract_origincdcustrdie1with|Some(cu',parents',die')->pp_type_info_diec(d:dwarf)(cu',parents',die')|None->"DW_AT_abstract origin failed"))letstruct_union_enum_types(d:dwarf):c_typelist=(letcupdies=(find_dies(fundie1->Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tag[tag_encode"DW_TAG_structure_type";tag_encode"DW_TAG_union_type";tag_encode"DW_TAG_enumeration_type"])d)inLem_list.map(analyse_type_info_deep(d:dwarf)true)cupdies)(*
let pp_all_struct_union_enum_types c d : string =
String.concat "\n\n" (List.map ((fun (cu,parents,die) -> pp_struct_union_type_defn c d (cu,parents,die))) (struct_union_type_dies d))
*)letpp_all_struct_union_enum_types'd:string=(letctyps:c_typelist=(struct_union_enum_typesd)inString.concat""((Lem_list.mappp_struct_union_type_defn')ctyps))(** ************************************************************ *)(** ** analysis of location and frame data for reverse mapping *)(** ************************************************************ *)(** analysis *)(** simple-minded analysis of location *)letanalyse_locations_rawc(d:dwarf):string=(let(cuh_default:compilation_unit_header)=(letcu=(myheadd.d_compilation_units)incu.cu_header)in(* find all DW_TAG_variable and DW_TAG_formal_parameter dies with a DW_AT_name attribute *)lettags=(Lem_list.maptag_encode["DW_TAG_variable";"DW_TAG_formal_parameter"])inletdies:(compilation_unit*(dielist)*die)list=(find_dies(fundie1->Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tagtags&&has_attribute"DW_AT_name"die1)d)inString.concat""(Lem_list.map(fun(cu,parents,die1)->letats=(Lem_list.list_combinedie1.die_abbreviation_declaration.ad_attribute_specificationsdie1.die_attribute_values)inletfind_ats(s:string)=(myfindNonPure(fun(((at:Nat_big_num.num),(af:Nat_big_num.num)),((pos:Nat_big_num.num),(av:attribute_value)))->Nat_big_num.equal(attribute_encodes)at)ats)inlet((_,_),(_,av_name))=(find_ats"DW_AT_name")inletname1=((matchav_namewith|AV_stringbs->string_of_byte_sequencebs|AV_strpn->pp_debug_str_entryd.d_strn|_->"av_name AV not understood"))inlet((_,_),(_,av_location))=(find_ats"DW_AT_location")inletppd_location=((matchav_locationwith|AV_exprloc(n,bs)->" "^(parse_and_pp_operationsccuh_defaultbs^"\n")|AV_block(n,bs)->" "^(parse_and_pp_operationsccuh_defaultbs^"\n")|AV_sec_offsetn->letlocation_list1=(myfindNonPure(fun(n',_)->Nat_big_num.equaln'n)d.d_loc)inpp_location_listccuh_defaultlocation_list1|_->"av_location AV not understood"))inpp_tag_encodingdie1.die_abbreviation_declaration.ad_tag^(" "^(name1^(":\n"^(ppd_location^"\n")))))dies))(** more proper analysis of locations *)(* TODO: handle this:
In a variable entry representing the definition of a variable (that is, with no
DW_AT_declaration attribute) if no location attribute is present, or if the location attribute is
present but has an empty location description (as described in Section 2.6), the variable is
assumed to exist in the source code but not in the executable program (but see number 10,
below).
In a variable entry representing a non-defining declaration of a variable, the location
specified modifies the location specified by the defining declaration and only applies for the
scope of the variable entry; if no location is specified, then the location specified in the
defining declaration applies.
The location of a variable may be further specified with a DW_AT_segment attribute, if
appropriate.
*)(*
if there's a DW_AT_location that's a location list (DW_FORM_sec_offset/AV_sec_offset) : use that for both the range(s) and location; interpret the range(s) wrt the applicable base address of the compilation unit
if there's a DW_AT_location that's a location expression (DW_FORM_exprloc/AV_exprloc or DW_block/AV_block), look for the closest enclosing range:
- DW_AT_low_pc (AV_addr) and no DW_AT_high_pc or DW_AT_ranges: just the singleton address
- DW_AT_low_pc (AV_addr) and DW_AT_high_pc (either an absolute AV_addr or an offset AV_constantN/AV_constant_SLEB128/AV_constantULEB128) : that range
- DW_AT_ranges (DW_FORM_sec_offset/AV_sec_offset) : get a range list from .debug_ranges; interpret wrt the applicable base address of the compilation unit
- for compilation units: a DW_AT_ranges together with a DW_AT_low_pc to specify the default base address to use in interpeting location and range lists
DW_OP_fbreg in location expressions evaluate the DW_AT_frame_base of
the closest enclosing function - which is either a location expression
or a location list (what happens if the ranges of that location list
don't cover where we are?)
For each variable and formal parameter that has a DW_AT_name, we'll calculate a list of pairs of a concrete (low,high) range and a location expression.
*)letcu_base_addresscu:Nat_big_num.num=((matchfind_attribute_value"DW_AT_low_pc"cu.cu_diewith|Some(AV_addrn)->n|_->(Nat_big_num.of_int0)(*Nothing*)(*Assert_extra.failwith "no cu DW_AT_low_pc"*)))letrange_of_dieccuhstr(dranges:range_list_list)(cu_base_address1:Nat_big_num.num)(die1:die):((Nat_big_num.num*Nat_big_num.num)list)option=((match(find_attribute_value"DW_AT_low_pc"die1,find_attribute_value"DW_AT_high_pc"die1,find_attribute_value"DW_AT_ranges"die1)with|(Some(AV_addrn),None,None)->Some[(n,Nat_big_num.addn((Nat_big_num.of_int1)))](* unclear if this case is used? *)|(Some(AV_addrn1),Some(AV_addrn2),None)->Some[(n1,n2)]|(Some(AV_addrn1),Some(AV_constant_ULEB128n2),None)->Some[(n1,Nat_big_num.addn1n2)](* should be mod all? *)|(Some(AV_addrn1),Some(AV_constant_SLEB128i2),None)->Some[(n1,Nat_big_num.abs(Nat_big_num.add(n1)i2))](* should be mod all? *)|(Some(AV_addrn1),Some(AV_constantN(_,_)),None)->failwith"AV_constantN in range_of_die"|(Some(AV_addrn1),Some(AV_block(n,bs)),None)->letn2=(natural_of_bytesc.endiannessbs)inSome[(n1,Nat_big_num.addn1n2)](* should be mod all? *)(* signed or unsigned interp? *)|(_,None,Some(AV_sec_offsetn))->letrlis=(snd((matchfind_range_listdrangesnwithSomerlis->rlis|none0->failwith("find_range_list failed on AV_sec_offset n="^(Nat_big_num.to_stringn^(" for die\n"^pp_dieccuhstrfalse((Nat_big_num.of_int0))falsedie1))))))inletnns=(interpret_range_listcu_base_address1rlis)inSomenns|(None,None,None)->None|(_,_,_)->Some[](*Assert_extra.failwith "unexpected attribute values in closest_enclosing_range"*)))letrange_of_die_d(d:dwarf)cu(die1:die):((Nat_big_num.num*Nat_big_num.num)list)option=(letc=(p_context_of_dd)inrange_of_dieccu.cu_headerd.d_strd.d_ranges(cu_base_addresscu)die1)letentry_address(die1:die):Nat_big_num.numoption=((match(find_attribute_value"DW_AT_low_pc"die1,find_attribute_value"DW_AT_entry_pc"die1)with|(_,Some(AV_addrn))->Somen|(Some(AV_addrn),_)->Somen|(None,None)->None))letrecclosest_enclosing_rangeccuhstr(dranges:range_list_list)(cu_base_address1:Nat_big_num.num)(parents:dielist):((Nat_big_num.num*Nat_big_num.num)list)option=((matchparentswith|[]->None|die1::parents'->(matchrange_of_dieccuhstrdrangescu_base_address1die1with|((Somex)asy)->y|None->closest_enclosing_rangeccuhstrdrangescu_base_address1parents')))(*
If one of the DW_FORM_data<n> forms is used to represent a signed or unsigned integer, it
can be hard for a consumer to discover the context necessary to determine which
interpretation is intended. Producers are therefore strongly encouraged to use
DW_FORM_sdata or DW_FORM_udata for signed and unsigned integers respectively,
rather than DW_FORM_data<n>.
no kidding - if we get an AV_constantN for DW_AT_high_pc, should it be interpreted as signed or unsigned? *)letrecclosest_enclosing_frame_basedloc(base_address1:Nat_big_num.num)(parents:dielist):attribute_valueoption=((matchparentswith|[]->None|die1::parents'->(matchfind_attribute_value"DW_AT_frame_base"die1with|Someav->Someav|None->closest_enclosing_frame_basedlocbase_address1parents')))letinterpreted_location_of_dieccuhstr(dloc:location_list_list)(dranges:range_list_list)(base_address1:Nat_big_num.num)(parents:dielist)(die1:die):((Nat_big_num.num*Nat_big_num.num*single_location_description)list)option=((* for a simple location expression bs, we look in the enclosing die
tree to find the associated pc range *)letlocationbs=((matchclosest_enclosing_rangeccuhstrdrangesbase_address1(die1::parents)with|Somenns->Some(Lem_list.map(fun(n1,n2)->(n1,n2,bs))nns)|None->(* if there is no such range, we take the full 0 - 0xfff.fff range*)Some[((Nat_big_num.of_int0),(arithmetic_context_of_cuhcuh).ac_max,bs)]))in(matchfind_attribute_value"DW_AT_location"die1with|Some(AV_exprloc(n,bs))->locationbs|Some(AV_block(n,bs))->locationbs(* while for a location list, we take the associated pc range from
each element of the list *)|Some(AV_sec_offsetn)->let(_,llis)=(find_location_listdlocn)inSome(interpret_location_listbase_address1llis)|None->None))(*val analyse_locations : dwarf -> analysed_location_data*)letanalyse_locations(d:dwarf):analysed_location_data=(letc=(p_context_of_dd)in(* let (cuh_default : compilation_unit_header) = let cu = myhead d.d_compilation_units in cu.cu_header in*)(* find all DW_TAG_variable and DW_TAG_formal_parameter dies with a DW_AT_location attribute and either a DW_AT_name or a DW_abstract_origin *)(* (leaving formal parameters of inlined routines with a DW_AT_const_value to the future) *)lettags=(Lem_list.maptag_encode["DW_TAG_variable";"DW_TAG_formal_parameter"])inletdies:(compilation_unit*(dielist)*die)list=(find_dies(fundie1->Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tagtags&&((has_attribute"DW_AT_name"die1||has_attribute"DW_AT_abstract_origin"die1)&&has_attribute"DW_AT_location"die1))d)inLem_list.map(fun((((cu:compilation_unit),(parents:dielist),(die1:die))asx))->letbase_address1=(cu_base_addresscu)inletinterpreted_locations:((Nat_big_num.num*Nat_big_num.num*single_location_description)list)option=(interpreted_location_of_dieccu.cu_headerd.d_strd.d_locd.d_rangesbase_address1parentsdie1)in(x,interpreted_locations))dies)letpp_analysed_locations1ccuh(nnls:(Nat_big_num.num*Nat_big_num.num*single_location_description)list):string=(String.concat""(Lem_list.map(fun(n1,n2,bs)->" "^(pphexn1^(" "^(pphexn2^(" "^parse_and_pp_operationsccuhbs)))))nnls))letpp_analysed_locations2ccuhmnnls:string=((matchmnnlswith|Somennls->pp_analysed_locations1ccuhnnls|None->" <no locations>"))(*
let pp_analysed_locations3 c d str (als: analysed_location_data) : string =
pad_rows
(List.map
(fun ((cu,parents,die),mnnls) ->
[" ";pp_die_abbrev_var c cu.cu_header str 0 false parents die
^ pp_type_info_die_DW_AT_type c d cu cu.cu_header str die;
pp_analysed_locations2 c cu.cu_header mnnls]
)
als
)
let pp_analysed_location_data (d: dwarf) (als: analysed_location_data) : string =
let c = p_context_of_d d in
(* let cu = myhead d.d_compilation_units in
let (cuh_default : compilation_unit_header) = cu.cu_header in
*)
pp_analysed_locations3 c (*HACK*) d d.d_str als
*)letpp_analysed_locations3cdstr(removed:bool)(als:analysed_location_data):(bool(*removed?*)*(string(*name*)*string(*offset*)*string(*kind*))*(unit->string)(*string*)(*type*)*string(*locations*)*(unit->string)(*parents*))list=(Lem_list.map(fun((cu,parents,die1),mnnls)->(removed,pp_die_abbrev_varcdcustrfalseparentsdie1,(*4.5s for only this*)(fun()->pp_type_info_die_DW_AT_typecdcustrdie1),(*12.2s for this and above*)pp_analysed_locations2ccu.cu_headermnnls,(*12.4s for this and above*)(fun()->pp_die_abbrev_var_parentscdcustrparents))(*14.4s for this and above*))als)letpp_analysed_locations3_diffcdstr(als_old:analysed_location_data)(als_new:analysed_location_data):(bool(*removed?*)*(string(*name*)*string(*offset*)*string(*kind*))*(unit->string)(*type*)*string(*locations*)*(unit->string)(*parents*))list=((* maybe alpha sort these? *)letppd_old=(pp_analysed_locations3cdstrtrueals_old)inletppd_new=(pp_analysed_locations3cdstrfalseals_new)in(* the old entries that don't have a same-name new entry *)letppd_gone=(List.filter(fun(removed,(name1,offset,kind),typ,locs,parents)->not(List.exists(fun(removed',(name',offset',kind'),typ',locs',parents')->name1=name')ppd_new))ppd_old)in(* the new entries, each preceded by any same-name old entries (this will display strangely if there's any variable shadowing...) *)letppd_upd=(List.concat(Lem_list.mapMaybe(fun(((removed,((name1,offset,kind)asy),typ,locs,parents)asx))->letsame_name_old=(List.filter(fun(removed',(name',offset',kind'),typ',locs',parents')->(Lem.pair_equal(=)(=)(name1,offset)(name',offset')))ppd_old)in(matchsame_name_oldwith|[((removed',((name',offset',kind')asy'),typ',locs',parents')asx')]->if(Lem.pair_equal(tripleEqualinstance_Basic_classes_Eq_string_dictinstance_Basic_classes_Eq_string_dictinstance_Basic_classes_Eq_string_dict)(=)(y,(*typ,*)locs)(y',(*typ',*)locs'))thenNoneelseSome(List.rev_append(List.revsame_name_old)[x])|_->Some(List.rev_append(List.revsame_name_old)[x])))ppd_new))inList.rev_append(List.revppd_gone)ppd_upd)letpp_analysed_location_format(xs:(bool(*removed?*)*(string(*name*)*string(*offset*)*string(*kind*))*(unit->string)(*string*)(*type*)*string(*locations*)*(unit->string)(*parents*))list):string=(pad_rows(Lem_list.map(fun(((removed,(name1,offset,kind),typ,locs,parents)asx))->[((ifremovedthen"-"else" ")^(name1^(" ("^(offset^(","^(kind^(") "^typ())))))));locs;parents()])xs))letpp_analysed_location_data(d:dwarf)(als:analysed_location_data):string=(letc=(p_context_of_dd)in(* let cu = myhead d.d_compilation_units in
let (cuh_default : compilation_unit_header) = cu.cu_header in
*)pp_analysed_location_format(pp_analysed_locations3c(*HACK*)dd.d_strfalseals))letpp_analysed_location_data_diff(d:dwarf)(als_old:analysed_location_data)(als_new:analysed_location_data):string=(letc=(p_context_of_dd)in(* let cu = myhead d.d_compilation_units in
let (cuh_default : compilation_unit_header) = cu.cu_header in
*)pp_analysed_location_format(pp_analysed_locations3_diffc(*HACK*)dd.d_strals_oldals_new))letpp_analysed_location_data_at_pc(d:dwarf)(alspc:analysed_location_data_at_pc):string=(String.concat""(Lem_list.map(fun((cu,parents,die1),(n1,n2,sld,esl))->" "^(letname1=((matchfind_name_of_died.d_strdie1with|Somes->s|None->"<no name>\n"))in(matcheslwith|Successsl->name1^(" @ "^(pp_single_locationsl^"\n"))|Faile->name1^(" @ "^("<fail: "^(e^">\n"))))))alspc))(*val analysed_locations_at_pc : evaluation_context -> dwarf_static -> natural -> analysed_location_data_at_pc*)letanalysed_locations_at_pc(ev)(ds:dwarf_static)(pc:Nat_big_num.num):analysed_location_data_at_pc=(letc:p_context=({endianness=(ds.ds_dwarf.d_endianness)})inletxs=(Lem_list.mapMaybe(fun(cupd,mnns)->(matchmnnswith|None->None|Somenns->letnns'=(List.filter(fun(n1,n2,sld)->Nat_big_num.greater_equalpcn1&&Nat_big_num.lesspcn2)nns)in(matchnns'with|[]->None|_->Some(cupd,nns'))))ds.ds_analysed_location_data)inList.concat(Lem_list.map(fun((cu,parents,die1),nns)->letac=(arithmetic_context_of_cuhcu.cu_header)inletbase_address1=(cu_base_addresscu)inletmfbloc:attribute_valueoption=(closest_enclosing_frame_baseds.ds_dwarf.d_locbase_address1parents)inLem_list.map(fun(n1,n2,sld)->letel:single_locationerror=(evaluate_location_description_bytescds.ds_dwarf.d_locds.ds_evaluated_frame_infocu.cu_headeracevmfblocpcsld)in((cu,parents,die1),(n1,n2,sld,el)))nns)xs))(*val names_of_address : dwarf -> analysed_location_data_at_pc -> natural -> list string*)letnames_of_address(d:dwarf)(alspc:analysed_location_data_at_pc)(address:Nat_big_num.num):stringlist=(Lem_list.mapMaybe(fun((cu,parents,die1),(n1,n2,sld,esl))->(matcheslwith|Success(SL_simple(SL_memory_addressa))->ifNat_big_num.equalaaddressthen(matchfind_name_of_died.d_strdie1with|Somes->Somes|None->None)elseNone|Success_->None(* just suppress? *)|Faile->None(* just suppress? *)))alspc)(*val filtered_analysed_location_data : dwarf_static -> natural -> analysed_location_data*)letfiltered_analysed_location_datadspc:((compilation_unit*(die)list*die)*((Nat_big_num.num*Nat_big_num.num*Byte_sequence_wrapper.byte_sequence)list)option)list=(Lem_list.mapMaybe(fun(cupd,mnns)->(matchmnnswith|None->None|Somenns->letnns'=(List.filter(fun(n1,n2,sld)->Nat_big_num.greater_equalpcn1&&Nat_big_num.lesspcn2)nns)in(matchnns'with|[]->None(*Just (cupd,Nothing)*)|_::_->Some(cupd,Somenns'))))ds.ds_analysed_location_data)(** ********************************************************************** *)(** ** estimate source-file line extents of each (non-inlined) subprogram *)(** ********************************************************************** *)(* The line number info associates source-file line numbers to
instruction addresses, but doesn't identify which subprogram those
line numbers come from. To recover that, we can use the
DW_TAG_subprogram die DW_AT_decl_file and DW_AT_decl_line info,
which gives the start of each subprogram. For C, function
definitions cannot be nested, so we can estimate their line-number
extents as from their start to the start of the next. Note that
this might be wrong if there are (eg) macro definitions between C
functions. Because of the lack of nesting, for C, just taking the
top-level DW_TAG_subprogram dies of each compilation unit should be
basically ok, and seems also to exclude inlined instances of
subprograms (which otherwise we could exclude by discarding any
with an abstract origin). However, those top-level subprograms are
not necessarily all from the "primary" file of the subprogram, and
conceivably some functions in the file might not be included in
that compilation unit but appear in another. We'll therefore take
all top-level subprograms from all compilation units, partition by
file (up to equality of (compilation directory, include directory,
and path)), and then sort. This assumes that the directory and
path strings from the line number info for different compilation
units are nicely comparable.
We also have to identify the compilation unit referred to by a line
number file entry that's been reported from the line-number
info. The DW_TAG_compile_unit DW_AT_name appears to be the path
concatentation (inserting a "/", not just the string concatenation)
of the lnfe_directory_index's string and the lnfe_path of one the
lnfe's of the line number header pointed to by the compilation
unit's DW_AT_stmt_list, but not necessarily any particular such
lnfe.*)letsubprogram_line_extents_compilation_unitdcu:(string*unpacked_file_entry*Nat_big_num.num)list=(letc=(p_context_of_dd)inletsubprogram_dies=(List.filter(fundie'->Nat_big_num.equaldie'.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subprogram"))cu.cu_die.die_children)inletlnp=(line_number_program_of_compilation_unitdcu)inletlnh=(lnp.lnp_header)inLem_list.mapMaybe(fundie1->(match(find_name_of_died.d_strdie1,find_natural_attribute_value_of_diec"DW_AT_decl_file"die1,find_natural_attribute_value_of_diec"DW_AT_decl_line"die1)with|(Somename1,Somefile,Someline)->Some(name1,unpack_file_entrylnhfile,line)|(_,_,_)->None))subprogram_dies)(* lookup in an association list and also return the list with that entry (if any) removed *)(*val extract : forall 'b 'c. Eq 'b => 'b -> list ('b * 'c) -> (maybe 'c) * list ('b * 'c)*)letrecextractdict_Basic_classes_Eq_byyzs:'coption*('b*'c)list=((matchyzswith|[]->(None,[])|(y',z')::yzs'->ifdict_Basic_classes_Eq_b.isEqual_methody'ythen(Somez',yzs')elselet(result,yzs'')=(extractdict_Basic_classes_Eq_byyzs')in(result,((y',z')::yzs''))))(* partition a list by the result of f, removing duplicates and sorting each partition by lt *)(*val partitionby: forall 'a 'b. Eq 'a , Eq 'b => ('a -> 'b) -> ('a -> 'a -> bool) -> list 'a -> list ('b * list 'a) -> list ('b * list 'a)*)letrecpartitionbydict_Basic_classes_Eq_adict_Basic_classes_Eq_bfltxsacc:('b*'alist)list=((matchxswith|[]->acc|x::xs'->lety=(fx)inlet(result,acc')=(extractdict_Basic_classes_Eq_byacc)inletacc''=((matchresultwith|Somexs''->ifLem_list.elemdict_Basic_classes_Eq_axxs''thenaccelse((y,Lem_sorting.insertByltxxs'')::acc')|None->(y,[x])::acc))inpartitionbydict_Basic_classes_Eq_adict_Basic_classes_Eq_bfltxs'acc''))letsubprogram_line_extentsd:(unpacked_file_entry*(string*unpacked_file_entry*Nat_big_num.num)list)list=(letsubprograms:(string*unpacked_file_entry*Nat_big_num.num)list=(List.concat(map(subprogram_line_extents_compilation_unitd)d.d_compilation_units))inpartitionby(instance_Basic_classes_Eq_tup3_dictinstance_Basic_classes_Eq_string_dict(instance_Basic_classes_Eq_tup3_dict(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)instance_Basic_classes_Eq_string_dict)instance_Basic_classes_Eq_Num_natural_dict)(instance_Basic_classes_Eq_tup3_dict(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)instance_Basic_classes_Eq_string_dict)(fun(name1,ufe,line)->ufe)(fun(name1,ufe,line)->fun(name',ufe',line')->Nat_big_num.lesslineline')subprograms[])letpp_subprogramsdict_Show_Show_asles:string=(String.concat"\n"(Lem_list.map(fun(ufe,sles')->pp_ufeufe^("\n"^String.concat""(Lem_list.map(fun(name1,ufe,line)->" "^(dict_Show_Show_a.show_methodline^(" "^(name1^"\n"))))sles')))sles))letrecfind_by_linedict_Basic_classes_Ord_blineslesline_lastname_last:'a=((matchsleswith|[]->name_last|(name',ufe',line')::sles'->ifdict_Basic_classes_Ord_b.isGreaterEqual_methodlineline_last&&dict_Basic_classes_Ord_b.isLess_methodlineline'thenname_lastelsefind_by_linedict_Basic_classes_Ord_blinesles'line'name'))letsubprogram_at_linesubprogram_line_extents1(ufe:unpacked_file_entry)(line:Nat_big_num.num):string=((match(lookupBy(tripleEqual(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)(instance_Basic_classes_Eq_Maybe_maybe_dictinstance_Basic_classes_Eq_string_dict)instance_Basic_classes_Eq_string_dict)ufesubprogram_line_extents1)with|None->"no matching unpacked_file_entry"|Somesles->find_by_lineinstance_Basic_classes_Ord_Num_natural_dictlinesles((Nat_big_num.of_int0))"file preamble"))(** ************************************************************ *)(** ** pull out subprograms *)(** ************************************************************ *)(*
val analyse_subprograms : dwarf -> analysed_location_data
let analyse_subprograms (d: dwarf) : analysed_location_data =
let c = p_context_of_d d in
let (cuh_default : compilation_unit_header) = let cu = myhead d.d_compilation_units in cu.cu_header in
(* find all DW_TAG_subprogram dies *)
let tags = List.map tag_encode ["DW_TAG_subprogram"] in
let dies : list (compilation_unit * (list die) * die) =
find_dies
(fun die ->
List.elem die.die_abbreviation_declaration.ad_tag tags
&& has_attribute "DW_AT_name" die
&& has_attribute "DW_AT_location" die)
d in
List.map
(fun (((cu:compilation_unit), (parents: list die), (die: die)) as x) ->
let name =
match find_name_of_die d.d_str die with
| Just s -> s
| Nothing -> "<no name>\n"
end in
let entry_point : maybe attribute_value =
match find_attribute_value "DW_AT_entry_pc" die with
| Nothing -> Nothing
|
let base_address = cu_base_address cu in
let interpreted_locations : maybe (list (natural * natural * single_location_description)) =
interpreted_location_of_die c cuh_default d.d_loc d.d_ranges base_address parents die in
(x,interpreted_locations)
)
dies
*)(** ************************************************************ *)(** ** evaluation of line-number info *)(** ************************************************************ *)letinitial_line_number_registers(lnh:line_number_header):line_number_registers=({lnr_address=((Nat_big_num.of_int0));lnr_op_index=((Nat_big_num.of_int0));lnr_file=((Nat_big_num.of_int1));lnr_line=((Nat_big_num.of_int1));lnr_column=((Nat_big_num.of_int0));lnr_is_stmt=(lnh.lnh_default_is_stmt);lnr_basic_block=false;lnr_end_sequence=false;lnr_prologue_end=false;lnr_epilogue_begin=false;lnr_isa=((Nat_big_num.of_int0));lnr_discriminator=((Nat_big_num.of_int0));})letevaluate_line_number_operation(lnh:line_number_header)((s:line_number_registers),(lnrs:line_number_registerslist))(lno:line_number_operation):line_number_registers*line_number_registerslist=(letnew_addresssoperation_advance=(Nat_big_num.adds.lnr_address(Nat_big_num.mullnh.lnh_minimum_instruction_length(Nat_big_num.div(Nat_big_num.adds.lnr_op_indexoperation_advance)lnh.lnh_maximum_operations_per_instruction)))inletnew_op_indexsoperation_advance=(Nat_big_num.modulus(Nat_big_num.adds.lnr_op_indexoperation_advance)lnh.lnh_maximum_operations_per_instruction)in(matchlnowith|DW_LN_specialadjusted_opcode->letoperation_advance=(Nat_big_num.divadjusted_opcodelnh.lnh_line_range)inletline_increment=(Nat_big_num.addlnh.lnh_line_base((Nat_big_num.modulusadjusted_opcodelnh.lnh_line_range)))inlets'=({swithlnr_line=(partialNaturalFromInteger(Nat_big_num.add(s.lnr_line)line_increment));lnr_address=(new_addresssoperation_advance);lnr_op_index=(new_op_indexsoperation_advance);})inletlnrs'=(s'::lnrs)inlets''=({s'withlnr_basic_block=false;lnr_prologue_end=false;lnr_epilogue_begin=false;lnr_discriminator=((Nat_big_num.of_int0));})in(s'',lnrs')|DW_LNS_copy->letlnrs'=(s::lnrs)inlets'=({swithlnr_basic_block=false;lnr_prologue_end=false;lnr_epilogue_begin=false;lnr_discriminator=((Nat_big_num.of_int0));})in(s',lnrs')|DW_LNS_advance_pcoperation_advance->lets'=({swithlnr_address=(new_addresssoperation_advance);lnr_op_index=(new_op_indexsoperation_advance);})in(s',lnrs)|DW_LNS_advance_lineline_increment->lets'=({swithlnr_line=(partialNaturalFromInteger(Nat_big_num.add(s.lnr_line)line_increment))})in(s',lnrs)|DW_LNS_set_filen->lets'=({swithlnr_file=n})in(s',lnrs)|DW_LNS_set_columnn->lets'=({swithlnr_column=n})in(s',lnrs)|DW_LNS_negate_stmt->lets'=({swithlnr_is_stmt=(nots.lnr_is_stmt)})in(s',lnrs)|DW_LNS_set_basic_block->lets'=({swithlnr_basic_block=true})in(s',lnrs)|DW_LNS_const_add_pc->letopcode=((Nat_big_num.of_int255))inletadjusted_opcode=(Nat_big_num.sub_natopcodelnh.lnh_opcode_base)inletoperation_advance=(Nat_big_num.divadjusted_opcodelnh.lnh_line_range)inlets'=({swithlnr_address=(new_addresssoperation_advance);lnr_op_index=(new_op_indexsoperation_advance);})in(s',lnrs)|DW_LNS_fixed_advance_pcn->lets'=({swithlnr_address=(Nat_big_num.adds.lnr_addressn);lnr_op_index=((Nat_big_num.of_int0));})in(s',lnrs)|DW_LNS_set_prologue_end->lets'=({swithlnr_prologue_end=true})in(s',lnrs)|DW_LNS_set_epilogue_begin->lets'=({swithlnr_epilogue_begin=true})in(s',lnrs)|DW_LNS_set_isan->lets'=({swithlnr_isa=n})in(s',lnrs)|DW_LNE_end_sequence->lets'=({swithlnr_end_sequence=true})inletlnrs'=(s'::lnrs)inlets''=(initial_line_number_registerslnh)in(s'',lnrs')|DW_LNE_set_addressn->lets'=({swithlnr_address=n;lnr_op_index=((Nat_big_num.of_int0));})in(s',lnrs)|DW_LNE_define_file(s,n1,n2,n3)->failwith"DW_LNE_define_file not implemented"(*TODO: add to file list in header - but why is this in the spec? *)|DW_LNE_set_discriminatorn->lets'=({swithlnr_discriminator=n})in(s',lnrs)))letrecevaluate_line_number_operations(lnh:line_number_header)((s:line_number_registers),(lnrs:line_number_registerslist))(lnos:line_number_operationlist):line_number_registers*line_number_registerslist=((matchlnoswith|[]->(s,lnrs)|lno::lnos'->let(s',lnrs')=(evaluate_line_number_operationlnh(s,lnrs)lno)inevaluate_line_number_operationslnh(s',lnrs')lnos'))letevaluate_line_number_program(lnp:line_number_program):line_number_registerslist=(List.rev(snd(evaluate_line_number_operationslnp.lnp_header((initial_line_number_registerslnp.lnp_header),[])lnp.lnp_operations)))letevaluated_line_info_of_compilation_unitdcuevaluated_line_info1:'a=(letc=(p_context_of_dd)inletoffset=(line_number_offset_of_compilation_unitccu)in(matchLem_list.list_find_opt(fun(lnh,lnrs)->Nat_big_num.equallnh.lnh_offsetoffset)evaluated_line_info1with|None->failwith"compilation unit line number offset not found"|Some(lnh,lnrs)->lnrs))letpp_line_number_registerslnr:string=(""^("address = "^(pphexlnr.lnr_address^("\n"^("op_index = "^(Nat_big_num.to_stringlnr.lnr_op_index^("\n"^("file = "^(Nat_big_num.to_stringlnr.lnr_file^("\n"^("line = "^(Nat_big_num.to_stringlnr.lnr_line^("\n"^("column = "^(Nat_big_num.to_stringlnr.lnr_column^("\n"^("is_stmt = "^(string_of_boollnr.lnr_is_stmt^("\n"^("basic_block = "^(string_of_boollnr.lnr_basic_block^("\n"^("end_sequence = "^(string_of_boollnr.lnr_end_sequence^("\n"^("prologue_end = "^(string_of_boollnr.lnr_prologue_end^("\n"^("epilogue_begin = "^(string_of_boollnr.lnr_epilogue_begin^("\n"^("isa = "^(Nat_big_num.to_stringlnr.lnr_isa^("\n"^("discriminator = "^(pphexlnr.lnr_discriminator^"\n"))))))))))))))))))))))))))))))))))))letpp_line_number_registers_tightlnr:stringlist=([pphexlnr.lnr_address;Nat_big_num.to_stringlnr.lnr_op_index;Nat_big_num.to_stringlnr.lnr_file;Nat_big_num.to_stringlnr.lnr_line;Nat_big_num.to_stringlnr.lnr_column;string_of_boollnr.lnr_is_stmt;string_of_boollnr.lnr_basic_block;string_of_boollnr.lnr_end_sequence;string_of_boollnr.lnr_prologue_end;string_of_boollnr.lnr_epilogue_begin;Nat_big_num.to_stringlnr.lnr_isa;pphexlnr.lnr_discriminator])letpp_line_number_registersslnrs:string=(pad_rows(["address";"op_index";"file";"line";"column";"is_stmt";"basic_block";"end_sequence";"prologue_end";"epilogue_begin";"isa";"discriminator"]::(Lem_list.mappp_line_number_registers_tightlnrs)))letpp_evaluated_line_info(eli:evaluated_line_info):string=(String.concat"\n"(Lem_list.map(fun(lnh,lnrs)->pp_line_number_headerlnh^("\n"^pp_line_number_registersslnrs))eli))(* readef example:
Decoded dump of debug contents of section .debug_line:
CU: /var/local/stephen/work/devel/rsem/ppcmem2/system/tests-adhoc/simple-malloc/test-concurrent.c:
File name Line number Starting address
test-concurrent.c 11 0x400144
test-concurrent.c 12 0x40014c
test-concurrent.c 13 0x400154
test-concurrent.c 14 0x400158
test-concurrent.c 17 0x400160
/var/local/stephen/work/devel/rsem/ppcmem2/system/tests-adhoc/simple-malloc/../thread_start_aarch64.h:
thread_start_aarch64.h 34 0x400168
thread_start_aarch64.h 36 0x400174
/var/local/stephen/work/devel/rsem/ppcmem2/system/tests-adhoc/simple-malloc/test-concurrent.c:
test-concurrent.c 19 0x400174
test-concurrent.c 20 0x40017c
test-concurrent.c 22 0x400180
CU: /var/local/stephen/work/devel/rsem/ppcmem2/system/tests-adhoc/simple-malloc/malloc.c:
...
*)letsource_lines_of_address(ds:dwarf_static)(a:Nat_big_num.num):(unpacked_file_entry*Nat_big_num.num*line_number_registers*string(*function*))list=(List.concat(Lem_list.map(fun(lnh,lnrs)->myfiltermaybe(funlnr->ifNat_big_num.equalalnr.lnr_address&¬lnr.lnr_end_sequencethenSome(unpack_file_entrylnhlnr.lnr_file,lnr.lnr_line,lnr,subprogram_at_lineds.ds_subprogram_line_extents(unpack_file_entrylnhlnr.lnr_file)lnr.lnr_line)elseNone)lnrs)ds.ds_evaluated_line_info))(** ************************************************************ *)(** ** collecting all the statically calculated analysis info *)(** ************************************************************ *)(*val extract_dwarf_static : elf_file -> maybe dwarf_static*)letextract_dwarf_staticf1:(dwarf_static)option=((matchextract_dwarff1with|None->None|Somedwarf1->(*let _ = my_debug5 (pp_dwarf dwarf) in *)letald:analysed_location_data=(analyse_locationsdwarf1)inletefi:evaluated_frame_info=(evaluate_frame_infodwarf1)inleteli:evaluated_line_info=(Lem_list.map(funlnp->(lnp.lnp_header,evaluate_line_number_programlnp))dwarf1.d_line_info)inletsle=(subprogram_line_extentsdwarf1)inletds=({ds_dwarf=dwarf1;ds_analysed_location_data=ald;ds_evaluated_frame_info=efi;ds_evaluated_line_info=eli;ds_subprogram_line_extents=sle;})inSomeds))(** ************************************************************ *)(** ** collect simple die tree view *)(** ************************************************************ *)letdecl_of_diedsubprogram_line_extents1cudie1:(unpacked_file_entry*int(*line*)*string(*subprogram name*))option=(letc=(p_context_of_dd)inletlnp=(line_number_program_of_compilation_unitdcu)inletlnh=(lnp.lnp_header)in(match(find_natural_attribute_value_of_diec"DW_AT_decl_file"die1,find_natural_attribute_value_of_diec"DW_AT_decl_line"die1)with|(Somefile,Someline)->letufe=(unpack_file_entrylnhfile)inletsubprogram_name=(subprogram_at_linesubprogram_line_extents1ufeline)inSome(ufe,Nat_big_num.to_intline,subprogram_name)|(_,_)->None))letcall_site_of_diedsubprogram_line_extents1cudie1:(unpacked_file_entry*int(*line*)*string(*subprogram name*))option=(letc=(p_context_of_dd)inletlnp=(line_number_program_of_compilation_unitdcu)inletlnh=(lnp.lnp_header)in(match(find_natural_attribute_value_of_diec"DW_AT_call_file"die1,find_natural_attribute_value_of_diec"DW_AT_call_line"die1)with|(Somefile,Someline)->letufe=(unpack_file_entrylnhfile)inletsubprogram_name=(subprogram_at_linesubprogram_line_extents1ufeline)inSome(ufe,Nat_big_num.to_intline,subprogram_name)|(_,_)->None))letmk_sdt_unspecified_parameter(d:dwarf)subprogram_line_extents1cuparentsdie1:sdt_unspecified_parameteroption=(ifnot(Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tag[tag_encode"DW_TAG_unspecified_parameters"])thenNoneelseSome())(*
let strict_msvfp x e s z =
match x with
| Just y -> y
| Nothing ->
Assert_extra.failwith ("mk_sdt_variable_or_formal_parameter strict failure " ^ e ^ " on \n" ^ s z ^ "\n")
end
*)letrecmk_sdt_variable_or_formal_parameter(d:dwarf)subprogram_line_extents1cuparentsdie1:sdt_variable_or_formal_parameteroption=(ifnot(Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tag[tag_encode"DW_TAG_variable";tag_encode"DW_TAG_formal_parameter"])thenNoneelseletc=(p_context_of_dd)in(* let s (cu,parents,die) = pp_die c cu.cu_header d.d_str true 0 false die in*)letcupdie1=(cu,parents,die1)inletkind=(ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_variable")thenSVPK_varelseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_formal_parameter")thenSVPK_paramelsefailwith("unreachable bad kind"))in(* find aDW_AT_specification die, if it exists. TODO: how should this interact with abstract origins? *)letmcupdie_spec=(find_reference_attribute_of_diecdcud.d_str"DW_AT_specification"die1)inSome({svfp_cupdie=cupdie1;svfp_kind=kind;(* svfp_name = strict_msvfp (find_name_of_die_using_abstract_origin_and_spec c d cu d.d_str die mcupdie_spec) "no name" s cupdie;*)svfp_name=((match(find_name_of_die_using_abstract_origin_and_speccdcud.d_strdie1mcupdie_spec)withSomename1->name1|None->"no name"));svfp_type=(*strict_msvfp*)(find_DW_AT_type_of_die_deep_using_abstract_origindcupdie1)(*"no type" s cupdie*);svfp_abstract_origin=((matchfind_reference_attribute_of_diecdcud.d_str"DW_AT_abstract_origin"die1with|None->None|Some(((cu',parents',die')ascupdie'))->mk_sdt_variable_or_formal_parameterdsubprogram_line_extents1cu'parents'die'));svfp_const_value=(find_integer_attribute_value_of_diec"DW_AT_const_value"die1);svfp_external=((matchfind_flag_attribute_value_of_die_using_abstract_origind"DW_AT_external"cupdie1withSomeb->b|None->false));svfp_declaration=((matchfind_flag_attribute_value_of_die_using_abstract_origind"DW_AT_declaration"cupdie1withSomeb->b|None->false));svfp_locations=(letbase_address1=(cu_base_addresscu)inletinterpreted_locations:((Nat_big_num.num*Nat_big_num.num*single_location_description)list)option=(interpreted_location_of_dieccu.cu_headerd.d_strd.d_locd.d_rangesbase_address1parentsdie1)inLem.option_map(funnnbss->Lem_list.map(fun(n1,n2,bs)->(n1,n2,parse_operations_bsccu.cu_headerbs))nnbss)interpreted_locations);svfp_decl=(decl_of_diedsubprogram_line_extents1cudie1);}))letstrict_mssxesz:'a=((matchxwith|Somey->y|None->failwith("mk_sdt_subroutine strict failure "^(e^(" on \n"^(sz^"\n"))))))letrecmk_sdt_subroutine(d:dwarf)subprogram_line_extents1(cu:compilation_unit)parents(die1:die):sdt_subroutineoption=(ifnot(Lem_list.eleminstance_Basic_classes_Eq_Num_natural_dictdie1.die_abbreviation_declaration.ad_tag[tag_encode"DW_TAG_subprogram";tag_encode"DW_TAG_inlined_subroutine"])thenNoneelseletc=(p_context_of_dd)in(* let s (cu,parents,die) : string = pp_die c cu.cu_header d.d_str true 0 false die in*)letcupdie1=(cu,parents,die1)inletparents'=(die1::parents)inletkind=(ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subprogram")thenSSK_subprogramelseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_inlined_subroutine")thenSSK_inlined_subroutineelsefailwith("unreachable bad kind"))inSome({ss_cupdie=cupdie1;ss_name=((*strict_mss ( *)find_name_of_die_using_abstract_origincdcud.d_strdie1)(* ) "no name" s cupdie;*);ss_kind=kind;ss_call_site=(call_site_of_diedsubprogram_line_extents1cudie1);ss_abstract_origin=((matchfind_reference_attribute_of_diecdcud.d_str"DW_AT_abstract_origin"die1with|None->None|Some(((cu',parents',die')ascupdie'))->mk_sdt_subroutinedsubprogram_line_extents1cu'parents'die'));ss_type=(find_DW_AT_type_of_die_deep(*_using_abstract_origin*)dcupdie1);ss_vars=(Lem_list.mapMaybe(mk_sdt_variable_or_formal_parameterdsubprogram_line_extents1cuparents')die1.die_children);ss_unspecified_parameters=(Lem_list.mapMaybe(mk_sdt_unspecified_parameterdsubprogram_line_extents1cuparents')die1.die_children);ss_entry_address=(entry_addressdie1);ss_pc_ranges=(range_of_die_ddcudie1);ss_subroutines=(Lem_list.mapMaybe(mk_sdt_subroutinedsubprogram_line_extents1cuparents')die1.die_children);ss_lexical_blocks=(Lem_list.mapMaybe(mk_sdt_lexical_blockdsubprogram_line_extents1cuparents')die1.die_children);ss_decl=(decl_of_diedsubprogram_line_extents1cudie1);ss_noreturn=((matchfind_flag_attribute_value_of_die_using_abstract_origind"DW_AT_noreturn"cupdie1withSomeb->b|None->false));ss_external=((matchfind_flag_attribute_value_of_die_using_abstract_origind"DW_AT_external"cupdie1withSomeb->b|None->false));}))andmk_sdt_lexical_block(d:dwarf)subprogram_line_extents1(cu:compilation_unit)parents(die1:die):sdt_lexical_blockoption=(ifnot(Nat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_lexical_block"))thenNoneelseletc=(p_context_of_dd)in(*let s (cu,parents,die) : string = pp_die c cu.cu_header d.d_str true 0 false die in*)letcupdie1=(cu,parents,die1)inletparents'=(die1::parents)inSome({slb_cupdie=cupdie1;slb_vars=(Lem_list.mapMaybe(mk_sdt_variable_or_formal_parameterdsubprogram_line_extents1cuparents')die1.die_children);slb_pc_ranges=(range_of_die_ddcudie1);slb_subroutines=(Lem_list.mapMaybe(mk_sdt_subroutinedsubprogram_line_extents1cuparents')die1.die_children);slb_lexical_blocks=(Lem_list.mapMaybe(mk_sdt_lexical_blockdsubprogram_line_extents1cuparents')die1.die_children);}))letstrict_mscuxesz:'a=((matchxwith|Somey->y|None->failwith("mk_sdt_compilation_unit strict failure "^(e^(" on \n"^(sz^"\n"))))))letmk_sdt_compilation_unit(d:dwarf)subprogram_line_extents1(cu:compilation_unit):sdt_compilation_unit=(letc=(p_context_of_dd)inlets(cu,(parents:dielist),die1):string=(pp_dieccu.cu_headerd.d_strtrue((Nat_big_num.of_int0))falsedie1)inletcupdie1=(cu,[],cu.cu_die)inletparents'=([cu.cu_die])in{scu_cupdie=(cu,[],cu.cu_die);scu_name=(strict_mscu(find_name_of_died.d_strcu.cu_die)"no name"scupdie1);scu_subroutines=(Lem_list.mapMaybe(mk_sdt_subroutinedsubprogram_line_extents1cuparents')cu.cu_die.die_children);scu_vars=(Lem_list.mapMaybe(mk_sdt_variable_or_formal_parameterdsubprogram_line_extents1cuparents')cu.cu_die.die_children);scu_pc_ranges=(range_of_die_ddcucu.cu_die);})letmk_sdt_dwarf(d:dwarf)subprogram_line_extents1:sdt_dwarf=({sd_compilation_units=(Lem_list.map(mk_sdt_compilation_unitdsubprogram_line_extents1)d.d_compilation_units);})(* **** verbose pp of simple die tree view *************** *)letpp_sdt_unspecified_parameter(level:Nat_big_num.num)(sup:sdt_unspecified_parameter):string=(indent_leveltruelevel^("unspecified parameters"^"\n"))letpp_parsed_single_location_description(level:Nat_big_num.num)((n1:Nat_big_num.num),(n2:Nat_big_num.num),(ops:operationlist)):string=(letindent=(indent_leveltruelevel)inindent^(pphexn1^(" "^(pphexn2^(" ("^(pp_operationsops^(")"^"\n")))))))letpp_pc_ranges(level:Nat_big_num.num)(rso:((Nat_big_num.num*Nat_big_num.num)list)option):string=((matchrsowith|None->"none\n"|Somers->letindent=(indent_leveltruelevel)in"\n"^String.concat""(Lem_list.map(fun(n1,n2)->indent^(pphexn1^(" "^(pphexn2^"\n"))))rs)))letpp_sdt_maybexf:string=((matchxwithNone->"none\n"|Somey->fy))letpp_sdt_maybe'fx:string=(pp_sdt_maybexf)letpp_sdt_listxsf:string=((matchxswith[]->"none\n"|_->"\n"^String.concat""((Lem_list.mapf)xs)))letpp_sdt_variable_or_formal_parameter(level:Nat_big_num.num)(svfp:sdt_variable_or_formal_parameter):string=(letindent=(indent_leveltruelevel)in""^(indent^("name:"^(svfp.svfp_name^("\n"^(indent^("cupdie:"^(pp_cupdie3svfp.svfp_cupdie^("\n"^(indent^("kind:"^(((matchsvfp.svfp_kindwithSVPK_var->"var"|SVPK_param->"param"))^("\n"^(indent^("type:"^(pp_sdt_maybe'pp_type_info_deepsvfp.svfp_type^("\n"^(indent^("const_value:"^(string_of_maybeinstance_Show_Show_Num_integer_dictsvfp.svfp_const_value^("\n"^(indent^("external:"^(string_of_boolsvfp.svfp_external^("\n"^(indent^("declaration:"^(string_of_boolsvfp.svfp_declaration^("\n"^(indent^("locations:"^(pp_sdt_maybesvfp.svfp_locations(funlocs->"\n"^String.concat""(Lem_list.map(pp_parsed_single_location_description(Nat_big_num.addlevel((Nat_big_num.of_int1))))locs))^(indent^("decl:"^(pp_sdt_maybesvfp.svfp_decl(funud->"\n"^(indent_leveltrue(Nat_big_num.addlevel((Nat_big_num.of_int1)))^(pp_udud^"\n")))^"\n")))))))))))))))))))))))))))))))))))letrecpp_sdt_subroutine(level:Nat_big_num.num)(ss:sdt_subroutine):string=(letindent=(indent_leveltruelevel)in""^(indent^("name:"^(pp_sdt_maybess.ss_name(funname1->name1^"\n")^(indent^("cupdie:"^(pp_cupdie3ss.ss_cupdie^("\n"^(indent^("kind:"^(((matchss.ss_kindwithSSK_subprogram->"subprogram"|SSK_inlined_subroutine->"inlined subroutine"))^("\n"^(indent^("call site:"^(pp_sdt_maybess.ss_call_site(funud->"\n"^(indent_leveltrue(Nat_big_num.addlevel((Nat_big_num.of_int1)))^(pp_udud^"\n")))^(indent^("abstract origin:"^(pp_sdt_maybess.ss_abstract_origin(pp_sdt_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("type:"^(pp_sdt_maybess.ss_type(funtyp->pp_type_info_deeptyp^"\n")^(indent^("vars:"^(pp_sdt_listss.ss_vars(pp_sdt_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("unspecified_parameters:"^(pp_sdt_listss.ss_unspecified_parameters(pp_sdt_unspecified_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("entry address: "^(pp_sdt_maybess.ss_entry_address(funn->pphexn^"\n")^(indent^("pc ranges:"^(pp_pc_ranges(Nat_big_num.addlevel((Nat_big_num.of_int1)))ss.ss_pc_ranges^(indent^("subroutines:"^(pp_sdt_listss.ss_subroutines(pp_sdt_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("lexical_blocks:"^(pp_sdt_listss.ss_lexical_blocks(pp_sdt_lexical_block(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("decl:"^(pp_sdt_maybess.ss_decl(funud->"\n"^(indent_leveltrue(Nat_big_num.addlevel((Nat_big_num.of_int1)))^(pp_udud^"\n")))^(indent^("noreturn:"^(string_of_boolss.ss_noreturn^("\n"^(indent^("external:"^(string_of_boolss.ss_external^("\n"^"\n"))))))))))))))))))))))))))))))))))))))))))))))))))andpp_sdt_lexical_block(level:Nat_big_num.num)(lb:sdt_lexical_block):string=(letindent=(indent_leveltruelevel)in""^(indent^("cupdie:"^(pp_cupdie3lb.slb_cupdie^("\n"^(indent^("pc ranges:"^(pp_pc_ranges(Nat_big_num.addlevel((Nat_big_num.of_int1)))lb.slb_pc_ranges^(indent^("vars:"^(pp_sdt_listlb.slb_vars(pp_sdt_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("subroutines :"^(pp_sdt_listlb.slb_subroutines(pp_sdt_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("lexical_blocks:"^(pp_sdt_listlb.slb_lexical_blocks(pp_sdt_lexical_block(Nat_big_num.addlevel((Nat_big_num.of_int1))))^"\n")))))))))))))))))letpp_sdt_compilation_unit(level:Nat_big_num.num)(cu:sdt_compilation_unit):string=(letindent=(indent_leveltruelevel)in""^(indent^("name:"^(cu.scu_name^("\n"^(indent^("cupdie:"^(pp_cupdie3cu.scu_cupdie^("\n"^(indent^("pc ranges:"^(pp_pc_ranges(Nat_big_num.addlevel((Nat_big_num.of_int1)))cu.scu_pc_ranges^(indent^("vars:"^(pp_sdt_listcu.scu_vars(pp_sdt_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("subroutines :"^(pp_sdt_listcu.scu_subroutines(pp_sdt_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^"\n"))))))))))))))))))letpp_sdt_dwarf(sdt_d:sdt_dwarf):string=(letindent_level1=((Nat_big_num.of_int0))inString.concat""(Lem_list.map(pp_sdt_compilation_unitindent_level1)sdt_d.sd_compilation_units))(* **** concise pp of simple die tree view *************** *)(* **************** global vars ************* *)letpp_sdt_concise_variable_or_formal_parameter(level:Nat_big_num.num)(svfp:sdt_variable_or_formal_parameter):string=(letindent=(indent_leveltruelevel)in""^(indent(* ^ indent ^ "cupdie:" ^ pp_cupdie3 svfp.svfp_cupdie ^ "\n"*)(*^ indent ^ "name:" ^*)^(svfp.svfp_name^(" "(*^ indent ^ "kind:" *)^(((matchsvfp.svfp_kindwithSVPK_var->"var"|SVPK_param->"param"))^(" "(*^ indent ^ "type:" *)^(pp_sdt_maybe'pp_type_info_deepsvfp.svfp_type^(" "(*^ indent ^ "const_value:"*)^((matchsvfp.svfp_const_valuewith|None->""|Somev->"const:"^(Nat_big_num.to_stringv^" "))(*^ indent ^ "external:" ^ show svfp.svfp_external ^ "\n"*)(*^ indent ^ "declaration:" ^ show svfp.svfp_declaration ^ "\n"*)(*^ indent ^ "locations:" *)^((matchsvfp.svfp_locationswithNone->"no locations\n"|Somelocs->"\n"^String.concat""(Lem_list.map(pp_parsed_single_location_description(Nat_big_num.addlevel((Nat_big_num.of_int1))))locs))))))))))))(* ^ indent ^ "decl:" ^ (match svfp.svfp_decl with Nothing -> "none\n" | Just ((ufe,line) as ud) -> "\n" ^ indent_level true (level+1) ^ pp_ufe ufe ^ " " ^ show line ^ "\n" end)*)letpp_sdt_globals_compilation_unit(level:Nat_big_num.num)(cu:sdt_compilation_unit):string=(letindent=(indent_leveltruelevel)in""(* ^ indent ^ "cupdie:" ^ pp_cupdie3 cu.scu_cupdie ^ "\n"*)^(indent^((*"name:" ^*)cu.scu_name^("\n"(* ^ indent ^ "vars:" ^ "\n"*)^String.concat""(Lem_list.map(pp_sdt_concise_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))cu.scu_vars)))))(* ^ indent ^ "subroutines :" ^ (match cu.scu_subroutines with | [] -> "none\n" | sus -> "\n" ^ String.concat "\n" (List.map (pp_sdt_subroutine (level+1)) sus) end) *)letpp_sdt_globals_dwarf(sdt_d:sdt_dwarf):string=(letindent_level1=((Nat_big_num.of_int0))inString.concat""(Lem_list.map(pp_sdt_globals_compilation_unitindent_level1)sdt_d.sd_compilation_units))(* ****************** local vars *************** *)letrecpp_sdt_locals_subroutine(level:Nat_big_num.num)(ss:sdt_subroutine):string=(letindent=(indent_leveltruelevel)in""^(indent(*^ "name:" ^*)^(pp_sdt_maybess.ss_name(funname1->name1^"\n")(* ^ indent ^ "cupdie:" ^ pp_cupdie3 ss.ss_cupdie ^ "\n"*)^(indent^("kind:"^(((matchss.ss_kindwithSSK_subprogram->"subprogram"|SSK_inlined_subroutine->"inlined subroutine"))^("\n"^(indent^("entry address: "^(pp_sdt_maybess.ss_entry_address(funn->pphexn^"\n")^(indent^("call site:"^(pp_sdt_maybess.ss_call_site(funud->"\n"^(indent_leveltrue(Nat_big_num.addlevel((Nat_big_num.of_int1)))^(pp_udud^"\n")))^(indent^("abstract origin:"^(pp_sdt_maybess.ss_abstract_origin(funs->"\n"^pp_sdt_locals_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1)))s)(* ^ indent ^ "type:" ^ pp_sdt_maybe ss.ss_type (fun typ -> pp_type_info_deep typ ^"\n" end)*)^(indent^("vars:"^(pp_sdt_listss.ss_vars(pp_sdt_concise_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("unspecified_parameters:"^(pp_sdt_listss.ss_unspecified_parameters(pp_sdt_unspecified_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))(* ^ indent ^ "pc ranges:" ^ pp_pc_ranges (level+1) ss.ss_pc_ranges*)^(indent^("subroutines:"^(pp_sdt_listss.ss_subroutines(pp_sdt_locals_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("lexical_blocks:"^(pp_sdt_listss.ss_lexical_blocks(pp_sdt_locals_lexical_block(Nat_big_num.addlevel((Nat_big_num.of_int1))))(* ^ indent ^ "decl:" ^ pp_sdt_maybe ss.ss_decl (fun ((ufe,line) as ud) -> "\n" ^ indent_level true (level+1) ^ pp_ufe ufe ^ " " ^ show line ^ "\n" end)*)(* ^ indent ^ "noreturn:" ^ show ss.ss_noreturn ^ "\n"*)(* ^ indent ^ "external:" ^ show ss.ss_external ^"\n"*)^"\n"))))))))))))))))))))))))))))andpp_sdt_locals_lexical_block(level:Nat_big_num.num)(lb:sdt_lexical_block):string=(letindent=(indent_leveltruelevel)in""(* ^ indent ^ "cupdie:" ^ pp_cupdie3 lb.slb_cupdie ^ "\n"*)^(indent^("vars:"^(pp_sdt_listlb.slb_vars(pp_sdt_concise_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))(* ^ indent ^ "pc ranges:" ^ pp_pc_ranges (level+1) lb.slb_pc_ranges*)^(indent^("subroutines :"^(pp_sdt_listlb.slb_subroutines(pp_sdt_locals_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("lexical_blocks:"^(pp_sdt_listlb.slb_lexical_blocks(pp_sdt_locals_lexical_block(Nat_big_num.addlevel((Nat_big_num.of_int1))))^"\n"))))))))))letpp_sdt_locals_compilation_unit(level:Nat_big_num.num)(cu:sdt_compilation_unit):string=(letindent=(indent_leveltruelevel)in""^(indent(*^ "name:" *)^(cu.scu_name^("\n"(* ^ indent ^ "cupdie:" ^ pp_cupdie3 cu.scu_cupdie ^ "\n"*)^(indent^("vars:"^(pp_sdt_listcu.scu_vars(pp_sdt_concise_variable_or_formal_parameter(Nat_big_num.addlevel((Nat_big_num.of_int1))))^(indent^("subroutines :"^pp_sdt_listcu.scu_subroutines(pp_sdt_locals_subroutine(Nat_big_num.addlevel((Nat_big_num.of_int1)))))))))))))letpp_sdt_locals_dwarf(sdt_d:sdt_dwarf):string=(letindent_level1=((Nat_big_num.of_int0))inString.concat""(Lem_list.map(pp_sdt_locals_compilation_unitindent_level1)sdt_d.sd_compilation_units))(** ************************************************************ *)(** ** analysis of inlined_subroutine data *)(** ************************************************************ *)(* old version, directly over die tree *)(*
let strict_ais x e s z =
match x with
| Just y -> y
| Nothing ->
Assert_extra.failwith ("analyse_inlined_subroutine strict failure " ^ e ^ " on \n" ^ s z ^ "\n")
end
val analyse_inlined_subroutines : dwarf -> inlined_subroutine_data
let analyse_inlined_subroutines (d: dwarf) : inlined_subroutine_data =
let c = p_context_of_d d in
let s (cu,parents,die) = pp_die c cu.cu_header d.d_str true 0 false die in
let inlined_subroutines : list (compilation_unit * (list die) * die) =
find_dies
(fun die ->
die.die_abbreviation_declaration.ad_tag = tag_encode "DW_TAG_inlined_subroutine")
d in
List.map
(fun (((cu:compilation_unit), (parents: list die), (die: die)) as inlined_subroutine) ->
let ((cu',parents,die') as abstract_origin) : compilation_unit * (list die) * die =
strict_ais (find_reference_attribute_of_die c d cu d.d_str "DW_AT_abstract_origin" die)
"no abstract origin" s inlined_subroutine in
let name : string =
strict_ais (find_name_of_die d.d_str die')
"no abstract origin name" s abstract_origin in
let call_file : unpacked_file_entry =
let file_index = strict_ais (find_natural_attribute_value_of_die c "DW_AT_call_file" die) "no DW_AT_call_file" s inlined_subroutine in
unpack_file_entry (line_number_program_of_compilation_unit d cu).lnp_header file_index in
(* match filename d cu file_index with | Just s -> s | Nothing -> "none" end in*)
let call_line : natural = strict_ais (find_natural_attribute_value_of_die c "DW_AT_call_line" die) "no DW_AT_call_line" s inlined_subroutine in
let pc_ranges : list (natural*natural) =
strict_ais (closest_enclosing_range c d.d_ranges (cu_base_address cu) [die](*deliberately ignore parents*))
"no pc ranges" s inlined_subroutine in
let const_params =
List.mapMaybe (fun die'' ->
if die''.die_abbreviation_declaration.ad_tag = tag_encode "DW_TAG_formal_parameter" then
match find_reference_attribute_of_die c d cu d.d_str "DW_AT_abstract_origin" die'' with
| Nothing -> Nothing
| Just abstract_origin' ->
match find_integer_attribute_value_of_die c "DW_AT_const_value" die'' with
| Nothing -> Nothing
| Just n ->
Just (<|
iscp_abstract_origin = abstract_origin';
iscp_value = n;
|>)
end
end
else
Nothing
) die.die_children in
<|
is_inlined_subroutine = inlined_subroutine;
is_abstract_origin = abstract_origin;
is_name = name;
is_call_file = call_file;
is_call_line = call_line;
is_pc_ranges = pc_ranges;
is_const_params = const_params;
|>
)
inlined_subroutines
*)(* new version, over simple-die-tree view, but still producing the previous old-style datastructure *)letanalyse_inlined_subroutines_sdt_const_param(svfp:sdt_variable_or_formal_parameter):inlined_subroutine_const_paramoption=((match(svfp.svfp_kind,svfp.svfp_abstract_origin,svfp.svfp_const_value)with|(SVPK_param,Somesvfp',Somen)->Some({iscp_abstract_origin=(svfp'.svfp_cupdie);iscp_value=n;})|_->None))letrecanalyse_inlined_subroutines_sdt_subroutine(sdt_parents:sdt_subroutinelist)(ss:sdt_subroutine):inlined_subroutinelist=(letthis:inlined_subroutinelist=((match(ss.ss_kind,ss.ss_abstract_origin)with|(SSK_inlined_subroutine,Somess')->let((call_file:unpacked_file_entry),(call_line:Nat_big_num.num))=((matchss.ss_call_sitewith|Some(((ufe,line,subprogram_name)asud):unpacked_decl)->(ufe,Nat_big_num.of_intline)|None->failwith"analyse_inlined_subroutines_sdt_subroutine found no ss_call_site"))inletpc_ranges=((matchss.ss_pc_rangeswith|Somepc_ranges->pc_ranges|None->failwith"analyse_inlined_subroutines_sdt_subroutine found no ss_pc_ranges"))inletconst_params=(Lem_list.mapMaybeanalyse_inlined_subroutines_sdt_const_paramss.ss_vars)in[({is_inlined_subroutine=(ss.ss_cupdie);is_abstract_origin=(ss'.ss_cupdie);is_inlined_subroutine_sdt=ss;is_inlined_subroutine_sdt_parents=sdt_parents;is_name=((matchss.ss_namewithSomename1->name1|None->"no name"));is_call_file=call_file;is_call_line=call_line;is_pc_ranges=pc_ranges;is_const_params=const_params;})]|(SSK_inlined_subroutine,None)->failwith"analyse_inlined_subroutines_sdt_subroutine found SSK_inlined_subroutine without ss_abstract_origin"|_->[]))inletsdt_parents'=(ss::sdt_parents)inList.rev_append(List.rev(List.rev_append(List.revthis)(List.concat(map(analyse_inlined_subroutines_sdt_subroutinesdt_parents')ss.ss_subroutines))))(List.concat(map(analyse_inlined_subroutines_sdt_lexical_blocksdt_parents')ss.ss_lexical_blocks)))andanalyse_inlined_subroutines_sdt_lexical_blocksdt_parents(lb:sdt_lexical_block):inlined_subroutinelist=(List.rev_append(List.rev(List.concat(map(analyse_inlined_subroutines_sdt_subroutinesdt_parents)lb.slb_subroutines)))(List.concat(map(analyse_inlined_subroutines_sdt_lexical_blocksdt_parents)lb.slb_lexical_blocks)))letanalyse_inlined_subroutines_sdt_compilation_unit(cu:sdt_compilation_unit):inlined_subroutinelist=(List.concat(map(analyse_inlined_subroutines_sdt_subroutine[])cu.scu_subroutines))letanalyse_inlined_subroutines_sdt_dwarf(sd:sdt_dwarf):inlined_subroutinelist=(List.concat(mapanalyse_inlined_subroutines_sdt_compilation_unitsd.sd_compilation_units))letanalyse_inlined_subroutine_by_range(is:inlined_subroutine):inlined_subroutine_data_by_range=(letn_ranges=(List.lengthis.is_pc_ranges)inLem_list.mapi(funi->fun(n1,n2)->((n1,n2),(Nat_big_num.of_inti,Nat_big_num.of_intn_ranges),is))is.is_pc_ranges)letis_ltdict_Basic_classes_Eq_bdict_Basic_classes_Ord_adict_Basic_classes_Ord_b((n1,n2),(m,n),is)((n1',n2'),(m',n'),is'):bool=(dict_Basic_classes_Ord_b.isLess_methodn1n1'||(dict_Basic_classes_Eq_b.isEqual_methodn1n1'&&dict_Basic_classes_Ord_a.isGreater_methodn2n2'))letanalyse_inlined_subroutines_by_range(iss:inlined_subroutine_data):inlined_subroutine_data_by_range=(Lem_sorting.insertSortBy(is_ltinstance_Basic_classes_Eq_Num_natural_dictinstance_Basic_classes_Ord_Num_natural_dictinstance_Basic_classes_Ord_Num_natural_dict)(List.concat(Lem_list.mapanalyse_inlined_subroutine_by_rangeiss)))(* pp the inlined_subroutine tree structure. Technically these die offsets each also need the compilation-unit offset to be globally unique, but that's locally constant *)letrecpp_inlined_subroutine_parents(ds:dielist):string=((matchdswith|[]->""|die1::ds'->ifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_inlined_subroutine")thenpp_posdie1.die_offset^(":"^pp_inlined_subroutine_parentsds')elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_lexical_block")then"<lexical_block>:"^pp_inlined_subroutine_parentsds'elseifNat_big_num.equaldie1.die_abbreviation_declaration.ad_tag(tag_encode"DW_TAG_subprogram")then""else"<surprising ad_tag in "^(pp_posdie1.die_offset^(": "^(pphexdie1.die_abbreviation_declaration.ad_tag^">")))))letpp_inlined_subroutine_headerdsis:string=(is.is_name^(" inlined from "^((subprogram_at_lineds.ds_subprogram_line_extentsis.is_call_fileis.is_call_line)^(":"^(Nat_big_num.to_stringis.is_call_line^(" ("^((pp_ufe_briefis.is_call_file)^(")"^(" "^(let(cu,parents,die1)=(is.is_inlined_subroutine)inpp_inlined_subroutine_parents(die1::parents)))))))))))letpp_inlined_subroutine_const_paramsdis:string=(letc=(p_context_of_dd)in(matchis.is_const_paramswith|[]->""|_->String.concat""(Lem_list.map(funiscp->letfake_als:analysed_location_data=([(iscp.iscp_abstract_origin,None)])inletfake_diff=(pp_analysed_locations3_diffc(*HACK*)dd.d_str[]fake_als)inletconst_in_place_of_locs=(Lem_list.map(fun(removed,(name1,offset,kind),typ,locs,parents)->(removed,(name1,offset,kind),typ,("const="^Nat_big_num.to_stringiscp.iscp_value),parents))fake_diff)inpp_analysed_location_formatconst_in_place_of_locs)is.is_const_params)))letpp_inlined_subroutinedsis:string=(pp_inlined_subroutine_headerdsis^("\n"^(String.concat""(Lem_list.map(fun(n1,n2)->" "^(pphexn1^(" "^(pphexn2^"\n"))))is.is_pc_ranges)^pp_inlined_subroutine_const_paramsds.ds_dwarfis)))letpp_inlined_subroutinesdsiss:string=(String.concat""(Lem_list.map(pp_inlined_subroutineds)iss))letpp_inlined_subroutine_by_rangeds((n1,n2),((m:Nat_big_num.num),(n:Nat_big_num.num)),is):string=(pphexn1^(" "^(pphexn2^(" "^((ifnot(Nat_big_num.equaln((Nat_big_num.of_int1)))then"("^(Nat_big_num.to_stringm^(" of "^(Nat_big_num.to_stringn^") ")))else"")^(pp_inlined_subroutine_headerdsis^("\n"^(ifNat_big_num.equalm((Nat_big_num.of_int0))thenpp_inlined_subroutine_const_paramsds.ds_dwarfiselse""))))))))letpp_inlined_subroutines_by_rangedsiss:string=(String.concat""(Lem_list.map(pp_inlined_subroutine_by_rangeds)iss))(** ************************************************************ *)(** ** pp of text section *)(** ************************************************************ *)(* assume 4-byte ARM instructions *)letrecwords_of_byte_sequence(addr:Nat_big_num.num)(bs:byte_sequence0)(acc:(Nat_big_num.num*Nat_big_num.num)list):(Nat_big_num.num*Nat_big_num.num)list=((matchread_4_bytes_bebswith|Success((b0,b1,b2,b3),bs')->leti:Nat_big_num.num=(Nat_big_num.add(Nat_big_num.add(Nat_big_num.add(natural_of_byteb0)(Nat_big_num.mul((Nat_big_num.of_int256))(natural_of_byteb1)))(Nat_big_num.mul((Nat_big_num.of_int65536))(natural_of_byteb2)))(Nat_big_num.mul(Nat_big_num.mul((Nat_big_num.of_int65536))((Nat_big_num.of_int256)))(natural_of_byteb3)))inwords_of_byte_sequence(Nat_big_num.addaddr((Nat_big_num.of_int4)))bs'((addr,i)::acc)|Fail_->List.revacc))letpp_instruction((addr:Nat_big_num.num),(i:Nat_big_num.num)):string=(Ml_bindings.hex_string_of_big_int_pad8addr^(" "^(Ml_bindings.hex_string_of_big_int_pad8i^"\n")))(*val pp_text_section : elf_file -> string*)letpp_text_sectionf:string=(let(p_context1,addr,bs)=(extract_textf)inletinstructions:(Nat_big_num.num*Nat_big_num.num)list=(words_of_byte_sequenceaddrbs[])inString.concat""(Lem_list.mappp_instructioninstructions))(** ************************************************************ *)(** ** top level for main_elf ******************************** *)(** ************************************************************ *)(*val harness_string_of_elf_like_objdump : elf_file -> byte_sequence -> string*)letharness_string_of_elf_like_objdumpf1bs:string=(letmds=(extract_dwarf_staticf1)in(matchmdswith|None->"<no dwarf information extracted>"|Someds->""(*pp_text_section f1*)^pp_dwarf_like_objdumpds.ds_dwarf))(*val harness_string_of_elf : elf_file -> byte_sequence -> string*)letharness_string_of_elff1bs:string=(letmds=(extract_dwarf_staticf1)in(matchmdswith|None->"<no dwarf information extracted>"|Someds->letsdt_d=(mk_sdt_dwarfds.ds_dwarfds.ds_subprogram_line_extents)in"* emacs outline-mode configuration -*-outline-*- C-c C-{t,a,d,e}"^(""(*pp_text_section f1*)^(pp_dwarfds.ds_dwarf(* ^ analyse_locations_raw c d *)^("************** evaluation of frame data *************************\n"^(pp_evaluated_frame_infods.ds_evaluated_frame_info^("************** analysis of location data *************************\n"^(pp_analysed_location_datads.ds_dwarfds.ds_analysed_location_data^("************** line info *************************\n"^(pp_evaluated_line_infods.ds_evaluated_line_info^("************** inlined subroutine info *************************\n"^(letiss=(analyse_inlined_subroutines_sdt_dwarfsdt_d)inpp_inlined_subroutinesdsiss^("************** inlined subroutine info by range *************************\n"^(pp_inlined_subroutines_by_rangeds(analyse_inlined_subroutines_by_rangeiss)^("************** subprogram line-number extent info *************************\n"^(pp_subprogramsinstance_Show_Show_Num_natural_dictds.ds_subprogram_line_extents^("************** simple die tree *************************\n"^(pp_sdt_dwarfsdt_d^("************** simple die tree globals *************************\n"^(pp_sdt_globals_dwarfsdt_d^("************** simple die tree locals *************************\n"^pp_sdt_locals_dwarfsdt_d)))))))))))))))))))))(*val harness_string_of_elf64_debug_info_section : elf64_file -> byte_sequence -> (*(natural -> string) -> (natural -> string) -> (natural -> string) -> elf64_header -> elf64_section_header_table -> string_table -> *) string*)letharness_string_of_elf64_debug_info_sectionf1bs0:string=((*os proc usr hdr sht stbl*)harness_string_of_elf(ELF_File_64f1)bs0)(*val harness_string_of_elf32_debug_info_section : elf32_file -> byte_sequence -> (* (natural -> string) -> (natural -> string) -> (natural -> string) -> elf32_header -> elf32_section_header_table -> string_table ->*) string*)letharness_string_of_elf32_debug_info_sectionf1bs0:string=((*os proc usr hdr sht stbl*)harness_string_of_elf(ELF_File_32f1)bs0)(*val harness_string_of_elf64_like_objdump : elf64_file -> byte_sequence -> (*(natural -> string) -> (natural -> string) -> (natural -> string) -> elf64_header -> elf64_section_header_table -> string_table -> *) string*)letharness_string_of_elf64_like_objdumpf1bs0:string=((*os proc usr hdr sht stbl*)harness_string_of_elf_like_objdump(ELF_File_64f1)bs0)(*val harness_string_of_elf32_like_objdump : elf32_file -> byte_sequence -> (* (natural -> string) -> (natural -> string) -> (natural -> string) -> elf32_header -> elf32_section_header_table -> string_table ->*) string*)letharness_string_of_elf32_like_objdumpf1bs0:string=((*os proc usr hdr sht stbl*)harness_string_of_elf_like_objdump(ELF_File_32f1)bs0)