MachODump.cpp 340 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446
  1. //===-- MachODump.cpp - Object file dumping utility for llvm --------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the MachO-specific dumper for llvm-objdump.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Object/MachO.h"
  14. #include "llvm-objdump.h"
  15. #include "llvm-c/Disassembler.h"
  16. #include "llvm/ADT/STLExtras.h"
  17. #include "llvm/ADT/StringExtras.h"
  18. #include "llvm/ADT/Triple.h"
  19. #include "llvm/Config/config.h"
  20. #include "llvm/DebugInfo/DIContext.h"
  21. #include "llvm/DebugInfo/DWARF/DWARFContext.h"
  22. #include "llvm/Demangle/Demangle.h"
  23. #include "llvm/MC/MCAsmInfo.h"
  24. #include "llvm/MC/MCContext.h"
  25. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  26. #include "llvm/MC/MCInst.h"
  27. #include "llvm/MC/MCInstPrinter.h"
  28. #include "llvm/MC/MCInstrDesc.h"
  29. #include "llvm/MC/MCInstrInfo.h"
  30. #include "llvm/MC/MCRegisterInfo.h"
  31. #include "llvm/MC/MCSubtargetInfo.h"
  32. #include "llvm/Object/MachOUniversal.h"
  33. #include "llvm/Support/Casting.h"
  34. #include "llvm/Support/CommandLine.h"
  35. #include "llvm/Support/Debug.h"
  36. #include "llvm/Support/Endian.h"
  37. #include "llvm/Support/Format.h"
  38. #include "llvm/Support/FormattedStream.h"
  39. #include "llvm/Support/GraphWriter.h"
  40. #include "llvm/Support/LEB128.h"
  41. #include "llvm/Support/MachO.h"
  42. #include "llvm/Support/MemoryBuffer.h"
  43. #include "llvm/Support/TargetRegistry.h"
  44. #include "llvm/Support/TargetSelect.h"
  45. #include "llvm/Support/ToolOutputFile.h"
  46. #include "llvm/Support/raw_ostream.h"
  47. #include <algorithm>
  48. #include <cstring>
  49. #include <system_error>
  50. #ifdef HAVE_LIBXAR
  51. extern "C" {
  52. #include <xar/xar.h>
  53. }
  54. #endif
  55. using namespace llvm;
  56. using namespace object;
  57. static cl::opt<bool>
  58. UseDbg("g",
  59. cl::desc("Print line information from debug info if available"));
  60. static cl::opt<std::string> DSYMFile("dsym",
  61. cl::desc("Use .dSYM file for debug info"));
  62. static cl::opt<bool> FullLeadingAddr("full-leading-addr",
  63. cl::desc("Print full leading address"));
  64. static cl::opt<bool> NoLeadingAddr("no-leading-addr",
  65. cl::desc("Print no leading address"));
  66. cl::opt<bool> llvm::UniversalHeaders("universal-headers",
  67. cl::desc("Print Mach-O universal headers "
  68. "(requires -macho)"));
  69. cl::opt<bool>
  70. llvm::ArchiveHeaders("archive-headers",
  71. cl::desc("Print archive headers for Mach-O archives "
  72. "(requires -macho)"));
  73. cl::opt<bool>
  74. ArchiveMemberOffsets("archive-member-offsets",
  75. cl::desc("Print the offset to each archive member for "
  76. "Mach-O archives (requires -macho and "
  77. "-archive-headers)"));
  78. cl::opt<bool>
  79. llvm::IndirectSymbols("indirect-symbols",
  80. cl::desc("Print indirect symbol table for Mach-O "
  81. "objects (requires -macho)"));
  82. cl::opt<bool>
  83. llvm::DataInCode("data-in-code",
  84. cl::desc("Print the data in code table for Mach-O objects "
  85. "(requires -macho)"));
  86. cl::opt<bool>
  87. llvm::LinkOptHints("link-opt-hints",
  88. cl::desc("Print the linker optimization hints for "
  89. "Mach-O objects (requires -macho)"));
  90. cl::opt<bool>
  91. llvm::InfoPlist("info-plist",
  92. cl::desc("Print the info plist section as strings for "
  93. "Mach-O objects (requires -macho)"));
  94. cl::opt<bool>
  95. llvm::DylibsUsed("dylibs-used",
  96. cl::desc("Print the shared libraries used for linked "
  97. "Mach-O files (requires -macho)"));
  98. cl::opt<bool>
  99. llvm::DylibId("dylib-id",
  100. cl::desc("Print the shared library's id for the dylib Mach-O "
  101. "file (requires -macho)"));
  102. cl::opt<bool>
  103. llvm::NonVerbose("non-verbose",
  104. cl::desc("Print the info for Mach-O objects in "
  105. "non-verbose or numeric form (requires -macho)"));
  106. cl::opt<bool>
  107. llvm::ObjcMetaData("objc-meta-data",
  108. cl::desc("Print the Objective-C runtime meta data for "
  109. "Mach-O files (requires -macho)"));
  110. cl::opt<std::string> llvm::DisSymName(
  111. "dis-symname",
  112. cl::desc("disassemble just this symbol's instructions (requires -macho)"));
  113. static cl::opt<bool> NoSymbolicOperands(
  114. "no-symbolic-operands",
  115. cl::desc("do not symbolic operands when disassembling (requires -macho)"));
  116. static cl::list<std::string>
  117. ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
  118. cl::ZeroOrMore);
  119. bool ArchAll = false;
  120. static std::string ThumbTripleName;
  121. static const Target *GetTarget(const MachOObjectFile *MachOObj,
  122. const char **McpuDefault,
  123. const Target **ThumbTarget) {
  124. // Figure out the target triple.
  125. llvm::Triple TT(TripleName);
  126. if (TripleName.empty()) {
  127. TT = MachOObj->getArchTriple(McpuDefault);
  128. TripleName = TT.str();
  129. }
  130. if (TT.getArch() == Triple::arm) {
  131. // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
  132. // that support ARM are also capable of Thumb mode.
  133. llvm::Triple ThumbTriple = TT;
  134. std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
  135. ThumbTriple.setArchName(ThumbName);
  136. ThumbTripleName = ThumbTriple.str();
  137. }
  138. // Get the target specific parser.
  139. std::string Error;
  140. const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
  141. if (TheTarget && ThumbTripleName.empty())
  142. return TheTarget;
  143. *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
  144. if (*ThumbTarget)
  145. return TheTarget;
  146. errs() << "llvm-objdump: error: unable to get target for '";
  147. if (!TheTarget)
  148. errs() << TripleName;
  149. else
  150. errs() << ThumbTripleName;
  151. errs() << "', see --version and --triple.\n";
  152. return nullptr;
  153. }
  154. struct SymbolSorter {
  155. bool operator()(const SymbolRef &A, const SymbolRef &B) {
  156. Expected<SymbolRef::Type> ATypeOrErr = A.getType();
  157. if (!ATypeOrErr)
  158. report_error(A.getObject()->getFileName(), ATypeOrErr.takeError());
  159. SymbolRef::Type AType = *ATypeOrErr;
  160. Expected<SymbolRef::Type> BTypeOrErr = B.getType();
  161. if (!BTypeOrErr)
  162. report_error(B.getObject()->getFileName(), BTypeOrErr.takeError());
  163. SymbolRef::Type BType = *BTypeOrErr;
  164. uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
  165. uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
  166. return AAddr < BAddr;
  167. }
  168. };
  169. // Types for the storted data in code table that is built before disassembly
  170. // and the predicate function to sort them.
  171. typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
  172. typedef std::vector<DiceTableEntry> DiceTable;
  173. typedef DiceTable::iterator dice_table_iterator;
  174. // This is used to search for a data in code table entry for the PC being
  175. // disassembled. The j parameter has the PC in j.first. A single data in code
  176. // table entry can cover many bytes for each of its Kind's. So if the offset,
  177. // aka the i.first value, of the data in code table entry plus its Length
  178. // covers the PC being searched for this will return true. If not it will
  179. // return false.
  180. static bool compareDiceTableEntries(const DiceTableEntry &i,
  181. const DiceTableEntry &j) {
  182. uint16_t Length;
  183. i.second.getLength(Length);
  184. return j.first >= i.first && j.first < i.first + Length;
  185. }
  186. static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
  187. unsigned short Kind) {
  188. uint32_t Value, Size = 1;
  189. switch (Kind) {
  190. default:
  191. case MachO::DICE_KIND_DATA:
  192. if (Length >= 4) {
  193. if (!NoShowRawInsn)
  194. dumpBytes(makeArrayRef(bytes, 4), outs());
  195. Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
  196. outs() << "\t.long " << Value;
  197. Size = 4;
  198. } else if (Length >= 2) {
  199. if (!NoShowRawInsn)
  200. dumpBytes(makeArrayRef(bytes, 2), outs());
  201. Value = bytes[1] << 8 | bytes[0];
  202. outs() << "\t.short " << Value;
  203. Size = 2;
  204. } else {
  205. if (!NoShowRawInsn)
  206. dumpBytes(makeArrayRef(bytes, 2), outs());
  207. Value = bytes[0];
  208. outs() << "\t.byte " << Value;
  209. Size = 1;
  210. }
  211. if (Kind == MachO::DICE_KIND_DATA)
  212. outs() << "\t@ KIND_DATA\n";
  213. else
  214. outs() << "\t@ data in code kind = " << Kind << "\n";
  215. break;
  216. case MachO::DICE_KIND_JUMP_TABLE8:
  217. if (!NoShowRawInsn)
  218. dumpBytes(makeArrayRef(bytes, 1), outs());
  219. Value = bytes[0];
  220. outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
  221. Size = 1;
  222. break;
  223. case MachO::DICE_KIND_JUMP_TABLE16:
  224. if (!NoShowRawInsn)
  225. dumpBytes(makeArrayRef(bytes, 2), outs());
  226. Value = bytes[1] << 8 | bytes[0];
  227. outs() << "\t.short " << format("%5u", Value & 0xffff)
  228. << "\t@ KIND_JUMP_TABLE16\n";
  229. Size = 2;
  230. break;
  231. case MachO::DICE_KIND_JUMP_TABLE32:
  232. case MachO::DICE_KIND_ABS_JUMP_TABLE32:
  233. if (!NoShowRawInsn)
  234. dumpBytes(makeArrayRef(bytes, 4), outs());
  235. Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
  236. outs() << "\t.long " << Value;
  237. if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
  238. outs() << "\t@ KIND_JUMP_TABLE32\n";
  239. else
  240. outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
  241. Size = 4;
  242. break;
  243. }
  244. return Size;
  245. }
  246. static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
  247. std::vector<SectionRef> &Sections,
  248. std::vector<SymbolRef> &Symbols,
  249. SmallVectorImpl<uint64_t> &FoundFns,
  250. uint64_t &BaseSegmentAddress) {
  251. for (const SymbolRef &Symbol : MachOObj->symbols()) {
  252. Expected<StringRef> SymName = Symbol.getName();
  253. if (!SymName)
  254. report_error(MachOObj->getFileName(), SymName.takeError());
  255. if (!SymName->startswith("ltmp"))
  256. Symbols.push_back(Symbol);
  257. }
  258. for (const SectionRef &Section : MachOObj->sections()) {
  259. StringRef SectName;
  260. Section.getName(SectName);
  261. Sections.push_back(Section);
  262. }
  263. bool BaseSegmentAddressSet = false;
  264. for (const auto &Command : MachOObj->load_commands()) {
  265. if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
  266. // We found a function starts segment, parse the addresses for later
  267. // consumption.
  268. MachO::linkedit_data_command LLC =
  269. MachOObj->getLinkeditDataLoadCommand(Command);
  270. MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
  271. } else if (Command.C.cmd == MachO::LC_SEGMENT) {
  272. MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
  273. StringRef SegName = SLC.segname;
  274. if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
  275. BaseSegmentAddressSet = true;
  276. BaseSegmentAddress = SLC.vmaddr;
  277. }
  278. }
  279. }
  280. }
  281. static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
  282. uint32_t n, uint32_t count,
  283. uint32_t stride, uint64_t addr) {
  284. MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
  285. uint32_t nindirectsyms = Dysymtab.nindirectsyms;
  286. if (n > nindirectsyms)
  287. outs() << " (entries start past the end of the indirect symbol "
  288. "table) (reserved1 field greater than the table size)";
  289. else if (n + count > nindirectsyms)
  290. outs() << " (entries extends past the end of the indirect symbol "
  291. "table)";
  292. outs() << "\n";
  293. uint32_t cputype = O->getHeader().cputype;
  294. if (cputype & MachO::CPU_ARCH_ABI64)
  295. outs() << "address index";
  296. else
  297. outs() << "address index";
  298. if (verbose)
  299. outs() << " name\n";
  300. else
  301. outs() << "\n";
  302. for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
  303. if (cputype & MachO::CPU_ARCH_ABI64)
  304. outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
  305. else
  306. outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
  307. MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
  308. uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
  309. if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
  310. outs() << "LOCAL\n";
  311. continue;
  312. }
  313. if (indirect_symbol ==
  314. (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
  315. outs() << "LOCAL ABSOLUTE\n";
  316. continue;
  317. }
  318. if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
  319. outs() << "ABSOLUTE\n";
  320. continue;
  321. }
  322. outs() << format("%5u ", indirect_symbol);
  323. if (verbose) {
  324. MachO::symtab_command Symtab = O->getSymtabLoadCommand();
  325. if (indirect_symbol < Symtab.nsyms) {
  326. symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
  327. SymbolRef Symbol = *Sym;
  328. Expected<StringRef> SymName = Symbol.getName();
  329. if (!SymName)
  330. report_error(O->getFileName(), SymName.takeError());
  331. outs() << *SymName;
  332. } else {
  333. outs() << "?";
  334. }
  335. }
  336. outs() << "\n";
  337. }
  338. }
  339. static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
  340. for (const auto &Load : O->load_commands()) {
  341. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  342. MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
  343. for (unsigned J = 0; J < Seg.nsects; ++J) {
  344. MachO::section_64 Sec = O->getSection64(Load, J);
  345. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  346. if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  347. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  348. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  349. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  350. section_type == MachO::S_SYMBOL_STUBS) {
  351. uint32_t stride;
  352. if (section_type == MachO::S_SYMBOL_STUBS)
  353. stride = Sec.reserved2;
  354. else
  355. stride = 8;
  356. if (stride == 0) {
  357. outs() << "Can't print indirect symbols for (" << Sec.segname << ","
  358. << Sec.sectname << ") "
  359. << "(size of stubs in reserved2 field is zero)\n";
  360. continue;
  361. }
  362. uint32_t count = Sec.size / stride;
  363. outs() << "Indirect symbols for (" << Sec.segname << ","
  364. << Sec.sectname << ") " << count << " entries";
  365. uint32_t n = Sec.reserved1;
  366. PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
  367. }
  368. }
  369. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  370. MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
  371. for (unsigned J = 0; J < Seg.nsects; ++J) {
  372. MachO::section Sec = O->getSection(Load, J);
  373. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  374. if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  375. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  376. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  377. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  378. section_type == MachO::S_SYMBOL_STUBS) {
  379. uint32_t stride;
  380. if (section_type == MachO::S_SYMBOL_STUBS)
  381. stride = Sec.reserved2;
  382. else
  383. stride = 4;
  384. if (stride == 0) {
  385. outs() << "Can't print indirect symbols for (" << Sec.segname << ","
  386. << Sec.sectname << ") "
  387. << "(size of stubs in reserved2 field is zero)\n";
  388. continue;
  389. }
  390. uint32_t count = Sec.size / stride;
  391. outs() << "Indirect symbols for (" << Sec.segname << ","
  392. << Sec.sectname << ") " << count << " entries";
  393. uint32_t n = Sec.reserved1;
  394. PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
  395. }
  396. }
  397. }
  398. }
  399. }
  400. static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
  401. MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
  402. uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
  403. outs() << "Data in code table (" << nentries << " entries)\n";
  404. outs() << "offset length kind\n";
  405. for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
  406. ++DI) {
  407. uint32_t Offset;
  408. DI->getOffset(Offset);
  409. outs() << format("0x%08" PRIx32, Offset) << " ";
  410. uint16_t Length;
  411. DI->getLength(Length);
  412. outs() << format("%6u", Length) << " ";
  413. uint16_t Kind;
  414. DI->getKind(Kind);
  415. if (verbose) {
  416. switch (Kind) {
  417. case MachO::DICE_KIND_DATA:
  418. outs() << "DATA";
  419. break;
  420. case MachO::DICE_KIND_JUMP_TABLE8:
  421. outs() << "JUMP_TABLE8";
  422. break;
  423. case MachO::DICE_KIND_JUMP_TABLE16:
  424. outs() << "JUMP_TABLE16";
  425. break;
  426. case MachO::DICE_KIND_JUMP_TABLE32:
  427. outs() << "JUMP_TABLE32";
  428. break;
  429. case MachO::DICE_KIND_ABS_JUMP_TABLE32:
  430. outs() << "ABS_JUMP_TABLE32";
  431. break;
  432. default:
  433. outs() << format("0x%04" PRIx32, Kind);
  434. break;
  435. }
  436. } else
  437. outs() << format("0x%04" PRIx32, Kind);
  438. outs() << "\n";
  439. }
  440. }
  441. static void PrintLinkOptHints(MachOObjectFile *O) {
  442. MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
  443. const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
  444. uint32_t nloh = LohLC.datasize;
  445. outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
  446. for (uint32_t i = 0; i < nloh;) {
  447. unsigned n;
  448. uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
  449. i += n;
  450. outs() << " identifier " << identifier << " ";
  451. if (i >= nloh)
  452. return;
  453. switch (identifier) {
  454. case 1:
  455. outs() << "AdrpAdrp\n";
  456. break;
  457. case 2:
  458. outs() << "AdrpLdr\n";
  459. break;
  460. case 3:
  461. outs() << "AdrpAddLdr\n";
  462. break;
  463. case 4:
  464. outs() << "AdrpLdrGotLdr\n";
  465. break;
  466. case 5:
  467. outs() << "AdrpAddStr\n";
  468. break;
  469. case 6:
  470. outs() << "AdrpLdrGotStr\n";
  471. break;
  472. case 7:
  473. outs() << "AdrpAdd\n";
  474. break;
  475. case 8:
  476. outs() << "AdrpLdrGot\n";
  477. break;
  478. default:
  479. outs() << "Unknown identifier value\n";
  480. break;
  481. }
  482. uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
  483. i += n;
  484. outs() << " narguments " << narguments << "\n";
  485. if (i >= nloh)
  486. return;
  487. for (uint32_t j = 0; j < narguments; j++) {
  488. uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
  489. i += n;
  490. outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
  491. if (i >= nloh)
  492. return;
  493. }
  494. }
  495. }
  496. static void PrintDylibs(MachOObjectFile *O, bool JustId) {
  497. unsigned Index = 0;
  498. for (const auto &Load : O->load_commands()) {
  499. if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
  500. (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
  501. Load.C.cmd == MachO::LC_LOAD_DYLIB ||
  502. Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
  503. Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
  504. Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
  505. Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
  506. MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
  507. if (dl.dylib.name < dl.cmdsize) {
  508. const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
  509. if (JustId)
  510. outs() << p << "\n";
  511. else {
  512. outs() << "\t" << p;
  513. outs() << " (compatibility version "
  514. << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
  515. << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
  516. << (dl.dylib.compatibility_version & 0xff) << ",";
  517. outs() << " current version "
  518. << ((dl.dylib.current_version >> 16) & 0xffff) << "."
  519. << ((dl.dylib.current_version >> 8) & 0xff) << "."
  520. << (dl.dylib.current_version & 0xff) << ")\n";
  521. }
  522. } else {
  523. outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
  524. if (Load.C.cmd == MachO::LC_ID_DYLIB)
  525. outs() << "LC_ID_DYLIB ";
  526. else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
  527. outs() << "LC_LOAD_DYLIB ";
  528. else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
  529. outs() << "LC_LOAD_WEAK_DYLIB ";
  530. else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
  531. outs() << "LC_LAZY_LOAD_DYLIB ";
  532. else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
  533. outs() << "LC_REEXPORT_DYLIB ";
  534. else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
  535. outs() << "LC_LOAD_UPWARD_DYLIB ";
  536. else
  537. outs() << "LC_??? ";
  538. outs() << "command " << Index++ << "\n";
  539. }
  540. }
  541. }
  542. }
  543. typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
  544. static void CreateSymbolAddressMap(MachOObjectFile *O,
  545. SymbolAddressMap *AddrMap) {
  546. // Create a map of symbol addresses to symbol names.
  547. for (const SymbolRef &Symbol : O->symbols()) {
  548. Expected<SymbolRef::Type> STOrErr = Symbol.getType();
  549. if (!STOrErr)
  550. report_error(O->getFileName(), STOrErr.takeError());
  551. SymbolRef::Type ST = *STOrErr;
  552. if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
  553. ST == SymbolRef::ST_Other) {
  554. uint64_t Address = Symbol.getValue();
  555. Expected<StringRef> SymNameOrErr = Symbol.getName();
  556. if (!SymNameOrErr)
  557. report_error(O->getFileName(), SymNameOrErr.takeError());
  558. StringRef SymName = *SymNameOrErr;
  559. if (!SymName.startswith(".objc"))
  560. (*AddrMap)[Address] = SymName;
  561. }
  562. }
  563. }
  564. // GuessSymbolName is passed the address of what might be a symbol and a
  565. // pointer to the SymbolAddressMap. It returns the name of a symbol
  566. // with that address or nullptr if no symbol is found with that address.
  567. static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
  568. const char *SymbolName = nullptr;
  569. // A DenseMap can't lookup up some values.
  570. if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
  571. StringRef name = AddrMap->lookup(value);
  572. if (!name.empty())
  573. SymbolName = name.data();
  574. }
  575. return SymbolName;
  576. }
  577. static void DumpCstringChar(const char c) {
  578. char p[2];
  579. p[0] = c;
  580. p[1] = '\0';
  581. outs().write_escaped(p);
  582. }
  583. static void DumpCstringSection(MachOObjectFile *O, const char *sect,
  584. uint32_t sect_size, uint64_t sect_addr,
  585. bool print_addresses) {
  586. for (uint32_t i = 0; i < sect_size; i++) {
  587. if (print_addresses) {
  588. if (O->is64Bit())
  589. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  590. else
  591. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  592. }
  593. for (; i < sect_size && sect[i] != '\0'; i++)
  594. DumpCstringChar(sect[i]);
  595. if (i < sect_size && sect[i] == '\0')
  596. outs() << "\n";
  597. }
  598. }
  599. static void DumpLiteral4(uint32_t l, float f) {
  600. outs() << format("0x%08" PRIx32, l);
  601. if ((l & 0x7f800000) != 0x7f800000)
  602. outs() << format(" (%.16e)\n", f);
  603. else {
  604. if (l == 0x7f800000)
  605. outs() << " (+Infinity)\n";
  606. else if (l == 0xff800000)
  607. outs() << " (-Infinity)\n";
  608. else if ((l & 0x00400000) == 0x00400000)
  609. outs() << " (non-signaling Not-a-Number)\n";
  610. else
  611. outs() << " (signaling Not-a-Number)\n";
  612. }
  613. }
  614. static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
  615. uint32_t sect_size, uint64_t sect_addr,
  616. bool print_addresses) {
  617. for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
  618. if (print_addresses) {
  619. if (O->is64Bit())
  620. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  621. else
  622. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  623. }
  624. float f;
  625. memcpy(&f, sect + i, sizeof(float));
  626. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  627. sys::swapByteOrder(f);
  628. uint32_t l;
  629. memcpy(&l, sect + i, sizeof(uint32_t));
  630. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  631. sys::swapByteOrder(l);
  632. DumpLiteral4(l, f);
  633. }
  634. }
  635. static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
  636. double d) {
  637. outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
  638. uint32_t Hi, Lo;
  639. Hi = (O->isLittleEndian()) ? l1 : l0;
  640. Lo = (O->isLittleEndian()) ? l0 : l1;
  641. // Hi is the high word, so this is equivalent to if(isfinite(d))
  642. if ((Hi & 0x7ff00000) != 0x7ff00000)
  643. outs() << format(" (%.16e)\n", d);
  644. else {
  645. if (Hi == 0x7ff00000 && Lo == 0)
  646. outs() << " (+Infinity)\n";
  647. else if (Hi == 0xfff00000 && Lo == 0)
  648. outs() << " (-Infinity)\n";
  649. else if ((Hi & 0x00080000) == 0x00080000)
  650. outs() << " (non-signaling Not-a-Number)\n";
  651. else
  652. outs() << " (signaling Not-a-Number)\n";
  653. }
  654. }
  655. static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
  656. uint32_t sect_size, uint64_t sect_addr,
  657. bool print_addresses) {
  658. for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
  659. if (print_addresses) {
  660. if (O->is64Bit())
  661. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  662. else
  663. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  664. }
  665. double d;
  666. memcpy(&d, sect + i, sizeof(double));
  667. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  668. sys::swapByteOrder(d);
  669. uint32_t l0, l1;
  670. memcpy(&l0, sect + i, sizeof(uint32_t));
  671. memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
  672. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  673. sys::swapByteOrder(l0);
  674. sys::swapByteOrder(l1);
  675. }
  676. DumpLiteral8(O, l0, l1, d);
  677. }
  678. }
  679. static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
  680. outs() << format("0x%08" PRIx32, l0) << " ";
  681. outs() << format("0x%08" PRIx32, l1) << " ";
  682. outs() << format("0x%08" PRIx32, l2) << " ";
  683. outs() << format("0x%08" PRIx32, l3) << "\n";
  684. }
  685. static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
  686. uint32_t sect_size, uint64_t sect_addr,
  687. bool print_addresses) {
  688. for (uint32_t i = 0; i < sect_size; i += 16) {
  689. if (print_addresses) {
  690. if (O->is64Bit())
  691. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  692. else
  693. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  694. }
  695. uint32_t l0, l1, l2, l3;
  696. memcpy(&l0, sect + i, sizeof(uint32_t));
  697. memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
  698. memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
  699. memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
  700. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  701. sys::swapByteOrder(l0);
  702. sys::swapByteOrder(l1);
  703. sys::swapByteOrder(l2);
  704. sys::swapByteOrder(l3);
  705. }
  706. DumpLiteral16(l0, l1, l2, l3);
  707. }
  708. }
  709. static void DumpLiteralPointerSection(MachOObjectFile *O,
  710. const SectionRef &Section,
  711. const char *sect, uint32_t sect_size,
  712. uint64_t sect_addr,
  713. bool print_addresses) {
  714. // Collect the literal sections in this Mach-O file.
  715. std::vector<SectionRef> LiteralSections;
  716. for (const SectionRef &Section : O->sections()) {
  717. DataRefImpl Ref = Section.getRawDataRefImpl();
  718. uint32_t section_type;
  719. if (O->is64Bit()) {
  720. const MachO::section_64 Sec = O->getSection64(Ref);
  721. section_type = Sec.flags & MachO::SECTION_TYPE;
  722. } else {
  723. const MachO::section Sec = O->getSection(Ref);
  724. section_type = Sec.flags & MachO::SECTION_TYPE;
  725. }
  726. if (section_type == MachO::S_CSTRING_LITERALS ||
  727. section_type == MachO::S_4BYTE_LITERALS ||
  728. section_type == MachO::S_8BYTE_LITERALS ||
  729. section_type == MachO::S_16BYTE_LITERALS)
  730. LiteralSections.push_back(Section);
  731. }
  732. // Set the size of the literal pointer.
  733. uint32_t lp_size = O->is64Bit() ? 8 : 4;
  734. // Collect the external relocation symbols for the literal pointers.
  735. std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
  736. for (const RelocationRef &Reloc : Section.relocations()) {
  737. DataRefImpl Rel;
  738. MachO::any_relocation_info RE;
  739. bool isExtern = false;
  740. Rel = Reloc.getRawDataRefImpl();
  741. RE = O->getRelocation(Rel);
  742. isExtern = O->getPlainRelocationExternal(RE);
  743. if (isExtern) {
  744. uint64_t RelocOffset = Reloc.getOffset();
  745. symbol_iterator RelocSym = Reloc.getSymbol();
  746. Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
  747. }
  748. }
  749. array_pod_sort(Relocs.begin(), Relocs.end());
  750. // Dump each literal pointer.
  751. for (uint32_t i = 0; i < sect_size; i += lp_size) {
  752. if (print_addresses) {
  753. if (O->is64Bit())
  754. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  755. else
  756. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  757. }
  758. uint64_t lp;
  759. if (O->is64Bit()) {
  760. memcpy(&lp, sect + i, sizeof(uint64_t));
  761. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  762. sys::swapByteOrder(lp);
  763. } else {
  764. uint32_t li;
  765. memcpy(&li, sect + i, sizeof(uint32_t));
  766. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  767. sys::swapByteOrder(li);
  768. lp = li;
  769. }
  770. // First look for an external relocation entry for this literal pointer.
  771. auto Reloc = find_if(Relocs, [&](const std::pair<uint64_t, SymbolRef> &P) {
  772. return P.first == i;
  773. });
  774. if (Reloc != Relocs.end()) {
  775. symbol_iterator RelocSym = Reloc->second;
  776. Expected<StringRef> SymName = RelocSym->getName();
  777. if (!SymName)
  778. report_error(O->getFileName(), SymName.takeError());
  779. outs() << "external relocation entry for symbol:" << *SymName << "\n";
  780. continue;
  781. }
  782. // For local references see what the section the literal pointer points to.
  783. auto Sect = find_if(LiteralSections, [&](const SectionRef &R) {
  784. return lp >= R.getAddress() && lp < R.getAddress() + R.getSize();
  785. });
  786. if (Sect == LiteralSections.end()) {
  787. outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
  788. continue;
  789. }
  790. uint64_t SectAddress = Sect->getAddress();
  791. uint64_t SectSize = Sect->getSize();
  792. StringRef SectName;
  793. Sect->getName(SectName);
  794. DataRefImpl Ref = Sect->getRawDataRefImpl();
  795. StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
  796. outs() << SegmentName << ":" << SectName << ":";
  797. uint32_t section_type;
  798. if (O->is64Bit()) {
  799. const MachO::section_64 Sec = O->getSection64(Ref);
  800. section_type = Sec.flags & MachO::SECTION_TYPE;
  801. } else {
  802. const MachO::section Sec = O->getSection(Ref);
  803. section_type = Sec.flags & MachO::SECTION_TYPE;
  804. }
  805. StringRef BytesStr;
  806. Sect->getContents(BytesStr);
  807. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  808. switch (section_type) {
  809. case MachO::S_CSTRING_LITERALS:
  810. for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
  811. i++) {
  812. DumpCstringChar(Contents[i]);
  813. }
  814. outs() << "\n";
  815. break;
  816. case MachO::S_4BYTE_LITERALS:
  817. float f;
  818. memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
  819. uint32_t l;
  820. memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
  821. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  822. sys::swapByteOrder(f);
  823. sys::swapByteOrder(l);
  824. }
  825. DumpLiteral4(l, f);
  826. break;
  827. case MachO::S_8BYTE_LITERALS: {
  828. double d;
  829. memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
  830. uint32_t l0, l1;
  831. memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
  832. memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
  833. sizeof(uint32_t));
  834. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  835. sys::swapByteOrder(f);
  836. sys::swapByteOrder(l0);
  837. sys::swapByteOrder(l1);
  838. }
  839. DumpLiteral8(O, l0, l1, d);
  840. break;
  841. }
  842. case MachO::S_16BYTE_LITERALS: {
  843. uint32_t l0, l1, l2, l3;
  844. memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
  845. memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
  846. sizeof(uint32_t));
  847. memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
  848. sizeof(uint32_t));
  849. memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
  850. sizeof(uint32_t));
  851. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  852. sys::swapByteOrder(l0);
  853. sys::swapByteOrder(l1);
  854. sys::swapByteOrder(l2);
  855. sys::swapByteOrder(l3);
  856. }
  857. DumpLiteral16(l0, l1, l2, l3);
  858. break;
  859. }
  860. }
  861. }
  862. }
  863. static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
  864. uint32_t sect_size, uint64_t sect_addr,
  865. SymbolAddressMap *AddrMap,
  866. bool verbose) {
  867. uint32_t stride;
  868. stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
  869. for (uint32_t i = 0; i < sect_size; i += stride) {
  870. const char *SymbolName = nullptr;
  871. if (O->is64Bit()) {
  872. outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
  873. uint64_t pointer_value;
  874. memcpy(&pointer_value, sect + i, stride);
  875. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  876. sys::swapByteOrder(pointer_value);
  877. outs() << format("0x%016" PRIx64, pointer_value);
  878. if (verbose)
  879. SymbolName = GuessSymbolName(pointer_value, AddrMap);
  880. } else {
  881. outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
  882. uint32_t pointer_value;
  883. memcpy(&pointer_value, sect + i, stride);
  884. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  885. sys::swapByteOrder(pointer_value);
  886. outs() << format("0x%08" PRIx32, pointer_value);
  887. if (verbose)
  888. SymbolName = GuessSymbolName(pointer_value, AddrMap);
  889. }
  890. if (SymbolName)
  891. outs() << " " << SymbolName;
  892. outs() << "\n";
  893. }
  894. }
  895. static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
  896. uint32_t size, uint64_t addr) {
  897. uint32_t cputype = O->getHeader().cputype;
  898. if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
  899. uint32_t j;
  900. for (uint32_t i = 0; i < size; i += j, addr += j) {
  901. if (O->is64Bit())
  902. outs() << format("%016" PRIx64, addr) << "\t";
  903. else
  904. outs() << format("%08" PRIx64, addr) << "\t";
  905. for (j = 0; j < 16 && i + j < size; j++) {
  906. uint8_t byte_word = *(sect + i + j);
  907. outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
  908. }
  909. outs() << "\n";
  910. }
  911. } else {
  912. uint32_t j;
  913. for (uint32_t i = 0; i < size; i += j, addr += j) {
  914. if (O->is64Bit())
  915. outs() << format("%016" PRIx64, addr) << "\t";
  916. else
  917. outs() << format("%08" PRIx64, addr) << "\t";
  918. for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
  919. j += sizeof(int32_t)) {
  920. if (i + j + sizeof(int32_t) <= size) {
  921. uint32_t long_word;
  922. memcpy(&long_word, sect + i + j, sizeof(int32_t));
  923. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  924. sys::swapByteOrder(long_word);
  925. outs() << format("%08" PRIx32, long_word) << " ";
  926. } else {
  927. for (uint32_t k = 0; i + j + k < size; k++) {
  928. uint8_t byte_word = *(sect + i + j + k);
  929. outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
  930. }
  931. }
  932. }
  933. outs() << "\n";
  934. }
  935. }
  936. }
  937. static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
  938. StringRef DisSegName, StringRef DisSectName);
  939. static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
  940. uint32_t size, uint32_t addr);
  941. #ifdef HAVE_LIBXAR
  942. static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
  943. uint32_t size, bool verbose,
  944. bool PrintXarHeader, bool PrintXarFileHeaders,
  945. std::string XarMemberName);
  946. #endif // defined(HAVE_LIBXAR)
  947. static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
  948. bool verbose) {
  949. SymbolAddressMap AddrMap;
  950. if (verbose)
  951. CreateSymbolAddressMap(O, &AddrMap);
  952. for (unsigned i = 0; i < FilterSections.size(); ++i) {
  953. StringRef DumpSection = FilterSections[i];
  954. std::pair<StringRef, StringRef> DumpSegSectName;
  955. DumpSegSectName = DumpSection.split(',');
  956. StringRef DumpSegName, DumpSectName;
  957. if (DumpSegSectName.second.size()) {
  958. DumpSegName = DumpSegSectName.first;
  959. DumpSectName = DumpSegSectName.second;
  960. } else {
  961. DumpSegName = "";
  962. DumpSectName = DumpSegSectName.first;
  963. }
  964. for (const SectionRef &Section : O->sections()) {
  965. StringRef SectName;
  966. Section.getName(SectName);
  967. DataRefImpl Ref = Section.getRawDataRefImpl();
  968. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  969. if ((DumpSegName.empty() || SegName == DumpSegName) &&
  970. (SectName == DumpSectName)) {
  971. uint32_t section_flags;
  972. if (O->is64Bit()) {
  973. const MachO::section_64 Sec = O->getSection64(Ref);
  974. section_flags = Sec.flags;
  975. } else {
  976. const MachO::section Sec = O->getSection(Ref);
  977. section_flags = Sec.flags;
  978. }
  979. uint32_t section_type = section_flags & MachO::SECTION_TYPE;
  980. StringRef BytesStr;
  981. Section.getContents(BytesStr);
  982. const char *sect = reinterpret_cast<const char *>(BytesStr.data());
  983. uint32_t sect_size = BytesStr.size();
  984. uint64_t sect_addr = Section.getAddress();
  985. outs() << "Contents of (" << SegName << "," << SectName
  986. << ") section\n";
  987. if (verbose) {
  988. if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
  989. (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
  990. DisassembleMachO(Filename, O, SegName, SectName);
  991. continue;
  992. }
  993. if (SegName == "__TEXT" && SectName == "__info_plist") {
  994. outs() << sect;
  995. continue;
  996. }
  997. if (SegName == "__OBJC" && SectName == "__protocol") {
  998. DumpProtocolSection(O, sect, sect_size, sect_addr);
  999. continue;
  1000. }
  1001. #ifdef HAVE_LIBXAR
  1002. if (SegName == "__LLVM" && SectName == "__bundle") {
  1003. DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
  1004. ArchiveHeaders, "");
  1005. continue;
  1006. }
  1007. #endif // defined(HAVE_LIBXAR)
  1008. switch (section_type) {
  1009. case MachO::S_REGULAR:
  1010. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1011. break;
  1012. case MachO::S_ZEROFILL:
  1013. outs() << "zerofill section and has no contents in the file\n";
  1014. break;
  1015. case MachO::S_CSTRING_LITERALS:
  1016. DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1017. break;
  1018. case MachO::S_4BYTE_LITERALS:
  1019. DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1020. break;
  1021. case MachO::S_8BYTE_LITERALS:
  1022. DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1023. break;
  1024. case MachO::S_16BYTE_LITERALS:
  1025. DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1026. break;
  1027. case MachO::S_LITERAL_POINTERS:
  1028. DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
  1029. !NoLeadingAddr);
  1030. break;
  1031. case MachO::S_MOD_INIT_FUNC_POINTERS:
  1032. case MachO::S_MOD_TERM_FUNC_POINTERS:
  1033. DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
  1034. verbose);
  1035. break;
  1036. default:
  1037. outs() << "Unknown section type ("
  1038. << format("0x%08" PRIx32, section_type) << ")\n";
  1039. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1040. break;
  1041. }
  1042. } else {
  1043. if (section_type == MachO::S_ZEROFILL)
  1044. outs() << "zerofill section and has no contents in the file\n";
  1045. else
  1046. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1047. }
  1048. }
  1049. }
  1050. }
  1051. }
  1052. static void DumpInfoPlistSectionContents(StringRef Filename,
  1053. MachOObjectFile *O) {
  1054. for (const SectionRef &Section : O->sections()) {
  1055. StringRef SectName;
  1056. Section.getName(SectName);
  1057. DataRefImpl Ref = Section.getRawDataRefImpl();
  1058. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  1059. if (SegName == "__TEXT" && SectName == "__info_plist") {
  1060. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  1061. StringRef BytesStr;
  1062. Section.getContents(BytesStr);
  1063. const char *sect = reinterpret_cast<const char *>(BytesStr.data());
  1064. outs() << sect;
  1065. return;
  1066. }
  1067. }
  1068. }
  1069. // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
  1070. // and if it is and there is a list of architecture flags is specified then
  1071. // check to make sure this Mach-O file is one of those architectures or all
  1072. // architectures were specified. If not then an error is generated and this
  1073. // routine returns false. Else it returns true.
  1074. static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
  1075. auto *MachO = dyn_cast<MachOObjectFile>(O);
  1076. if (!MachO || ArchAll || ArchFlags.empty())
  1077. return true;
  1078. MachO::mach_header H;
  1079. MachO::mach_header_64 H_64;
  1080. Triple T;
  1081. if (MachO->is64Bit()) {
  1082. H_64 = MachO->MachOObjectFile::getHeader64();
  1083. T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
  1084. } else {
  1085. H = MachO->MachOObjectFile::getHeader();
  1086. T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
  1087. }
  1088. if (none_of(ArchFlags, [&](const std::string &Name) {
  1089. return Name == T.getArchName();
  1090. })) {
  1091. errs() << "llvm-objdump: " + Filename + ": No architecture specified.\n";
  1092. return false;
  1093. }
  1094. return true;
  1095. }
  1096. static void printObjcMetaData(MachOObjectFile *O, bool verbose);
  1097. // ProcessMachO() is passed a single opened Mach-O file, which may be an
  1098. // archive member and or in a slice of a universal file. It prints the
  1099. // the file name and header info and then processes it according to the
  1100. // command line options.
  1101. static void ProcessMachO(StringRef Name, MachOObjectFile *MachOOF,
  1102. StringRef ArchiveMemberName = StringRef(),
  1103. StringRef ArchitectureName = StringRef()) {
  1104. // If we are doing some processing here on the Mach-O file print the header
  1105. // info. And don't print it otherwise like in the case of printing the
  1106. // UniversalHeaders or ArchiveHeaders.
  1107. if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
  1108. LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
  1109. DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
  1110. outs() << Name;
  1111. if (!ArchiveMemberName.empty())
  1112. outs() << '(' << ArchiveMemberName << ')';
  1113. if (!ArchitectureName.empty())
  1114. outs() << " (architecture " << ArchitectureName << ")";
  1115. outs() << ":\n";
  1116. }
  1117. // To use the report_error() form with an ArchiveName and FileName set
  1118. // these up based on what is passed for Name and ArchiveMemberName.
  1119. StringRef ArchiveName;
  1120. StringRef FileName;
  1121. if (!ArchiveMemberName.empty()) {
  1122. ArchiveName = Name;
  1123. FileName = ArchiveMemberName;
  1124. } else {
  1125. ArchiveName = StringRef();
  1126. FileName = Name;
  1127. }
  1128. // If we need the symbol table to do the operation then check it here to
  1129. // produce a good error message as to where the Mach-O file comes from in
  1130. // the error message.
  1131. if (Disassemble || IndirectSymbols || FilterSections.size() != 0 ||
  1132. UnwindInfo)
  1133. if (Error Err = MachOOF->checkSymbolTable())
  1134. report_error(ArchiveName, FileName, std::move(Err), ArchitectureName);
  1135. if (Disassemble)
  1136. DisassembleMachO(FileName, MachOOF, "__TEXT", "__text");
  1137. if (IndirectSymbols)
  1138. PrintIndirectSymbols(MachOOF, !NonVerbose);
  1139. if (DataInCode)
  1140. PrintDataInCodeTable(MachOOF, !NonVerbose);
  1141. if (LinkOptHints)
  1142. PrintLinkOptHints(MachOOF);
  1143. if (Relocations)
  1144. PrintRelocations(MachOOF);
  1145. if (SectionHeaders)
  1146. PrintSectionHeaders(MachOOF);
  1147. if (SectionContents)
  1148. PrintSectionContents(MachOOF);
  1149. if (FilterSections.size() != 0)
  1150. DumpSectionContents(FileName, MachOOF, !NonVerbose);
  1151. if (InfoPlist)
  1152. DumpInfoPlistSectionContents(FileName, MachOOF);
  1153. if (DylibsUsed)
  1154. PrintDylibs(MachOOF, false);
  1155. if (DylibId)
  1156. PrintDylibs(MachOOF, true);
  1157. if (SymbolTable)
  1158. PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
  1159. if (UnwindInfo)
  1160. printMachOUnwindInfo(MachOOF);
  1161. if (PrivateHeaders) {
  1162. printMachOFileHeader(MachOOF);
  1163. printMachOLoadCommands(MachOOF);
  1164. }
  1165. if (FirstPrivateHeader)
  1166. printMachOFileHeader(MachOOF);
  1167. if (ObjcMetaData)
  1168. printObjcMetaData(MachOOF, !NonVerbose);
  1169. if (ExportsTrie)
  1170. printExportsTrie(MachOOF);
  1171. if (Rebase)
  1172. printRebaseTable(MachOOF);
  1173. if (Bind)
  1174. printBindTable(MachOOF);
  1175. if (LazyBind)
  1176. printLazyBindTable(MachOOF);
  1177. if (WeakBind)
  1178. printWeakBindTable(MachOOF);
  1179. if (DwarfDumpType != DIDT_Null) {
  1180. std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF));
  1181. // Dump the complete DWARF structure.
  1182. DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */);
  1183. }
  1184. }
  1185. // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
  1186. static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
  1187. outs() << " cputype (" << cputype << ")\n";
  1188. outs() << " cpusubtype (" << cpusubtype << ")\n";
  1189. }
  1190. // printCPUType() helps print_fat_headers by printing the cputype and
  1191. // pusubtype (symbolically for the one's it knows about).
  1192. static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
  1193. switch (cputype) {
  1194. case MachO::CPU_TYPE_I386:
  1195. switch (cpusubtype) {
  1196. case MachO::CPU_SUBTYPE_I386_ALL:
  1197. outs() << " cputype CPU_TYPE_I386\n";
  1198. outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
  1199. break;
  1200. default:
  1201. printUnknownCPUType(cputype, cpusubtype);
  1202. break;
  1203. }
  1204. break;
  1205. case MachO::CPU_TYPE_X86_64:
  1206. switch (cpusubtype) {
  1207. case MachO::CPU_SUBTYPE_X86_64_ALL:
  1208. outs() << " cputype CPU_TYPE_X86_64\n";
  1209. outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
  1210. break;
  1211. case MachO::CPU_SUBTYPE_X86_64_H:
  1212. outs() << " cputype CPU_TYPE_X86_64\n";
  1213. outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
  1214. break;
  1215. default:
  1216. printUnknownCPUType(cputype, cpusubtype);
  1217. break;
  1218. }
  1219. break;
  1220. case MachO::CPU_TYPE_ARM:
  1221. switch (cpusubtype) {
  1222. case MachO::CPU_SUBTYPE_ARM_ALL:
  1223. outs() << " cputype CPU_TYPE_ARM\n";
  1224. outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
  1225. break;
  1226. case MachO::CPU_SUBTYPE_ARM_V4T:
  1227. outs() << " cputype CPU_TYPE_ARM\n";
  1228. outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
  1229. break;
  1230. case MachO::CPU_SUBTYPE_ARM_V5TEJ:
  1231. outs() << " cputype CPU_TYPE_ARM\n";
  1232. outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
  1233. break;
  1234. case MachO::CPU_SUBTYPE_ARM_XSCALE:
  1235. outs() << " cputype CPU_TYPE_ARM\n";
  1236. outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
  1237. break;
  1238. case MachO::CPU_SUBTYPE_ARM_V6:
  1239. outs() << " cputype CPU_TYPE_ARM\n";
  1240. outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
  1241. break;
  1242. case MachO::CPU_SUBTYPE_ARM_V6M:
  1243. outs() << " cputype CPU_TYPE_ARM\n";
  1244. outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
  1245. break;
  1246. case MachO::CPU_SUBTYPE_ARM_V7:
  1247. outs() << " cputype CPU_TYPE_ARM\n";
  1248. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
  1249. break;
  1250. case MachO::CPU_SUBTYPE_ARM_V7EM:
  1251. outs() << " cputype CPU_TYPE_ARM\n";
  1252. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
  1253. break;
  1254. case MachO::CPU_SUBTYPE_ARM_V7K:
  1255. outs() << " cputype CPU_TYPE_ARM\n";
  1256. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
  1257. break;
  1258. case MachO::CPU_SUBTYPE_ARM_V7M:
  1259. outs() << " cputype CPU_TYPE_ARM\n";
  1260. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
  1261. break;
  1262. case MachO::CPU_SUBTYPE_ARM_V7S:
  1263. outs() << " cputype CPU_TYPE_ARM\n";
  1264. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
  1265. break;
  1266. default:
  1267. printUnknownCPUType(cputype, cpusubtype);
  1268. break;
  1269. }
  1270. break;
  1271. case MachO::CPU_TYPE_ARM64:
  1272. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  1273. case MachO::CPU_SUBTYPE_ARM64_ALL:
  1274. outs() << " cputype CPU_TYPE_ARM64\n";
  1275. outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
  1276. break;
  1277. default:
  1278. printUnknownCPUType(cputype, cpusubtype);
  1279. break;
  1280. }
  1281. break;
  1282. default:
  1283. printUnknownCPUType(cputype, cpusubtype);
  1284. break;
  1285. }
  1286. }
  1287. static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
  1288. bool verbose) {
  1289. outs() << "Fat headers\n";
  1290. if (verbose) {
  1291. if (UB->getMagic() == MachO::FAT_MAGIC)
  1292. outs() << "fat_magic FAT_MAGIC\n";
  1293. else // UB->getMagic() == MachO::FAT_MAGIC_64
  1294. outs() << "fat_magic FAT_MAGIC_64\n";
  1295. } else
  1296. outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
  1297. uint32_t nfat_arch = UB->getNumberOfObjects();
  1298. StringRef Buf = UB->getData();
  1299. uint64_t size = Buf.size();
  1300. uint64_t big_size = sizeof(struct MachO::fat_header) +
  1301. nfat_arch * sizeof(struct MachO::fat_arch);
  1302. outs() << "nfat_arch " << UB->getNumberOfObjects();
  1303. if (nfat_arch == 0)
  1304. outs() << " (malformed, contains zero architecture types)\n";
  1305. else if (big_size > size)
  1306. outs() << " (malformed, architectures past end of file)\n";
  1307. else
  1308. outs() << "\n";
  1309. for (uint32_t i = 0; i < nfat_arch; ++i) {
  1310. MachOUniversalBinary::ObjectForArch OFA(UB, i);
  1311. uint32_t cputype = OFA.getCPUType();
  1312. uint32_t cpusubtype = OFA.getCPUSubType();
  1313. outs() << "architecture ";
  1314. for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
  1315. MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
  1316. uint32_t other_cputype = other_OFA.getCPUType();
  1317. uint32_t other_cpusubtype = other_OFA.getCPUSubType();
  1318. if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
  1319. (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
  1320. (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
  1321. outs() << "(illegal duplicate architecture) ";
  1322. break;
  1323. }
  1324. }
  1325. if (verbose) {
  1326. outs() << OFA.getArchTypeName() << "\n";
  1327. printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  1328. } else {
  1329. outs() << i << "\n";
  1330. outs() << " cputype " << cputype << "\n";
  1331. outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
  1332. << "\n";
  1333. }
  1334. if (verbose &&
  1335. (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
  1336. outs() << " capabilities CPU_SUBTYPE_LIB64\n";
  1337. else
  1338. outs() << " capabilities "
  1339. << format("0x%" PRIx32,
  1340. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
  1341. outs() << " offset " << OFA.getOffset();
  1342. if (OFA.getOffset() > size)
  1343. outs() << " (past end of file)";
  1344. if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
  1345. outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
  1346. outs() << "\n";
  1347. outs() << " size " << OFA.getSize();
  1348. big_size = OFA.getOffset() + OFA.getSize();
  1349. if (big_size > size)
  1350. outs() << " (past end of file)";
  1351. outs() << "\n";
  1352. outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
  1353. << ")\n";
  1354. }
  1355. }
  1356. static void printArchiveChild(StringRef Filename, const Archive::Child &C,
  1357. bool verbose, bool print_offset,
  1358. StringRef ArchitectureName = StringRef()) {
  1359. if (print_offset)
  1360. outs() << C.getChildOffset() << "\t";
  1361. Expected<sys::fs::perms> ModeOrErr = C.getAccessMode();
  1362. if (!ModeOrErr)
  1363. report_error(Filename, C, ModeOrErr.takeError(), ArchitectureName);
  1364. sys::fs::perms Mode = ModeOrErr.get();
  1365. if (verbose) {
  1366. // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
  1367. // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
  1368. outs() << "-";
  1369. outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
  1370. outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
  1371. outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
  1372. outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
  1373. outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
  1374. outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
  1375. outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
  1376. outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
  1377. outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
  1378. } else {
  1379. outs() << format("0%o ", Mode);
  1380. }
  1381. Expected<unsigned> UIDOrErr = C.getUID();
  1382. if (!UIDOrErr)
  1383. report_error(Filename, C, UIDOrErr.takeError(), ArchitectureName);
  1384. unsigned UID = UIDOrErr.get();
  1385. outs() << format("%3d/", UID);
  1386. Expected<unsigned> GIDOrErr = C.getGID();
  1387. if (!GIDOrErr)
  1388. report_error(Filename, C, GIDOrErr.takeError(), ArchitectureName);
  1389. unsigned GID = GIDOrErr.get();
  1390. outs() << format("%-3d ", GID);
  1391. Expected<uint64_t> Size = C.getRawSize();
  1392. if (!Size)
  1393. report_error(Filename, C, Size.takeError(), ArchitectureName);
  1394. outs() << format("%5" PRId64, Size.get()) << " ";
  1395. StringRef RawLastModified = C.getRawLastModified();
  1396. if (verbose) {
  1397. unsigned Seconds;
  1398. if (RawLastModified.getAsInteger(10, Seconds))
  1399. outs() << "(date: \"" << RawLastModified
  1400. << "\" contains non-decimal chars) ";
  1401. else {
  1402. // Since cime(3) returns a 26 character string of the form:
  1403. // "Sun Sep 16 01:03:52 1973\n\0"
  1404. // just print 24 characters.
  1405. time_t t = Seconds;
  1406. outs() << format("%.24s ", ctime(&t));
  1407. }
  1408. } else {
  1409. outs() << RawLastModified << " ";
  1410. }
  1411. if (verbose) {
  1412. Expected<StringRef> NameOrErr = C.getName();
  1413. if (!NameOrErr) {
  1414. consumeError(NameOrErr.takeError());
  1415. Expected<StringRef> NameOrErr = C.getRawName();
  1416. if (!NameOrErr)
  1417. report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
  1418. StringRef RawName = NameOrErr.get();
  1419. outs() << RawName << "\n";
  1420. } else {
  1421. StringRef Name = NameOrErr.get();
  1422. outs() << Name << "\n";
  1423. }
  1424. } else {
  1425. Expected<StringRef> NameOrErr = C.getRawName();
  1426. if (!NameOrErr)
  1427. report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
  1428. StringRef RawName = NameOrErr.get();
  1429. outs() << RawName << "\n";
  1430. }
  1431. }
  1432. static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
  1433. bool print_offset,
  1434. StringRef ArchitectureName = StringRef()) {
  1435. Error Err = Error::success();
  1436. ;
  1437. for (const auto &C : A->children(Err, false))
  1438. printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
  1439. if (Err)
  1440. report_error(StringRef(), Filename, std::move(Err), ArchitectureName);
  1441. }
  1442. // ParseInputMachO() parses the named Mach-O file in Filename and handles the
  1443. // -arch flags selecting just those slices as specified by them and also parses
  1444. // archive files. Then for each individual Mach-O file ProcessMachO() is
  1445. // called to process the file based on the command line options.
  1446. void llvm::ParseInputMachO(StringRef Filename) {
  1447. // Check for -arch all and verifiy the -arch flags are valid.
  1448. for (unsigned i = 0; i < ArchFlags.size(); ++i) {
  1449. if (ArchFlags[i] == "all") {
  1450. ArchAll = true;
  1451. } else {
  1452. if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
  1453. errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
  1454. "'for the -arch option\n";
  1455. return;
  1456. }
  1457. }
  1458. }
  1459. // Attempt to open the binary.
  1460. Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
  1461. if (!BinaryOrErr)
  1462. report_error(Filename, BinaryOrErr.takeError());
  1463. Binary &Bin = *BinaryOrErr.get().getBinary();
  1464. if (Archive *A = dyn_cast<Archive>(&Bin)) {
  1465. outs() << "Archive : " << Filename << "\n";
  1466. if (ArchiveHeaders)
  1467. printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
  1468. Error Err = Error::success();
  1469. for (auto &C : A->children(Err)) {
  1470. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1471. if (!ChildOrErr) {
  1472. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1473. report_error(Filename, C, std::move(E));
  1474. continue;
  1475. }
  1476. if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
  1477. if (!checkMachOAndArchFlags(O, Filename))
  1478. return;
  1479. ProcessMachO(Filename, O, O->getFileName());
  1480. }
  1481. }
  1482. if (Err)
  1483. report_error(Filename, std::move(Err));
  1484. return;
  1485. }
  1486. if (UniversalHeaders) {
  1487. if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
  1488. printMachOUniversalHeaders(UB, !NonVerbose);
  1489. }
  1490. if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
  1491. // If we have a list of architecture flags specified dump only those.
  1492. if (!ArchAll && ArchFlags.size() != 0) {
  1493. // Look for a slice in the universal binary that matches each ArchFlag.
  1494. bool ArchFound;
  1495. for (unsigned i = 0; i < ArchFlags.size(); ++i) {
  1496. ArchFound = false;
  1497. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1498. E = UB->end_objects();
  1499. I != E; ++I) {
  1500. if (ArchFlags[i] == I->getArchTypeName()) {
  1501. ArchFound = true;
  1502. Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
  1503. I->getAsObjectFile();
  1504. std::string ArchitectureName = "";
  1505. if (ArchFlags.size() > 1)
  1506. ArchitectureName = I->getArchTypeName();
  1507. if (ObjOrErr) {
  1508. ObjectFile &O = *ObjOrErr.get();
  1509. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
  1510. ProcessMachO(Filename, MachOOF, "", ArchitectureName);
  1511. } else if (auto E = isNotObjectErrorInvalidFileType(
  1512. ObjOrErr.takeError())) {
  1513. report_error(Filename, StringRef(), std::move(E),
  1514. ArchitectureName);
  1515. continue;
  1516. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1517. I->getAsArchive()) {
  1518. std::unique_ptr<Archive> &A = *AOrErr;
  1519. outs() << "Archive : " << Filename;
  1520. if (!ArchitectureName.empty())
  1521. outs() << " (architecture " << ArchitectureName << ")";
  1522. outs() << "\n";
  1523. if (ArchiveHeaders)
  1524. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1525. ArchiveMemberOffsets, ArchitectureName);
  1526. Error Err = Error::success();
  1527. for (auto &C : A->children(Err)) {
  1528. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1529. if (!ChildOrErr) {
  1530. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1531. report_error(Filename, C, std::move(E), ArchitectureName);
  1532. continue;
  1533. }
  1534. if (MachOObjectFile *O =
  1535. dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
  1536. ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
  1537. }
  1538. if (Err)
  1539. report_error(Filename, std::move(Err));
  1540. } else {
  1541. consumeError(AOrErr.takeError());
  1542. error("Mach-O universal file: " + Filename + " for " +
  1543. "architecture " + StringRef(I->getArchTypeName()) +
  1544. " is not a Mach-O file or an archive file");
  1545. }
  1546. }
  1547. }
  1548. if (!ArchFound) {
  1549. errs() << "llvm-objdump: file: " + Filename + " does not contain "
  1550. << "architecture: " + ArchFlags[i] + "\n";
  1551. return;
  1552. }
  1553. }
  1554. return;
  1555. }
  1556. // No architecture flags were specified so if this contains a slice that
  1557. // matches the host architecture dump only that.
  1558. if (!ArchAll) {
  1559. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1560. E = UB->end_objects();
  1561. I != E; ++I) {
  1562. if (MachOObjectFile::getHostArch().getArchName() ==
  1563. I->getArchTypeName()) {
  1564. Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
  1565. std::string ArchiveName;
  1566. ArchiveName.clear();
  1567. if (ObjOrErr) {
  1568. ObjectFile &O = *ObjOrErr.get();
  1569. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
  1570. ProcessMachO(Filename, MachOOF);
  1571. } else if (auto E = isNotObjectErrorInvalidFileType(
  1572. ObjOrErr.takeError())) {
  1573. report_error(Filename, std::move(E));
  1574. continue;
  1575. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1576. I->getAsArchive()) {
  1577. std::unique_ptr<Archive> &A = *AOrErr;
  1578. outs() << "Archive : " << Filename << "\n";
  1579. if (ArchiveHeaders)
  1580. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1581. ArchiveMemberOffsets);
  1582. Error Err = Error::success();
  1583. for (auto &C : A->children(Err)) {
  1584. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1585. if (!ChildOrErr) {
  1586. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1587. report_error(Filename, C, std::move(E));
  1588. continue;
  1589. }
  1590. if (MachOObjectFile *O =
  1591. dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
  1592. ProcessMachO(Filename, O, O->getFileName());
  1593. }
  1594. if (Err)
  1595. report_error(Filename, std::move(Err));
  1596. } else {
  1597. consumeError(AOrErr.takeError());
  1598. error("Mach-O universal file: " + Filename + " for architecture " +
  1599. StringRef(I->getArchTypeName()) +
  1600. " is not a Mach-O file or an archive file");
  1601. }
  1602. return;
  1603. }
  1604. }
  1605. }
  1606. // Either all architectures have been specified or none have been specified
  1607. // and this does not contain the host architecture so dump all the slices.
  1608. bool moreThanOneArch = UB->getNumberOfObjects() > 1;
  1609. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1610. E = UB->end_objects();
  1611. I != E; ++I) {
  1612. Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
  1613. std::string ArchitectureName = "";
  1614. if (moreThanOneArch)
  1615. ArchitectureName = I->getArchTypeName();
  1616. if (ObjOrErr) {
  1617. ObjectFile &Obj = *ObjOrErr.get();
  1618. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
  1619. ProcessMachO(Filename, MachOOF, "", ArchitectureName);
  1620. } else if (auto E = isNotObjectErrorInvalidFileType(
  1621. ObjOrErr.takeError())) {
  1622. report_error(StringRef(), Filename, std::move(E), ArchitectureName);
  1623. continue;
  1624. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1625. I->getAsArchive()) {
  1626. std::unique_ptr<Archive> &A = *AOrErr;
  1627. outs() << "Archive : " << Filename;
  1628. if (!ArchitectureName.empty())
  1629. outs() << " (architecture " << ArchitectureName << ")";
  1630. outs() << "\n";
  1631. if (ArchiveHeaders)
  1632. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1633. ArchiveMemberOffsets, ArchitectureName);
  1634. Error Err = Error::success();
  1635. for (auto &C : A->children(Err)) {
  1636. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1637. if (!ChildOrErr) {
  1638. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1639. report_error(Filename, C, std::move(E), ArchitectureName);
  1640. continue;
  1641. }
  1642. if (MachOObjectFile *O =
  1643. dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
  1644. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
  1645. ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
  1646. ArchitectureName);
  1647. }
  1648. }
  1649. if (Err)
  1650. report_error(Filename, std::move(Err));
  1651. } else {
  1652. consumeError(AOrErr.takeError());
  1653. error("Mach-O universal file: " + Filename + " for architecture " +
  1654. StringRef(I->getArchTypeName()) +
  1655. " is not a Mach-O file or an archive file");
  1656. }
  1657. }
  1658. return;
  1659. }
  1660. if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
  1661. if (!checkMachOAndArchFlags(O, Filename))
  1662. return;
  1663. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
  1664. ProcessMachO(Filename, MachOOF);
  1665. } else
  1666. errs() << "llvm-objdump: '" << Filename << "': "
  1667. << "Object is not a Mach-O file type.\n";
  1668. return;
  1669. }
  1670. llvm_unreachable("Input object can't be invalid at this point");
  1671. }
  1672. typedef std::pair<uint64_t, const char *> BindInfoEntry;
  1673. typedef std::vector<BindInfoEntry> BindTable;
  1674. typedef BindTable::iterator bind_table_iterator;
  1675. // The block of info used by the Symbolizer call backs.
  1676. struct DisassembleInfo {
  1677. bool verbose;
  1678. MachOObjectFile *O;
  1679. SectionRef S;
  1680. SymbolAddressMap *AddrMap;
  1681. std::vector<SectionRef> *Sections;
  1682. const char *class_name;
  1683. const char *selector_name;
  1684. char *method;
  1685. char *demangled_name;
  1686. uint64_t adrp_addr;
  1687. uint32_t adrp_inst;
  1688. BindTable *bindtable;
  1689. uint32_t depth;
  1690. };
  1691. // SymbolizerGetOpInfo() is the operand information call back function.
  1692. // This is called to get the symbolic information for operand(s) of an
  1693. // instruction when it is being done. This routine does this from
  1694. // the relocation information, symbol table, etc. That block of information
  1695. // is a pointer to the struct DisassembleInfo that was passed when the
  1696. // disassembler context was created and passed to back to here when
  1697. // called back by the disassembler for instruction operands that could have
  1698. // relocation information. The address of the instruction containing operand is
  1699. // at the Pc parameter. The immediate value the operand has is passed in
  1700. // op_info->Value and is at Offset past the start of the instruction and has a
  1701. // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
  1702. // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
  1703. // names and addends of the symbolic expression to add for the operand. The
  1704. // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
  1705. // information is returned then this function returns 1 else it returns 0.
  1706. static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
  1707. uint64_t Size, int TagType, void *TagBuf) {
  1708. struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
  1709. struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
  1710. uint64_t value = op_info->Value;
  1711. // Make sure all fields returned are zero if we don't set them.
  1712. memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
  1713. op_info->Value = value;
  1714. // If the TagType is not the value 1 which it code knows about or if no
  1715. // verbose symbolic information is wanted then just return 0, indicating no
  1716. // information is being returned.
  1717. if (TagType != 1 || !info->verbose)
  1718. return 0;
  1719. unsigned int Arch = info->O->getArch();
  1720. if (Arch == Triple::x86) {
  1721. if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
  1722. return 0;
  1723. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1724. // TODO:
  1725. // Search the external relocation entries of a fully linked image
  1726. // (if any) for an entry that matches this segment offset.
  1727. // uint32_t seg_offset = (Pc + Offset);
  1728. return 0;
  1729. }
  1730. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1731. // for an entry for this section offset.
  1732. uint32_t sect_addr = info->S.getAddress();
  1733. uint32_t sect_offset = (Pc + Offset) - sect_addr;
  1734. bool reloc_found = false;
  1735. DataRefImpl Rel;
  1736. MachO::any_relocation_info RE;
  1737. bool isExtern = false;
  1738. SymbolRef Symbol;
  1739. bool r_scattered = false;
  1740. uint32_t r_value, pair_r_value, r_type;
  1741. for (const RelocationRef &Reloc : info->S.relocations()) {
  1742. uint64_t RelocOffset = Reloc.getOffset();
  1743. if (RelocOffset == sect_offset) {
  1744. Rel = Reloc.getRawDataRefImpl();
  1745. RE = info->O->getRelocation(Rel);
  1746. r_type = info->O->getAnyRelocationType(RE);
  1747. r_scattered = info->O->isRelocationScattered(RE);
  1748. if (r_scattered) {
  1749. r_value = info->O->getScatteredRelocationValue(RE);
  1750. if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
  1751. r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
  1752. DataRefImpl RelNext = Rel;
  1753. info->O->moveRelocationNext(RelNext);
  1754. MachO::any_relocation_info RENext;
  1755. RENext = info->O->getRelocation(RelNext);
  1756. if (info->O->isRelocationScattered(RENext))
  1757. pair_r_value = info->O->getScatteredRelocationValue(RENext);
  1758. else
  1759. return 0;
  1760. }
  1761. } else {
  1762. isExtern = info->O->getPlainRelocationExternal(RE);
  1763. if (isExtern) {
  1764. symbol_iterator RelocSym = Reloc.getSymbol();
  1765. Symbol = *RelocSym;
  1766. }
  1767. }
  1768. reloc_found = true;
  1769. break;
  1770. }
  1771. }
  1772. if (reloc_found && isExtern) {
  1773. Expected<StringRef> SymName = Symbol.getName();
  1774. if (!SymName)
  1775. report_error(info->O->getFileName(), SymName.takeError());
  1776. const char *name = SymName->data();
  1777. op_info->AddSymbol.Present = 1;
  1778. op_info->AddSymbol.Name = name;
  1779. // For i386 extern relocation entries the value in the instruction is
  1780. // the offset from the symbol, and value is already set in op_info->Value.
  1781. return 1;
  1782. }
  1783. if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
  1784. r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
  1785. const char *add = GuessSymbolName(r_value, info->AddrMap);
  1786. const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
  1787. uint32_t offset = value - (r_value - pair_r_value);
  1788. op_info->AddSymbol.Present = 1;
  1789. if (add != nullptr)
  1790. op_info->AddSymbol.Name = add;
  1791. else
  1792. op_info->AddSymbol.Value = r_value;
  1793. op_info->SubtractSymbol.Present = 1;
  1794. if (sub != nullptr)
  1795. op_info->SubtractSymbol.Name = sub;
  1796. else
  1797. op_info->SubtractSymbol.Value = pair_r_value;
  1798. op_info->Value = offset;
  1799. return 1;
  1800. }
  1801. return 0;
  1802. }
  1803. if (Arch == Triple::x86_64) {
  1804. if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
  1805. return 0;
  1806. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1807. // TODO:
  1808. // Search the external relocation entries of a fully linked image
  1809. // (if any) for an entry that matches this segment offset.
  1810. // uint64_t seg_offset = (Pc + Offset);
  1811. return 0;
  1812. }
  1813. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1814. // for an entry for this section offset.
  1815. uint64_t sect_addr = info->S.getAddress();
  1816. uint64_t sect_offset = (Pc + Offset) - sect_addr;
  1817. bool reloc_found = false;
  1818. DataRefImpl Rel;
  1819. MachO::any_relocation_info RE;
  1820. bool isExtern = false;
  1821. SymbolRef Symbol;
  1822. for (const RelocationRef &Reloc : info->S.relocations()) {
  1823. uint64_t RelocOffset = Reloc.getOffset();
  1824. if (RelocOffset == sect_offset) {
  1825. Rel = Reloc.getRawDataRefImpl();
  1826. RE = info->O->getRelocation(Rel);
  1827. // NOTE: Scattered relocations don't exist on x86_64.
  1828. isExtern = info->O->getPlainRelocationExternal(RE);
  1829. if (isExtern) {
  1830. symbol_iterator RelocSym = Reloc.getSymbol();
  1831. Symbol = *RelocSym;
  1832. }
  1833. reloc_found = true;
  1834. break;
  1835. }
  1836. }
  1837. if (reloc_found && isExtern) {
  1838. // The Value passed in will be adjusted by the Pc if the instruction
  1839. // adds the Pc. But for x86_64 external relocation entries the Value
  1840. // is the offset from the external symbol.
  1841. if (info->O->getAnyRelocationPCRel(RE))
  1842. op_info->Value -= Pc + Offset + Size;
  1843. Expected<StringRef> SymName = Symbol.getName();
  1844. if (!SymName)
  1845. report_error(info->O->getFileName(), SymName.takeError());
  1846. const char *name = SymName->data();
  1847. unsigned Type = info->O->getAnyRelocationType(RE);
  1848. if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
  1849. DataRefImpl RelNext = Rel;
  1850. info->O->moveRelocationNext(RelNext);
  1851. MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
  1852. unsigned TypeNext = info->O->getAnyRelocationType(RENext);
  1853. bool isExternNext = info->O->getPlainRelocationExternal(RENext);
  1854. unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
  1855. if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
  1856. op_info->SubtractSymbol.Present = 1;
  1857. op_info->SubtractSymbol.Name = name;
  1858. symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
  1859. Symbol = *RelocSymNext;
  1860. Expected<StringRef> SymNameNext = Symbol.getName();
  1861. if (!SymNameNext)
  1862. report_error(info->O->getFileName(), SymNameNext.takeError());
  1863. name = SymNameNext->data();
  1864. }
  1865. }
  1866. // TODO: add the VariantKinds to op_info->VariantKind for relocation types
  1867. // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
  1868. op_info->AddSymbol.Present = 1;
  1869. op_info->AddSymbol.Name = name;
  1870. return 1;
  1871. }
  1872. return 0;
  1873. }
  1874. if (Arch == Triple::arm) {
  1875. if (Offset != 0 || (Size != 4 && Size != 2))
  1876. return 0;
  1877. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1878. // TODO:
  1879. // Search the external relocation entries of a fully linked image
  1880. // (if any) for an entry that matches this segment offset.
  1881. // uint32_t seg_offset = (Pc + Offset);
  1882. return 0;
  1883. }
  1884. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1885. // for an entry for this section offset.
  1886. uint32_t sect_addr = info->S.getAddress();
  1887. uint32_t sect_offset = (Pc + Offset) - sect_addr;
  1888. DataRefImpl Rel;
  1889. MachO::any_relocation_info RE;
  1890. bool isExtern = false;
  1891. SymbolRef Symbol;
  1892. bool r_scattered = false;
  1893. uint32_t r_value, pair_r_value, r_type, r_length, other_half;
  1894. auto Reloc =
  1895. find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
  1896. uint64_t RelocOffset = Reloc.getOffset();
  1897. return RelocOffset == sect_offset;
  1898. });
  1899. if (Reloc == info->S.relocations().end())
  1900. return 0;
  1901. Rel = Reloc->getRawDataRefImpl();
  1902. RE = info->O->getRelocation(Rel);
  1903. r_length = info->O->getAnyRelocationLength(RE);
  1904. r_scattered = info->O->isRelocationScattered(RE);
  1905. if (r_scattered) {
  1906. r_value = info->O->getScatteredRelocationValue(RE);
  1907. r_type = info->O->getScatteredRelocationType(RE);
  1908. } else {
  1909. r_type = info->O->getAnyRelocationType(RE);
  1910. isExtern = info->O->getPlainRelocationExternal(RE);
  1911. if (isExtern) {
  1912. symbol_iterator RelocSym = Reloc->getSymbol();
  1913. Symbol = *RelocSym;
  1914. }
  1915. }
  1916. if (r_type == MachO::ARM_RELOC_HALF ||
  1917. r_type == MachO::ARM_RELOC_SECTDIFF ||
  1918. r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
  1919. r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  1920. DataRefImpl RelNext = Rel;
  1921. info->O->moveRelocationNext(RelNext);
  1922. MachO::any_relocation_info RENext;
  1923. RENext = info->O->getRelocation(RelNext);
  1924. other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
  1925. if (info->O->isRelocationScattered(RENext))
  1926. pair_r_value = info->O->getScatteredRelocationValue(RENext);
  1927. }
  1928. if (isExtern) {
  1929. Expected<StringRef> SymName = Symbol.getName();
  1930. if (!SymName)
  1931. report_error(info->O->getFileName(), SymName.takeError());
  1932. const char *name = SymName->data();
  1933. op_info->AddSymbol.Present = 1;
  1934. op_info->AddSymbol.Name = name;
  1935. switch (r_type) {
  1936. case MachO::ARM_RELOC_HALF:
  1937. if ((r_length & 0x1) == 1) {
  1938. op_info->Value = value << 16 | other_half;
  1939. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  1940. } else {
  1941. op_info->Value = other_half << 16 | value;
  1942. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  1943. }
  1944. break;
  1945. default:
  1946. break;
  1947. }
  1948. return 1;
  1949. }
  1950. // If we have a branch that is not an external relocation entry then
  1951. // return 0 so the code in tryAddingSymbolicOperand() can use the
  1952. // SymbolLookUp call back with the branch target address to look up the
  1953. // symbol and possibility add an annotation for a symbol stub.
  1954. if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
  1955. r_type == MachO::ARM_THUMB_RELOC_BR22))
  1956. return 0;
  1957. uint32_t offset = 0;
  1958. if (r_type == MachO::ARM_RELOC_HALF ||
  1959. r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  1960. if ((r_length & 0x1) == 1)
  1961. value = value << 16 | other_half;
  1962. else
  1963. value = other_half << 16 | value;
  1964. }
  1965. if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
  1966. r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
  1967. offset = value - r_value;
  1968. value = r_value;
  1969. }
  1970. if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  1971. if ((r_length & 0x1) == 1)
  1972. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  1973. else
  1974. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  1975. const char *add = GuessSymbolName(r_value, info->AddrMap);
  1976. const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
  1977. int32_t offset = value - (r_value - pair_r_value);
  1978. op_info->AddSymbol.Present = 1;
  1979. if (add != nullptr)
  1980. op_info->AddSymbol.Name = add;
  1981. else
  1982. op_info->AddSymbol.Value = r_value;
  1983. op_info->SubtractSymbol.Present = 1;
  1984. if (sub != nullptr)
  1985. op_info->SubtractSymbol.Name = sub;
  1986. else
  1987. op_info->SubtractSymbol.Value = pair_r_value;
  1988. op_info->Value = offset;
  1989. return 1;
  1990. }
  1991. op_info->AddSymbol.Present = 1;
  1992. op_info->Value = offset;
  1993. if (r_type == MachO::ARM_RELOC_HALF) {
  1994. if ((r_length & 0x1) == 1)
  1995. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  1996. else
  1997. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  1998. }
  1999. const char *add = GuessSymbolName(value, info->AddrMap);
  2000. if (add != nullptr) {
  2001. op_info->AddSymbol.Name = add;
  2002. return 1;
  2003. }
  2004. op_info->AddSymbol.Value = value;
  2005. return 1;
  2006. }
  2007. if (Arch == Triple::aarch64) {
  2008. if (Offset != 0 || Size != 4)
  2009. return 0;
  2010. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  2011. // TODO:
  2012. // Search the external relocation entries of a fully linked image
  2013. // (if any) for an entry that matches this segment offset.
  2014. // uint64_t seg_offset = (Pc + Offset);
  2015. return 0;
  2016. }
  2017. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  2018. // for an entry for this section offset.
  2019. uint64_t sect_addr = info->S.getAddress();
  2020. uint64_t sect_offset = (Pc + Offset) - sect_addr;
  2021. auto Reloc =
  2022. find_if(info->S.relocations(), [&](const RelocationRef &Reloc) {
  2023. uint64_t RelocOffset = Reloc.getOffset();
  2024. return RelocOffset == sect_offset;
  2025. });
  2026. if (Reloc == info->S.relocations().end())
  2027. return 0;
  2028. DataRefImpl Rel = Reloc->getRawDataRefImpl();
  2029. MachO::any_relocation_info RE = info->O->getRelocation(Rel);
  2030. uint32_t r_type = info->O->getAnyRelocationType(RE);
  2031. if (r_type == MachO::ARM64_RELOC_ADDEND) {
  2032. DataRefImpl RelNext = Rel;
  2033. info->O->moveRelocationNext(RelNext);
  2034. MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
  2035. if (value == 0) {
  2036. value = info->O->getPlainRelocationSymbolNum(RENext);
  2037. op_info->Value = value;
  2038. }
  2039. }
  2040. // NOTE: Scattered relocations don't exist on arm64.
  2041. if (!info->O->getPlainRelocationExternal(RE))
  2042. return 0;
  2043. Expected<StringRef> SymName = Reloc->getSymbol()->getName();
  2044. if (!SymName)
  2045. report_error(info->O->getFileName(), SymName.takeError());
  2046. const char *name = SymName->data();
  2047. op_info->AddSymbol.Present = 1;
  2048. op_info->AddSymbol.Name = name;
  2049. switch (r_type) {
  2050. case MachO::ARM64_RELOC_PAGE21:
  2051. /* @page */
  2052. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
  2053. break;
  2054. case MachO::ARM64_RELOC_PAGEOFF12:
  2055. /* @pageoff */
  2056. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
  2057. break;
  2058. case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
  2059. /* @gotpage */
  2060. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
  2061. break;
  2062. case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
  2063. /* @gotpageoff */
  2064. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
  2065. break;
  2066. case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
  2067. /* @tvlppage is not implemented in llvm-mc */
  2068. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
  2069. break;
  2070. case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
  2071. /* @tvlppageoff is not implemented in llvm-mc */
  2072. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
  2073. break;
  2074. default:
  2075. case MachO::ARM64_RELOC_BRANCH26:
  2076. op_info->VariantKind = LLVMDisassembler_VariantKind_None;
  2077. break;
  2078. }
  2079. return 1;
  2080. }
  2081. return 0;
  2082. }
  2083. // GuessCstringPointer is passed the address of what might be a pointer to a
  2084. // literal string in a cstring section. If that address is in a cstring section
  2085. // it returns a pointer to that string. Else it returns nullptr.
  2086. static const char *GuessCstringPointer(uint64_t ReferenceValue,
  2087. struct DisassembleInfo *info) {
  2088. for (const auto &Load : info->O->load_commands()) {
  2089. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2090. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2091. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2092. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2093. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2094. if (section_type == MachO::S_CSTRING_LITERALS &&
  2095. ReferenceValue >= Sec.addr &&
  2096. ReferenceValue < Sec.addr + Sec.size) {
  2097. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2098. uint64_t object_offset = Sec.offset + sect_offset;
  2099. StringRef MachOContents = info->O->getData();
  2100. uint64_t object_size = MachOContents.size();
  2101. const char *object_addr = (const char *)MachOContents.data();
  2102. if (object_offset < object_size) {
  2103. const char *name = object_addr + object_offset;
  2104. return name;
  2105. } else {
  2106. return nullptr;
  2107. }
  2108. }
  2109. }
  2110. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  2111. MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
  2112. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2113. MachO::section Sec = info->O->getSection(Load, J);
  2114. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2115. if (section_type == MachO::S_CSTRING_LITERALS &&
  2116. ReferenceValue >= Sec.addr &&
  2117. ReferenceValue < Sec.addr + Sec.size) {
  2118. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2119. uint64_t object_offset = Sec.offset + sect_offset;
  2120. StringRef MachOContents = info->O->getData();
  2121. uint64_t object_size = MachOContents.size();
  2122. const char *object_addr = (const char *)MachOContents.data();
  2123. if (object_offset < object_size) {
  2124. const char *name = object_addr + object_offset;
  2125. return name;
  2126. } else {
  2127. return nullptr;
  2128. }
  2129. }
  2130. }
  2131. }
  2132. }
  2133. return nullptr;
  2134. }
  2135. // GuessIndirectSymbol returns the name of the indirect symbol for the
  2136. // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe
  2137. // an address of a symbol stub or a lazy or non-lazy pointer to associate the
  2138. // symbol name being referenced by the stub or pointer.
  2139. static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
  2140. struct DisassembleInfo *info) {
  2141. MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
  2142. MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
  2143. for (const auto &Load : info->O->load_commands()) {
  2144. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2145. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2146. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2147. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2148. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2149. if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  2150. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  2151. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  2152. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  2153. section_type == MachO::S_SYMBOL_STUBS) &&
  2154. ReferenceValue >= Sec.addr &&
  2155. ReferenceValue < Sec.addr + Sec.size) {
  2156. uint32_t stride;
  2157. if (section_type == MachO::S_SYMBOL_STUBS)
  2158. stride = Sec.reserved2;
  2159. else
  2160. stride = 8;
  2161. if (stride == 0)
  2162. return nullptr;
  2163. uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
  2164. if (index < Dysymtab.nindirectsyms) {
  2165. uint32_t indirect_symbol =
  2166. info->O->getIndirectSymbolTableEntry(Dysymtab, index);
  2167. if (indirect_symbol < Symtab.nsyms) {
  2168. symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
  2169. SymbolRef Symbol = *Sym;
  2170. Expected<StringRef> SymName = Symbol.getName();
  2171. if (!SymName)
  2172. report_error(info->O->getFileName(), SymName.takeError());
  2173. const char *name = SymName->data();
  2174. return name;
  2175. }
  2176. }
  2177. }
  2178. }
  2179. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  2180. MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
  2181. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2182. MachO::section Sec = info->O->getSection(Load, J);
  2183. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2184. if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  2185. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  2186. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  2187. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  2188. section_type == MachO::S_SYMBOL_STUBS) &&
  2189. ReferenceValue >= Sec.addr &&
  2190. ReferenceValue < Sec.addr + Sec.size) {
  2191. uint32_t stride;
  2192. if (section_type == MachO::S_SYMBOL_STUBS)
  2193. stride = Sec.reserved2;
  2194. else
  2195. stride = 4;
  2196. if (stride == 0)
  2197. return nullptr;
  2198. uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
  2199. if (index < Dysymtab.nindirectsyms) {
  2200. uint32_t indirect_symbol =
  2201. info->O->getIndirectSymbolTableEntry(Dysymtab, index);
  2202. if (indirect_symbol < Symtab.nsyms) {
  2203. symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
  2204. SymbolRef Symbol = *Sym;
  2205. Expected<StringRef> SymName = Symbol.getName();
  2206. if (!SymName)
  2207. report_error(info->O->getFileName(), SymName.takeError());
  2208. const char *name = SymName->data();
  2209. return name;
  2210. }
  2211. }
  2212. }
  2213. }
  2214. }
  2215. }
  2216. return nullptr;
  2217. }
  2218. // method_reference() is called passing it the ReferenceName that might be
  2219. // a reference it to an Objective-C method call. If so then it allocates and
  2220. // assembles a method call string with the values last seen and saved in
  2221. // the DisassembleInfo's class_name and selector_name fields. This is saved
  2222. // into the method field of the info and any previous string is free'ed.
  2223. // Then the class_name field in the info is set to nullptr. The method call
  2224. // string is set into ReferenceName and ReferenceType is set to
  2225. // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call
  2226. // then both ReferenceType and ReferenceName are left unchanged.
  2227. static void method_reference(struct DisassembleInfo *info,
  2228. uint64_t *ReferenceType,
  2229. const char **ReferenceName) {
  2230. unsigned int Arch = info->O->getArch();
  2231. if (*ReferenceName != nullptr) {
  2232. if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
  2233. if (info->selector_name != nullptr) {
  2234. if (info->method != nullptr)
  2235. free(info->method);
  2236. if (info->class_name != nullptr) {
  2237. info->method = (char *)malloc(5 + strlen(info->class_name) +
  2238. strlen(info->selector_name));
  2239. if (info->method != nullptr) {
  2240. strcpy(info->method, "+[");
  2241. strcat(info->method, info->class_name);
  2242. strcat(info->method, " ");
  2243. strcat(info->method, info->selector_name);
  2244. strcat(info->method, "]");
  2245. *ReferenceName = info->method;
  2246. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2247. }
  2248. } else {
  2249. info->method = (char *)malloc(9 + strlen(info->selector_name));
  2250. if (info->method != nullptr) {
  2251. if (Arch == Triple::x86_64)
  2252. strcpy(info->method, "-[%rdi ");
  2253. else if (Arch == Triple::aarch64)
  2254. strcpy(info->method, "-[x0 ");
  2255. else
  2256. strcpy(info->method, "-[r? ");
  2257. strcat(info->method, info->selector_name);
  2258. strcat(info->method, "]");
  2259. *ReferenceName = info->method;
  2260. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2261. }
  2262. }
  2263. info->class_name = nullptr;
  2264. }
  2265. } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
  2266. if (info->selector_name != nullptr) {
  2267. if (info->method != nullptr)
  2268. free(info->method);
  2269. info->method = (char *)malloc(17 + strlen(info->selector_name));
  2270. if (info->method != nullptr) {
  2271. if (Arch == Triple::x86_64)
  2272. strcpy(info->method, "-[[%rdi super] ");
  2273. else if (Arch == Triple::aarch64)
  2274. strcpy(info->method, "-[[x0 super] ");
  2275. else
  2276. strcpy(info->method, "-[[r? super] ");
  2277. strcat(info->method, info->selector_name);
  2278. strcat(info->method, "]");
  2279. *ReferenceName = info->method;
  2280. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2281. }
  2282. info->class_name = nullptr;
  2283. }
  2284. }
  2285. }
  2286. }
  2287. // GuessPointerPointer() is passed the address of what might be a pointer to
  2288. // a reference to an Objective-C class, selector, message ref or cfstring.
  2289. // If so the value of the pointer is returned and one of the booleans are set
  2290. // to true. If not zero is returned and all the booleans are set to false.
  2291. static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
  2292. struct DisassembleInfo *info,
  2293. bool &classref, bool &selref, bool &msgref,
  2294. bool &cfstring) {
  2295. classref = false;
  2296. selref = false;
  2297. msgref = false;
  2298. cfstring = false;
  2299. for (const auto &Load : info->O->load_commands()) {
  2300. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2301. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2302. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2303. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2304. if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
  2305. strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
  2306. strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
  2307. strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
  2308. strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
  2309. ReferenceValue >= Sec.addr &&
  2310. ReferenceValue < Sec.addr + Sec.size) {
  2311. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2312. uint64_t object_offset = Sec.offset + sect_offset;
  2313. StringRef MachOContents = info->O->getData();
  2314. uint64_t object_size = MachOContents.size();
  2315. const char *object_addr = (const char *)MachOContents.data();
  2316. if (object_offset < object_size) {
  2317. uint64_t pointer_value;
  2318. memcpy(&pointer_value, object_addr + object_offset,
  2319. sizeof(uint64_t));
  2320. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  2321. sys::swapByteOrder(pointer_value);
  2322. if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
  2323. selref = true;
  2324. else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
  2325. strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
  2326. classref = true;
  2327. else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
  2328. ReferenceValue + 8 < Sec.addr + Sec.size) {
  2329. msgref = true;
  2330. memcpy(&pointer_value, object_addr + object_offset + 8,
  2331. sizeof(uint64_t));
  2332. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  2333. sys::swapByteOrder(pointer_value);
  2334. } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
  2335. cfstring = true;
  2336. return pointer_value;
  2337. } else {
  2338. return 0;
  2339. }
  2340. }
  2341. }
  2342. }
  2343. // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
  2344. }
  2345. return 0;
  2346. }
  2347. // get_pointer_64 returns a pointer to the bytes in the object file at the
  2348. // Address from a section in the Mach-O file. And indirectly returns the
  2349. // offset into the section, number of bytes left in the section past the offset
  2350. // and which section is was being referenced. If the Address is not in a
  2351. // section nullptr is returned.
  2352. static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
  2353. uint32_t &left, SectionRef &S,
  2354. DisassembleInfo *info,
  2355. bool objc_only = false) {
  2356. offset = 0;
  2357. left = 0;
  2358. S = SectionRef();
  2359. for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
  2360. uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
  2361. uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
  2362. if (SectSize == 0)
  2363. continue;
  2364. if (objc_only) {
  2365. StringRef SectName;
  2366. ((*(info->Sections))[SectIdx]).getName(SectName);
  2367. DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
  2368. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  2369. if (SegName != "__OBJC" && SectName != "__cstring")
  2370. continue;
  2371. }
  2372. if (Address >= SectAddress && Address < SectAddress + SectSize) {
  2373. S = (*(info->Sections))[SectIdx];
  2374. offset = Address - SectAddress;
  2375. left = SectSize - offset;
  2376. StringRef SectContents;
  2377. ((*(info->Sections))[SectIdx]).getContents(SectContents);
  2378. return SectContents.data() + offset;
  2379. }
  2380. }
  2381. return nullptr;
  2382. }
  2383. static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
  2384. uint32_t &left, SectionRef &S,
  2385. DisassembleInfo *info,
  2386. bool objc_only = false) {
  2387. return get_pointer_64(Address, offset, left, S, info, objc_only);
  2388. }
  2389. // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
  2390. // the symbol indirectly through n_value. Based on the relocation information
  2391. // for the specified section offset in the specified section reference.
  2392. // If no relocation information is found and a non-zero ReferenceValue for the
  2393. // symbol is passed, look up that address in the info's AddrMap.
  2394. static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
  2395. DisassembleInfo *info, uint64_t &n_value,
  2396. uint64_t ReferenceValue = 0) {
  2397. n_value = 0;
  2398. if (!info->verbose)
  2399. return nullptr;
  2400. // See if there is an external relocation entry at the sect_offset.
  2401. bool reloc_found = false;
  2402. DataRefImpl Rel;
  2403. MachO::any_relocation_info RE;
  2404. bool isExtern = false;
  2405. SymbolRef Symbol;
  2406. for (const RelocationRef &Reloc : S.relocations()) {
  2407. uint64_t RelocOffset = Reloc.getOffset();
  2408. if (RelocOffset == sect_offset) {
  2409. Rel = Reloc.getRawDataRefImpl();
  2410. RE = info->O->getRelocation(Rel);
  2411. if (info->O->isRelocationScattered(RE))
  2412. continue;
  2413. isExtern = info->O->getPlainRelocationExternal(RE);
  2414. if (isExtern) {
  2415. symbol_iterator RelocSym = Reloc.getSymbol();
  2416. Symbol = *RelocSym;
  2417. }
  2418. reloc_found = true;
  2419. break;
  2420. }
  2421. }
  2422. // If there is an external relocation entry for a symbol in this section
  2423. // at this section_offset then use that symbol's value for the n_value
  2424. // and return its name.
  2425. const char *SymbolName = nullptr;
  2426. if (reloc_found && isExtern) {
  2427. n_value = Symbol.getValue();
  2428. Expected<StringRef> NameOrError = Symbol.getName();
  2429. if (!NameOrError)
  2430. report_error(info->O->getFileName(), NameOrError.takeError());
  2431. StringRef Name = *NameOrError;
  2432. if (!Name.empty()) {
  2433. SymbolName = Name.data();
  2434. return SymbolName;
  2435. }
  2436. }
  2437. // TODO: For fully linked images, look through the external relocation
  2438. // entries off the dynamic symtab command. For these the r_offset is from the
  2439. // start of the first writeable segment in the Mach-O file. So the offset
  2440. // to this section from that segment is passed to this routine by the caller,
  2441. // as the database_offset. Which is the difference of the section's starting
  2442. // address and the first writable segment.
  2443. //
  2444. // NOTE: need add passing the database_offset to this routine.
  2445. // We did not find an external relocation entry so look up the ReferenceValue
  2446. // as an address of a symbol and if found return that symbol's name.
  2447. SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
  2448. return SymbolName;
  2449. }
  2450. static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
  2451. DisassembleInfo *info,
  2452. uint32_t ReferenceValue) {
  2453. uint64_t n_value64;
  2454. return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
  2455. }
  2456. // These are structs in the Objective-C meta data and read to produce the
  2457. // comments for disassembly. While these are part of the ABI they are no
  2458. // public defintions. So the are here not in include/llvm/Support/MachO.h .
  2459. // The cfstring object in a 64-bit Mach-O file.
  2460. struct cfstring64_t {
  2461. uint64_t isa; // class64_t * (64-bit pointer)
  2462. uint64_t flags; // flag bits
  2463. uint64_t characters; // char * (64-bit pointer)
  2464. uint64_t length; // number of non-NULL characters in above
  2465. };
  2466. // The class object in a 64-bit Mach-O file.
  2467. struct class64_t {
  2468. uint64_t isa; // class64_t * (64-bit pointer)
  2469. uint64_t superclass; // class64_t * (64-bit pointer)
  2470. uint64_t cache; // Cache (64-bit pointer)
  2471. uint64_t vtable; // IMP * (64-bit pointer)
  2472. uint64_t data; // class_ro64_t * (64-bit pointer)
  2473. };
  2474. struct class32_t {
  2475. uint32_t isa; /* class32_t * (32-bit pointer) */
  2476. uint32_t superclass; /* class32_t * (32-bit pointer) */
  2477. uint32_t cache; /* Cache (32-bit pointer) */
  2478. uint32_t vtable; /* IMP * (32-bit pointer) */
  2479. uint32_t data; /* class_ro32_t * (32-bit pointer) */
  2480. };
  2481. struct class_ro64_t {
  2482. uint32_t flags;
  2483. uint32_t instanceStart;
  2484. uint32_t instanceSize;
  2485. uint32_t reserved;
  2486. uint64_t ivarLayout; // const uint8_t * (64-bit pointer)
  2487. uint64_t name; // const char * (64-bit pointer)
  2488. uint64_t baseMethods; // const method_list_t * (64-bit pointer)
  2489. uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer)
  2490. uint64_t ivars; // const ivar_list_t * (64-bit pointer)
  2491. uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
  2492. uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
  2493. };
  2494. struct class_ro32_t {
  2495. uint32_t flags;
  2496. uint32_t instanceStart;
  2497. uint32_t instanceSize;
  2498. uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
  2499. uint32_t name; /* const char * (32-bit pointer) */
  2500. uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
  2501. uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
  2502. uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
  2503. uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
  2504. uint32_t baseProperties; /* const struct objc_property_list *
  2505. (32-bit pointer) */
  2506. };
  2507. /* Values for class_ro{64,32}_t->flags */
  2508. #define RO_META (1 << 0)
  2509. #define RO_ROOT (1 << 1)
  2510. #define RO_HAS_CXX_STRUCTORS (1 << 2)
  2511. struct method_list64_t {
  2512. uint32_t entsize;
  2513. uint32_t count;
  2514. /* struct method64_t first; These structures follow inline */
  2515. };
  2516. struct method_list32_t {
  2517. uint32_t entsize;
  2518. uint32_t count;
  2519. /* struct method32_t first; These structures follow inline */
  2520. };
  2521. struct method64_t {
  2522. uint64_t name; /* SEL (64-bit pointer) */
  2523. uint64_t types; /* const char * (64-bit pointer) */
  2524. uint64_t imp; /* IMP (64-bit pointer) */
  2525. };
  2526. struct method32_t {
  2527. uint32_t name; /* SEL (32-bit pointer) */
  2528. uint32_t types; /* const char * (32-bit pointer) */
  2529. uint32_t imp; /* IMP (32-bit pointer) */
  2530. };
  2531. struct protocol_list64_t {
  2532. uint64_t count; /* uintptr_t (a 64-bit value) */
  2533. /* struct protocol64_t * list[0]; These pointers follow inline */
  2534. };
  2535. struct protocol_list32_t {
  2536. uint32_t count; /* uintptr_t (a 32-bit value) */
  2537. /* struct protocol32_t * list[0]; These pointers follow inline */
  2538. };
  2539. struct protocol64_t {
  2540. uint64_t isa; /* id * (64-bit pointer) */
  2541. uint64_t name; /* const char * (64-bit pointer) */
  2542. uint64_t protocols; /* struct protocol_list64_t *
  2543. (64-bit pointer) */
  2544. uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
  2545. uint64_t classMethods; /* method_list_t * (64-bit pointer) */
  2546. uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
  2547. uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
  2548. uint64_t instanceProperties; /* struct objc_property_list *
  2549. (64-bit pointer) */
  2550. };
  2551. struct protocol32_t {
  2552. uint32_t isa; /* id * (32-bit pointer) */
  2553. uint32_t name; /* const char * (32-bit pointer) */
  2554. uint32_t protocols; /* struct protocol_list_t *
  2555. (32-bit pointer) */
  2556. uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
  2557. uint32_t classMethods; /* method_list_t * (32-bit pointer) */
  2558. uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
  2559. uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
  2560. uint32_t instanceProperties; /* struct objc_property_list *
  2561. (32-bit pointer) */
  2562. };
  2563. struct ivar_list64_t {
  2564. uint32_t entsize;
  2565. uint32_t count;
  2566. /* struct ivar64_t first; These structures follow inline */
  2567. };
  2568. struct ivar_list32_t {
  2569. uint32_t entsize;
  2570. uint32_t count;
  2571. /* struct ivar32_t first; These structures follow inline */
  2572. };
  2573. struct ivar64_t {
  2574. uint64_t offset; /* uintptr_t * (64-bit pointer) */
  2575. uint64_t name; /* const char * (64-bit pointer) */
  2576. uint64_t type; /* const char * (64-bit pointer) */
  2577. uint32_t alignment;
  2578. uint32_t size;
  2579. };
  2580. struct ivar32_t {
  2581. uint32_t offset; /* uintptr_t * (32-bit pointer) */
  2582. uint32_t name; /* const char * (32-bit pointer) */
  2583. uint32_t type; /* const char * (32-bit pointer) */
  2584. uint32_t alignment;
  2585. uint32_t size;
  2586. };
  2587. struct objc_property_list64 {
  2588. uint32_t entsize;
  2589. uint32_t count;
  2590. /* struct objc_property64 first; These structures follow inline */
  2591. };
  2592. struct objc_property_list32 {
  2593. uint32_t entsize;
  2594. uint32_t count;
  2595. /* struct objc_property32 first; These structures follow inline */
  2596. };
  2597. struct objc_property64 {
  2598. uint64_t name; /* const char * (64-bit pointer) */
  2599. uint64_t attributes; /* const char * (64-bit pointer) */
  2600. };
  2601. struct objc_property32 {
  2602. uint32_t name; /* const char * (32-bit pointer) */
  2603. uint32_t attributes; /* const char * (32-bit pointer) */
  2604. };
  2605. struct category64_t {
  2606. uint64_t name; /* const char * (64-bit pointer) */
  2607. uint64_t cls; /* struct class_t * (64-bit pointer) */
  2608. uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
  2609. uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
  2610. uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
  2611. uint64_t instanceProperties; /* struct objc_property_list *
  2612. (64-bit pointer) */
  2613. };
  2614. struct category32_t {
  2615. uint32_t name; /* const char * (32-bit pointer) */
  2616. uint32_t cls; /* struct class_t * (32-bit pointer) */
  2617. uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
  2618. uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
  2619. uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
  2620. uint32_t instanceProperties; /* struct objc_property_list *
  2621. (32-bit pointer) */
  2622. };
  2623. struct objc_image_info64 {
  2624. uint32_t version;
  2625. uint32_t flags;
  2626. };
  2627. struct objc_image_info32 {
  2628. uint32_t version;
  2629. uint32_t flags;
  2630. };
  2631. struct imageInfo_t {
  2632. uint32_t version;
  2633. uint32_t flags;
  2634. };
  2635. /* masks for objc_image_info.flags */
  2636. #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
  2637. #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
  2638. struct message_ref64 {
  2639. uint64_t imp; /* IMP (64-bit pointer) */
  2640. uint64_t sel; /* SEL (64-bit pointer) */
  2641. };
  2642. struct message_ref32 {
  2643. uint32_t imp; /* IMP (32-bit pointer) */
  2644. uint32_t sel; /* SEL (32-bit pointer) */
  2645. };
  2646. // Objective-C 1 (32-bit only) meta data structs.
  2647. struct objc_module_t {
  2648. uint32_t version;
  2649. uint32_t size;
  2650. uint32_t name; /* char * (32-bit pointer) */
  2651. uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
  2652. };
  2653. struct objc_symtab_t {
  2654. uint32_t sel_ref_cnt;
  2655. uint32_t refs; /* SEL * (32-bit pointer) */
  2656. uint16_t cls_def_cnt;
  2657. uint16_t cat_def_cnt;
  2658. // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
  2659. };
  2660. struct objc_class_t {
  2661. uint32_t isa; /* struct objc_class * (32-bit pointer) */
  2662. uint32_t super_class; /* struct objc_class * (32-bit pointer) */
  2663. uint32_t name; /* const char * (32-bit pointer) */
  2664. int32_t version;
  2665. int32_t info;
  2666. int32_t instance_size;
  2667. uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
  2668. uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
  2669. uint32_t cache; /* struct objc_cache * (32-bit pointer) */
  2670. uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
  2671. };
  2672. #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
  2673. // class is not a metaclass
  2674. #define CLS_CLASS 0x1
  2675. // class is a metaclass
  2676. #define CLS_META 0x2
  2677. struct objc_category_t {
  2678. uint32_t category_name; /* char * (32-bit pointer) */
  2679. uint32_t class_name; /* char * (32-bit pointer) */
  2680. uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
  2681. uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
  2682. uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
  2683. };
  2684. struct objc_ivar_t {
  2685. uint32_t ivar_name; /* char * (32-bit pointer) */
  2686. uint32_t ivar_type; /* char * (32-bit pointer) */
  2687. int32_t ivar_offset;
  2688. };
  2689. struct objc_ivar_list_t {
  2690. int32_t ivar_count;
  2691. // struct objc_ivar_t ivar_list[1]; /* variable length structure */
  2692. };
  2693. struct objc_method_list_t {
  2694. uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
  2695. int32_t method_count;
  2696. // struct objc_method_t method_list[1]; /* variable length structure */
  2697. };
  2698. struct objc_method_t {
  2699. uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
  2700. uint32_t method_types; /* char * (32-bit pointer) */
  2701. uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
  2702. (32-bit pointer) */
  2703. };
  2704. struct objc_protocol_list_t {
  2705. uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
  2706. int32_t count;
  2707. // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
  2708. // (32-bit pointer) */
  2709. };
  2710. struct objc_protocol_t {
  2711. uint32_t isa; /* struct objc_class * (32-bit pointer) */
  2712. uint32_t protocol_name; /* char * (32-bit pointer) */
  2713. uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
  2714. uint32_t instance_methods; /* struct objc_method_description_list *
  2715. (32-bit pointer) */
  2716. uint32_t class_methods; /* struct objc_method_description_list *
  2717. (32-bit pointer) */
  2718. };
  2719. struct objc_method_description_list_t {
  2720. int32_t count;
  2721. // struct objc_method_description_t list[1];
  2722. };
  2723. struct objc_method_description_t {
  2724. uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
  2725. uint32_t types; /* char * (32-bit pointer) */
  2726. };
  2727. inline void swapStruct(struct cfstring64_t &cfs) {
  2728. sys::swapByteOrder(cfs.isa);
  2729. sys::swapByteOrder(cfs.flags);
  2730. sys::swapByteOrder(cfs.characters);
  2731. sys::swapByteOrder(cfs.length);
  2732. }
  2733. inline void swapStruct(struct class64_t &c) {
  2734. sys::swapByteOrder(c.isa);
  2735. sys::swapByteOrder(c.superclass);
  2736. sys::swapByteOrder(c.cache);
  2737. sys::swapByteOrder(c.vtable);
  2738. sys::swapByteOrder(c.data);
  2739. }
  2740. inline void swapStruct(struct class32_t &c) {
  2741. sys::swapByteOrder(c.isa);
  2742. sys::swapByteOrder(c.superclass);
  2743. sys::swapByteOrder(c.cache);
  2744. sys::swapByteOrder(c.vtable);
  2745. sys::swapByteOrder(c.data);
  2746. }
  2747. inline void swapStruct(struct class_ro64_t &cro) {
  2748. sys::swapByteOrder(cro.flags);
  2749. sys::swapByteOrder(cro.instanceStart);
  2750. sys::swapByteOrder(cro.instanceSize);
  2751. sys::swapByteOrder(cro.reserved);
  2752. sys::swapByteOrder(cro.ivarLayout);
  2753. sys::swapByteOrder(cro.name);
  2754. sys::swapByteOrder(cro.baseMethods);
  2755. sys::swapByteOrder(cro.baseProtocols);
  2756. sys::swapByteOrder(cro.ivars);
  2757. sys::swapByteOrder(cro.weakIvarLayout);
  2758. sys::swapByteOrder(cro.baseProperties);
  2759. }
  2760. inline void swapStruct(struct class_ro32_t &cro) {
  2761. sys::swapByteOrder(cro.flags);
  2762. sys::swapByteOrder(cro.instanceStart);
  2763. sys::swapByteOrder(cro.instanceSize);
  2764. sys::swapByteOrder(cro.ivarLayout);
  2765. sys::swapByteOrder(cro.name);
  2766. sys::swapByteOrder(cro.baseMethods);
  2767. sys::swapByteOrder(cro.baseProtocols);
  2768. sys::swapByteOrder(cro.ivars);
  2769. sys::swapByteOrder(cro.weakIvarLayout);
  2770. sys::swapByteOrder(cro.baseProperties);
  2771. }
  2772. inline void swapStruct(struct method_list64_t &ml) {
  2773. sys::swapByteOrder(ml.entsize);
  2774. sys::swapByteOrder(ml.count);
  2775. }
  2776. inline void swapStruct(struct method_list32_t &ml) {
  2777. sys::swapByteOrder(ml.entsize);
  2778. sys::swapByteOrder(ml.count);
  2779. }
  2780. inline void swapStruct(struct method64_t &m) {
  2781. sys::swapByteOrder(m.name);
  2782. sys::swapByteOrder(m.types);
  2783. sys::swapByteOrder(m.imp);
  2784. }
  2785. inline void swapStruct(struct method32_t &m) {
  2786. sys::swapByteOrder(m.name);
  2787. sys::swapByteOrder(m.types);
  2788. sys::swapByteOrder(m.imp);
  2789. }
  2790. inline void swapStruct(struct protocol_list64_t &pl) {
  2791. sys::swapByteOrder(pl.count);
  2792. }
  2793. inline void swapStruct(struct protocol_list32_t &pl) {
  2794. sys::swapByteOrder(pl.count);
  2795. }
  2796. inline void swapStruct(struct protocol64_t &p) {
  2797. sys::swapByteOrder(p.isa);
  2798. sys::swapByteOrder(p.name);
  2799. sys::swapByteOrder(p.protocols);
  2800. sys::swapByteOrder(p.instanceMethods);
  2801. sys::swapByteOrder(p.classMethods);
  2802. sys::swapByteOrder(p.optionalInstanceMethods);
  2803. sys::swapByteOrder(p.optionalClassMethods);
  2804. sys::swapByteOrder(p.instanceProperties);
  2805. }
  2806. inline void swapStruct(struct protocol32_t &p) {
  2807. sys::swapByteOrder(p.isa);
  2808. sys::swapByteOrder(p.name);
  2809. sys::swapByteOrder(p.protocols);
  2810. sys::swapByteOrder(p.instanceMethods);
  2811. sys::swapByteOrder(p.classMethods);
  2812. sys::swapByteOrder(p.optionalInstanceMethods);
  2813. sys::swapByteOrder(p.optionalClassMethods);
  2814. sys::swapByteOrder(p.instanceProperties);
  2815. }
  2816. inline void swapStruct(struct ivar_list64_t &il) {
  2817. sys::swapByteOrder(il.entsize);
  2818. sys::swapByteOrder(il.count);
  2819. }
  2820. inline void swapStruct(struct ivar_list32_t &il) {
  2821. sys::swapByteOrder(il.entsize);
  2822. sys::swapByteOrder(il.count);
  2823. }
  2824. inline void swapStruct(struct ivar64_t &i) {
  2825. sys::swapByteOrder(i.offset);
  2826. sys::swapByteOrder(i.name);
  2827. sys::swapByteOrder(i.type);
  2828. sys::swapByteOrder(i.alignment);
  2829. sys::swapByteOrder(i.size);
  2830. }
  2831. inline void swapStruct(struct ivar32_t &i) {
  2832. sys::swapByteOrder(i.offset);
  2833. sys::swapByteOrder(i.name);
  2834. sys::swapByteOrder(i.type);
  2835. sys::swapByteOrder(i.alignment);
  2836. sys::swapByteOrder(i.size);
  2837. }
  2838. inline void swapStruct(struct objc_property_list64 &pl) {
  2839. sys::swapByteOrder(pl.entsize);
  2840. sys::swapByteOrder(pl.count);
  2841. }
  2842. inline void swapStruct(struct objc_property_list32 &pl) {
  2843. sys::swapByteOrder(pl.entsize);
  2844. sys::swapByteOrder(pl.count);
  2845. }
  2846. inline void swapStruct(struct objc_property64 &op) {
  2847. sys::swapByteOrder(op.name);
  2848. sys::swapByteOrder(op.attributes);
  2849. }
  2850. inline void swapStruct(struct objc_property32 &op) {
  2851. sys::swapByteOrder(op.name);
  2852. sys::swapByteOrder(op.attributes);
  2853. }
  2854. inline void swapStruct(struct category64_t &c) {
  2855. sys::swapByteOrder(c.name);
  2856. sys::swapByteOrder(c.cls);
  2857. sys::swapByteOrder(c.instanceMethods);
  2858. sys::swapByteOrder(c.classMethods);
  2859. sys::swapByteOrder(c.protocols);
  2860. sys::swapByteOrder(c.instanceProperties);
  2861. }
  2862. inline void swapStruct(struct category32_t &c) {
  2863. sys::swapByteOrder(c.name);
  2864. sys::swapByteOrder(c.cls);
  2865. sys::swapByteOrder(c.instanceMethods);
  2866. sys::swapByteOrder(c.classMethods);
  2867. sys::swapByteOrder(c.protocols);
  2868. sys::swapByteOrder(c.instanceProperties);
  2869. }
  2870. inline void swapStruct(struct objc_image_info64 &o) {
  2871. sys::swapByteOrder(o.version);
  2872. sys::swapByteOrder(o.flags);
  2873. }
  2874. inline void swapStruct(struct objc_image_info32 &o) {
  2875. sys::swapByteOrder(o.version);
  2876. sys::swapByteOrder(o.flags);
  2877. }
  2878. inline void swapStruct(struct imageInfo_t &o) {
  2879. sys::swapByteOrder(o.version);
  2880. sys::swapByteOrder(o.flags);
  2881. }
  2882. inline void swapStruct(struct message_ref64 &mr) {
  2883. sys::swapByteOrder(mr.imp);
  2884. sys::swapByteOrder(mr.sel);
  2885. }
  2886. inline void swapStruct(struct message_ref32 &mr) {
  2887. sys::swapByteOrder(mr.imp);
  2888. sys::swapByteOrder(mr.sel);
  2889. }
  2890. inline void swapStruct(struct objc_module_t &module) {
  2891. sys::swapByteOrder(module.version);
  2892. sys::swapByteOrder(module.size);
  2893. sys::swapByteOrder(module.name);
  2894. sys::swapByteOrder(module.symtab);
  2895. }
  2896. inline void swapStruct(struct objc_symtab_t &symtab) {
  2897. sys::swapByteOrder(symtab.sel_ref_cnt);
  2898. sys::swapByteOrder(symtab.refs);
  2899. sys::swapByteOrder(symtab.cls_def_cnt);
  2900. sys::swapByteOrder(symtab.cat_def_cnt);
  2901. }
  2902. inline void swapStruct(struct objc_class_t &objc_class) {
  2903. sys::swapByteOrder(objc_class.isa);
  2904. sys::swapByteOrder(objc_class.super_class);
  2905. sys::swapByteOrder(objc_class.name);
  2906. sys::swapByteOrder(objc_class.version);
  2907. sys::swapByteOrder(objc_class.info);
  2908. sys::swapByteOrder(objc_class.instance_size);
  2909. sys::swapByteOrder(objc_class.ivars);
  2910. sys::swapByteOrder(objc_class.methodLists);
  2911. sys::swapByteOrder(objc_class.cache);
  2912. sys::swapByteOrder(objc_class.protocols);
  2913. }
  2914. inline void swapStruct(struct objc_category_t &objc_category) {
  2915. sys::swapByteOrder(objc_category.category_name);
  2916. sys::swapByteOrder(objc_category.class_name);
  2917. sys::swapByteOrder(objc_category.instance_methods);
  2918. sys::swapByteOrder(objc_category.class_methods);
  2919. sys::swapByteOrder(objc_category.protocols);
  2920. }
  2921. inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
  2922. sys::swapByteOrder(objc_ivar_list.ivar_count);
  2923. }
  2924. inline void swapStruct(struct objc_ivar_t &objc_ivar) {
  2925. sys::swapByteOrder(objc_ivar.ivar_name);
  2926. sys::swapByteOrder(objc_ivar.ivar_type);
  2927. sys::swapByteOrder(objc_ivar.ivar_offset);
  2928. }
  2929. inline void swapStruct(struct objc_method_list_t &method_list) {
  2930. sys::swapByteOrder(method_list.obsolete);
  2931. sys::swapByteOrder(method_list.method_count);
  2932. }
  2933. inline void swapStruct(struct objc_method_t &method) {
  2934. sys::swapByteOrder(method.method_name);
  2935. sys::swapByteOrder(method.method_types);
  2936. sys::swapByteOrder(method.method_imp);
  2937. }
  2938. inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
  2939. sys::swapByteOrder(protocol_list.next);
  2940. sys::swapByteOrder(protocol_list.count);
  2941. }
  2942. inline void swapStruct(struct objc_protocol_t &protocol) {
  2943. sys::swapByteOrder(protocol.isa);
  2944. sys::swapByteOrder(protocol.protocol_name);
  2945. sys::swapByteOrder(protocol.protocol_list);
  2946. sys::swapByteOrder(protocol.instance_methods);
  2947. sys::swapByteOrder(protocol.class_methods);
  2948. }
  2949. inline void swapStruct(struct objc_method_description_list_t &mdl) {
  2950. sys::swapByteOrder(mdl.count);
  2951. }
  2952. inline void swapStruct(struct objc_method_description_t &md) {
  2953. sys::swapByteOrder(md.name);
  2954. sys::swapByteOrder(md.types);
  2955. }
  2956. static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
  2957. struct DisassembleInfo *info);
  2958. // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
  2959. // to an Objective-C class and returns the class name. It is also passed the
  2960. // address of the pointer, so when the pointer is zero as it can be in an .o
  2961. // file, that is used to look for an external relocation entry with a symbol
  2962. // name.
  2963. static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
  2964. uint64_t ReferenceValue,
  2965. struct DisassembleInfo *info) {
  2966. const char *r;
  2967. uint32_t offset, left;
  2968. SectionRef S;
  2969. // The pointer_value can be 0 in an object file and have a relocation
  2970. // entry for the class symbol at the ReferenceValue (the address of the
  2971. // pointer).
  2972. if (pointer_value == 0) {
  2973. r = get_pointer_64(ReferenceValue, offset, left, S, info);
  2974. if (r == nullptr || left < sizeof(uint64_t))
  2975. return nullptr;
  2976. uint64_t n_value;
  2977. const char *symbol_name = get_symbol_64(offset, S, info, n_value);
  2978. if (symbol_name == nullptr)
  2979. return nullptr;
  2980. const char *class_name = strrchr(symbol_name, '$');
  2981. if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
  2982. return class_name + 2;
  2983. else
  2984. return nullptr;
  2985. }
  2986. // The case were the pointer_value is non-zero and points to a class defined
  2987. // in this Mach-O file.
  2988. r = get_pointer_64(pointer_value, offset, left, S, info);
  2989. if (r == nullptr || left < sizeof(struct class64_t))
  2990. return nullptr;
  2991. struct class64_t c;
  2992. memcpy(&c, r, sizeof(struct class64_t));
  2993. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  2994. swapStruct(c);
  2995. if (c.data == 0)
  2996. return nullptr;
  2997. r = get_pointer_64(c.data, offset, left, S, info);
  2998. if (r == nullptr || left < sizeof(struct class_ro64_t))
  2999. return nullptr;
  3000. struct class_ro64_t cro;
  3001. memcpy(&cro, r, sizeof(struct class_ro64_t));
  3002. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3003. swapStruct(cro);
  3004. if (cro.name == 0)
  3005. return nullptr;
  3006. const char *name = get_pointer_64(cro.name, offset, left, S, info);
  3007. return name;
  3008. }
  3009. // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
  3010. // pointer to a cfstring and returns its name or nullptr.
  3011. static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
  3012. struct DisassembleInfo *info) {
  3013. const char *r, *name;
  3014. uint32_t offset, left;
  3015. SectionRef S;
  3016. struct cfstring64_t cfs;
  3017. uint64_t cfs_characters;
  3018. r = get_pointer_64(ReferenceValue, offset, left, S, info);
  3019. if (r == nullptr || left < sizeof(struct cfstring64_t))
  3020. return nullptr;
  3021. memcpy(&cfs, r, sizeof(struct cfstring64_t));
  3022. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3023. swapStruct(cfs);
  3024. if (cfs.characters == 0) {
  3025. uint64_t n_value;
  3026. const char *symbol_name = get_symbol_64(
  3027. offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
  3028. if (symbol_name == nullptr)
  3029. return nullptr;
  3030. cfs_characters = n_value;
  3031. } else
  3032. cfs_characters = cfs.characters;
  3033. name = get_pointer_64(cfs_characters, offset, left, S, info);
  3034. return name;
  3035. }
  3036. // get_objc2_64bit_selref() is used for disassembly and is passed a the address
  3037. // of a pointer to an Objective-C selector reference when the pointer value is
  3038. // zero as in a .o file and is likely to have a external relocation entry with
  3039. // who's symbol's n_value is the real pointer to the selector name. If that is
  3040. // the case the real pointer to the selector name is returned else 0 is
  3041. // returned
  3042. static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
  3043. struct DisassembleInfo *info) {
  3044. uint32_t offset, left;
  3045. SectionRef S;
  3046. const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
  3047. if (r == nullptr || left < sizeof(uint64_t))
  3048. return 0;
  3049. uint64_t n_value;
  3050. const char *symbol_name = get_symbol_64(offset, S, info, n_value);
  3051. if (symbol_name == nullptr)
  3052. return 0;
  3053. return n_value;
  3054. }
  3055. static const SectionRef get_section(MachOObjectFile *O, const char *segname,
  3056. const char *sectname) {
  3057. for (const SectionRef &Section : O->sections()) {
  3058. StringRef SectName;
  3059. Section.getName(SectName);
  3060. DataRefImpl Ref = Section.getRawDataRefImpl();
  3061. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3062. if (SegName == segname && SectName == sectname)
  3063. return Section;
  3064. }
  3065. return SectionRef();
  3066. }
  3067. static void
  3068. walk_pointer_list_64(const char *listname, const SectionRef S,
  3069. MachOObjectFile *O, struct DisassembleInfo *info,
  3070. void (*func)(uint64_t, struct DisassembleInfo *info)) {
  3071. if (S == SectionRef())
  3072. return;
  3073. StringRef SectName;
  3074. S.getName(SectName);
  3075. DataRefImpl Ref = S.getRawDataRefImpl();
  3076. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3077. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  3078. StringRef BytesStr;
  3079. S.getContents(BytesStr);
  3080. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  3081. for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
  3082. uint32_t left = S.getSize() - i;
  3083. uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
  3084. uint64_t p = 0;
  3085. memcpy(&p, Contents + i, size);
  3086. if (i + sizeof(uint64_t) > S.getSize())
  3087. outs() << listname << " list pointer extends past end of (" << SegName
  3088. << "," << SectName << ") section\n";
  3089. outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
  3090. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  3091. sys::swapByteOrder(p);
  3092. uint64_t n_value = 0;
  3093. const char *name = get_symbol_64(i, S, info, n_value, p);
  3094. if (name == nullptr)
  3095. name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
  3096. if (n_value != 0) {
  3097. outs() << format("0x%" PRIx64, n_value);
  3098. if (p != 0)
  3099. outs() << " + " << format("0x%" PRIx64, p);
  3100. } else
  3101. outs() << format("0x%" PRIx64, p);
  3102. if (name != nullptr)
  3103. outs() << " " << name;
  3104. outs() << "\n";
  3105. p += n_value;
  3106. if (func)
  3107. func(p, info);
  3108. }
  3109. }
  3110. static void
  3111. walk_pointer_list_32(const char *listname, const SectionRef S,
  3112. MachOObjectFile *O, struct DisassembleInfo *info,
  3113. void (*func)(uint32_t, struct DisassembleInfo *info)) {
  3114. if (S == SectionRef())
  3115. return;
  3116. StringRef SectName;
  3117. S.getName(SectName);
  3118. DataRefImpl Ref = S.getRawDataRefImpl();
  3119. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3120. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  3121. StringRef BytesStr;
  3122. S.getContents(BytesStr);
  3123. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  3124. for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
  3125. uint32_t left = S.getSize() - i;
  3126. uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
  3127. uint32_t p = 0;
  3128. memcpy(&p, Contents + i, size);
  3129. if (i + sizeof(uint32_t) > S.getSize())
  3130. outs() << listname << " list pointer extends past end of (" << SegName
  3131. << "," << SectName << ") section\n";
  3132. uint32_t Address = S.getAddress() + i;
  3133. outs() << format("%08" PRIx32, Address) << " ";
  3134. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  3135. sys::swapByteOrder(p);
  3136. outs() << format("0x%" PRIx32, p);
  3137. const char *name = get_symbol_32(i, S, info, p);
  3138. if (name != nullptr)
  3139. outs() << " " << name;
  3140. outs() << "\n";
  3141. if (func)
  3142. func(p, info);
  3143. }
  3144. }
  3145. static void print_layout_map(const char *layout_map, uint32_t left) {
  3146. if (layout_map == nullptr)
  3147. return;
  3148. outs() << " layout map: ";
  3149. do {
  3150. outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
  3151. left--;
  3152. layout_map++;
  3153. } while (*layout_map != '\0' && left != 0);
  3154. outs() << "\n";
  3155. }
  3156. static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
  3157. uint32_t offset, left;
  3158. SectionRef S;
  3159. const char *layout_map;
  3160. if (p == 0)
  3161. return;
  3162. layout_map = get_pointer_64(p, offset, left, S, info);
  3163. print_layout_map(layout_map, left);
  3164. }
  3165. static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
  3166. uint32_t offset, left;
  3167. SectionRef S;
  3168. const char *layout_map;
  3169. if (p == 0)
  3170. return;
  3171. layout_map = get_pointer_32(p, offset, left, S, info);
  3172. print_layout_map(layout_map, left);
  3173. }
  3174. static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
  3175. const char *indent) {
  3176. struct method_list64_t ml;
  3177. struct method64_t m;
  3178. const char *r;
  3179. uint32_t offset, xoffset, left, i;
  3180. SectionRef S, xS;
  3181. const char *name, *sym_name;
  3182. uint64_t n_value;
  3183. r = get_pointer_64(p, offset, left, S, info);
  3184. if (r == nullptr)
  3185. return;
  3186. memset(&ml, '\0', sizeof(struct method_list64_t));
  3187. if (left < sizeof(struct method_list64_t)) {
  3188. memcpy(&ml, r, left);
  3189. outs() << " (method_list_t entends past the end of the section)\n";
  3190. } else
  3191. memcpy(&ml, r, sizeof(struct method_list64_t));
  3192. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3193. swapStruct(ml);
  3194. outs() << indent << "\t\t entsize " << ml.entsize << "\n";
  3195. outs() << indent << "\t\t count " << ml.count << "\n";
  3196. p += sizeof(struct method_list64_t);
  3197. offset += sizeof(struct method_list64_t);
  3198. for (i = 0; i < ml.count; i++) {
  3199. r = get_pointer_64(p, offset, left, S, info);
  3200. if (r == nullptr)
  3201. return;
  3202. memset(&m, '\0', sizeof(struct method64_t));
  3203. if (left < sizeof(struct method64_t)) {
  3204. memcpy(&m, r, left);
  3205. outs() << indent << " (method_t extends past the end of the section)\n";
  3206. } else
  3207. memcpy(&m, r, sizeof(struct method64_t));
  3208. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3209. swapStruct(m);
  3210. outs() << indent << "\t\t name ";
  3211. sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
  3212. info, n_value, m.name);
  3213. if (n_value != 0) {
  3214. if (info->verbose && sym_name != nullptr)
  3215. outs() << sym_name;
  3216. else
  3217. outs() << format("0x%" PRIx64, n_value);
  3218. if (m.name != 0)
  3219. outs() << " + " << format("0x%" PRIx64, m.name);
  3220. } else
  3221. outs() << format("0x%" PRIx64, m.name);
  3222. name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
  3223. if (name != nullptr)
  3224. outs() << format(" %.*s", left, name);
  3225. outs() << "\n";
  3226. outs() << indent << "\t\t types ";
  3227. sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
  3228. info, n_value, m.types);
  3229. if (n_value != 0) {
  3230. if (info->verbose && sym_name != nullptr)
  3231. outs() << sym_name;
  3232. else
  3233. outs() << format("0x%" PRIx64, n_value);
  3234. if (m.types != 0)
  3235. outs() << " + " << format("0x%" PRIx64, m.types);
  3236. } else
  3237. outs() << format("0x%" PRIx64, m.types);
  3238. name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
  3239. if (name != nullptr)
  3240. outs() << format(" %.*s", left, name);
  3241. outs() << "\n";
  3242. outs() << indent << "\t\t imp ";
  3243. name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
  3244. n_value, m.imp);
  3245. if (info->verbose && name == nullptr) {
  3246. if (n_value != 0) {
  3247. outs() << format("0x%" PRIx64, n_value) << " ";
  3248. if (m.imp != 0)
  3249. outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
  3250. } else
  3251. outs() << format("0x%" PRIx64, m.imp) << " ";
  3252. }
  3253. if (name != nullptr)
  3254. outs() << name;
  3255. outs() << "\n";
  3256. p += sizeof(struct method64_t);
  3257. offset += sizeof(struct method64_t);
  3258. }
  3259. }
  3260. static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
  3261. const char *indent) {
  3262. struct method_list32_t ml;
  3263. struct method32_t m;
  3264. const char *r, *name;
  3265. uint32_t offset, xoffset, left, i;
  3266. SectionRef S, xS;
  3267. r = get_pointer_32(p, offset, left, S, info);
  3268. if (r == nullptr)
  3269. return;
  3270. memset(&ml, '\0', sizeof(struct method_list32_t));
  3271. if (left < sizeof(struct method_list32_t)) {
  3272. memcpy(&ml, r, left);
  3273. outs() << " (method_list_t entends past the end of the section)\n";
  3274. } else
  3275. memcpy(&ml, r, sizeof(struct method_list32_t));
  3276. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3277. swapStruct(ml);
  3278. outs() << indent << "\t\t entsize " << ml.entsize << "\n";
  3279. outs() << indent << "\t\t count " << ml.count << "\n";
  3280. p += sizeof(struct method_list32_t);
  3281. offset += sizeof(struct method_list32_t);
  3282. for (i = 0; i < ml.count; i++) {
  3283. r = get_pointer_32(p, offset, left, S, info);
  3284. if (r == nullptr)
  3285. return;
  3286. memset(&m, '\0', sizeof(struct method32_t));
  3287. if (left < sizeof(struct method32_t)) {
  3288. memcpy(&ml, r, left);
  3289. outs() << indent << " (method_t entends past the end of the section)\n";
  3290. } else
  3291. memcpy(&m, r, sizeof(struct method32_t));
  3292. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3293. swapStruct(m);
  3294. outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name);
  3295. name = get_pointer_32(m.name, xoffset, left, xS, info);
  3296. if (name != nullptr)
  3297. outs() << format(" %.*s", left, name);
  3298. outs() << "\n";
  3299. outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types);
  3300. name = get_pointer_32(m.types, xoffset, left, xS, info);
  3301. if (name != nullptr)
  3302. outs() << format(" %.*s", left, name);
  3303. outs() << "\n";
  3304. outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp);
  3305. name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
  3306. m.imp);
  3307. if (name != nullptr)
  3308. outs() << " " << name;
  3309. outs() << "\n";
  3310. p += sizeof(struct method32_t);
  3311. offset += sizeof(struct method32_t);
  3312. }
  3313. }
  3314. static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
  3315. uint32_t offset, left, xleft;
  3316. SectionRef S;
  3317. struct objc_method_list_t method_list;
  3318. struct objc_method_t method;
  3319. const char *r, *methods, *name, *SymbolName;
  3320. int32_t i;
  3321. r = get_pointer_32(p, offset, left, S, info, true);
  3322. if (r == nullptr)
  3323. return true;
  3324. outs() << "\n";
  3325. if (left > sizeof(struct objc_method_list_t)) {
  3326. memcpy(&method_list, r, sizeof(struct objc_method_list_t));
  3327. } else {
  3328. outs() << "\t\t objc_method_list extends past end of the section\n";
  3329. memset(&method_list, '\0', sizeof(struct objc_method_list_t));
  3330. memcpy(&method_list, r, left);
  3331. }
  3332. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3333. swapStruct(method_list);
  3334. outs() << "\t\t obsolete "
  3335. << format("0x%08" PRIx32, method_list.obsolete) << "\n";
  3336. outs() << "\t\t method_count " << method_list.method_count << "\n";
  3337. methods = r + sizeof(struct objc_method_list_t);
  3338. for (i = 0; i < method_list.method_count; i++) {
  3339. if ((i + 1) * sizeof(struct objc_method_t) > left) {
  3340. outs() << "\t\t remaining method's extend past the of the section\n";
  3341. break;
  3342. }
  3343. memcpy(&method, methods + i * sizeof(struct objc_method_t),
  3344. sizeof(struct objc_method_t));
  3345. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3346. swapStruct(method);
  3347. outs() << "\t\t method_name "
  3348. << format("0x%08" PRIx32, method.method_name);
  3349. if (info->verbose) {
  3350. name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
  3351. if (name != nullptr)
  3352. outs() << format(" %.*s", xleft, name);
  3353. else
  3354. outs() << " (not in an __OBJC section)";
  3355. }
  3356. outs() << "\n";
  3357. outs() << "\t\t method_types "
  3358. << format("0x%08" PRIx32, method.method_types);
  3359. if (info->verbose) {
  3360. name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
  3361. if (name != nullptr)
  3362. outs() << format(" %.*s", xleft, name);
  3363. else
  3364. outs() << " (not in an __OBJC section)";
  3365. }
  3366. outs() << "\n";
  3367. outs() << "\t\t method_imp "
  3368. << format("0x%08" PRIx32, method.method_imp) << " ";
  3369. if (info->verbose) {
  3370. SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
  3371. if (SymbolName != nullptr)
  3372. outs() << SymbolName;
  3373. }
  3374. outs() << "\n";
  3375. }
  3376. return false;
  3377. }
  3378. static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
  3379. struct protocol_list64_t pl;
  3380. uint64_t q, n_value;
  3381. struct protocol64_t pc;
  3382. const char *r;
  3383. uint32_t offset, xoffset, left, i;
  3384. SectionRef S, xS;
  3385. const char *name, *sym_name;
  3386. r = get_pointer_64(p, offset, left, S, info);
  3387. if (r == nullptr)
  3388. return;
  3389. memset(&pl, '\0', sizeof(struct protocol_list64_t));
  3390. if (left < sizeof(struct protocol_list64_t)) {
  3391. memcpy(&pl, r, left);
  3392. outs() << " (protocol_list_t entends past the end of the section)\n";
  3393. } else
  3394. memcpy(&pl, r, sizeof(struct protocol_list64_t));
  3395. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3396. swapStruct(pl);
  3397. outs() << " count " << pl.count << "\n";
  3398. p += sizeof(struct protocol_list64_t);
  3399. offset += sizeof(struct protocol_list64_t);
  3400. for (i = 0; i < pl.count; i++) {
  3401. r = get_pointer_64(p, offset, left, S, info);
  3402. if (r == nullptr)
  3403. return;
  3404. q = 0;
  3405. if (left < sizeof(uint64_t)) {
  3406. memcpy(&q, r, left);
  3407. outs() << " (protocol_t * entends past the end of the section)\n";
  3408. } else
  3409. memcpy(&q, r, sizeof(uint64_t));
  3410. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3411. sys::swapByteOrder(q);
  3412. outs() << "\t\t list[" << i << "] ";
  3413. sym_name = get_symbol_64(offset, S, info, n_value, q);
  3414. if (n_value != 0) {
  3415. if (info->verbose && sym_name != nullptr)
  3416. outs() << sym_name;
  3417. else
  3418. outs() << format("0x%" PRIx64, n_value);
  3419. if (q != 0)
  3420. outs() << " + " << format("0x%" PRIx64, q);
  3421. } else
  3422. outs() << format("0x%" PRIx64, q);
  3423. outs() << " (struct protocol_t *)\n";
  3424. r = get_pointer_64(q + n_value, offset, left, S, info);
  3425. if (r == nullptr)
  3426. return;
  3427. memset(&pc, '\0', sizeof(struct protocol64_t));
  3428. if (left < sizeof(struct protocol64_t)) {
  3429. memcpy(&pc, r, left);
  3430. outs() << " (protocol_t entends past the end of the section)\n";
  3431. } else
  3432. memcpy(&pc, r, sizeof(struct protocol64_t));
  3433. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3434. swapStruct(pc);
  3435. outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n";
  3436. outs() << "\t\t\t name ";
  3437. sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
  3438. info, n_value, pc.name);
  3439. if (n_value != 0) {
  3440. if (info->verbose && sym_name != nullptr)
  3441. outs() << sym_name;
  3442. else
  3443. outs() << format("0x%" PRIx64, n_value);
  3444. if (pc.name != 0)
  3445. outs() << " + " << format("0x%" PRIx64, pc.name);
  3446. } else
  3447. outs() << format("0x%" PRIx64, pc.name);
  3448. name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
  3449. if (name != nullptr)
  3450. outs() << format(" %.*s", left, name);
  3451. outs() << "\n";
  3452. outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
  3453. outs() << "\t\t instanceMethods ";
  3454. sym_name =
  3455. get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
  3456. S, info, n_value, pc.instanceMethods);
  3457. if (n_value != 0) {
  3458. if (info->verbose && sym_name != nullptr)
  3459. outs() << sym_name;
  3460. else
  3461. outs() << format("0x%" PRIx64, n_value);
  3462. if (pc.instanceMethods != 0)
  3463. outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
  3464. } else
  3465. outs() << format("0x%" PRIx64, pc.instanceMethods);
  3466. outs() << " (struct method_list_t *)\n";
  3467. if (pc.instanceMethods + n_value != 0)
  3468. print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
  3469. outs() << "\t\t classMethods ";
  3470. sym_name =
  3471. get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
  3472. info, n_value, pc.classMethods);
  3473. if (n_value != 0) {
  3474. if (info->verbose && sym_name != nullptr)
  3475. outs() << sym_name;
  3476. else
  3477. outs() << format("0x%" PRIx64, n_value);
  3478. if (pc.classMethods != 0)
  3479. outs() << " + " << format("0x%" PRIx64, pc.classMethods);
  3480. } else
  3481. outs() << format("0x%" PRIx64, pc.classMethods);
  3482. outs() << " (struct method_list_t *)\n";
  3483. if (pc.classMethods + n_value != 0)
  3484. print_method_list64_t(pc.classMethods + n_value, info, "\t");
  3485. outs() << "\t optionalInstanceMethods "
  3486. << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
  3487. outs() << "\t optionalClassMethods "
  3488. << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
  3489. outs() << "\t instanceProperties "
  3490. << format("0x%" PRIx64, pc.instanceProperties) << "\n";
  3491. p += sizeof(uint64_t);
  3492. offset += sizeof(uint64_t);
  3493. }
  3494. }
  3495. static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
  3496. struct protocol_list32_t pl;
  3497. uint32_t q;
  3498. struct protocol32_t pc;
  3499. const char *r;
  3500. uint32_t offset, xoffset, left, i;
  3501. SectionRef S, xS;
  3502. const char *name;
  3503. r = get_pointer_32(p, offset, left, S, info);
  3504. if (r == nullptr)
  3505. return;
  3506. memset(&pl, '\0', sizeof(struct protocol_list32_t));
  3507. if (left < sizeof(struct protocol_list32_t)) {
  3508. memcpy(&pl, r, left);
  3509. outs() << " (protocol_list_t entends past the end of the section)\n";
  3510. } else
  3511. memcpy(&pl, r, sizeof(struct protocol_list32_t));
  3512. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3513. swapStruct(pl);
  3514. outs() << " count " << pl.count << "\n";
  3515. p += sizeof(struct protocol_list32_t);
  3516. offset += sizeof(struct protocol_list32_t);
  3517. for (i = 0; i < pl.count; i++) {
  3518. r = get_pointer_32(p, offset, left, S, info);
  3519. if (r == nullptr)
  3520. return;
  3521. q = 0;
  3522. if (left < sizeof(uint32_t)) {
  3523. memcpy(&q, r, left);
  3524. outs() << " (protocol_t * entends past the end of the section)\n";
  3525. } else
  3526. memcpy(&q, r, sizeof(uint32_t));
  3527. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3528. sys::swapByteOrder(q);
  3529. outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q)
  3530. << " (struct protocol_t *)\n";
  3531. r = get_pointer_32(q, offset, left, S, info);
  3532. if (r == nullptr)
  3533. return;
  3534. memset(&pc, '\0', sizeof(struct protocol32_t));
  3535. if (left < sizeof(struct protocol32_t)) {
  3536. memcpy(&pc, r, left);
  3537. outs() << " (protocol_t entends past the end of the section)\n";
  3538. } else
  3539. memcpy(&pc, r, sizeof(struct protocol32_t));
  3540. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3541. swapStruct(pc);
  3542. outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n";
  3543. outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name);
  3544. name = get_pointer_32(pc.name, xoffset, left, xS, info);
  3545. if (name != nullptr)
  3546. outs() << format(" %.*s", left, name);
  3547. outs() << "\n";
  3548. outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
  3549. outs() << "\t\t instanceMethods "
  3550. << format("0x%" PRIx32, pc.instanceMethods)
  3551. << " (struct method_list_t *)\n";
  3552. if (pc.instanceMethods != 0)
  3553. print_method_list32_t(pc.instanceMethods, info, "\t");
  3554. outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods)
  3555. << " (struct method_list_t *)\n";
  3556. if (pc.classMethods != 0)
  3557. print_method_list32_t(pc.classMethods, info, "\t");
  3558. outs() << "\t optionalInstanceMethods "
  3559. << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
  3560. outs() << "\t optionalClassMethods "
  3561. << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
  3562. outs() << "\t instanceProperties "
  3563. << format("0x%" PRIx32, pc.instanceProperties) << "\n";
  3564. p += sizeof(uint32_t);
  3565. offset += sizeof(uint32_t);
  3566. }
  3567. }
  3568. static void print_indent(uint32_t indent) {
  3569. for (uint32_t i = 0; i < indent;) {
  3570. if (indent - i >= 8) {
  3571. outs() << "\t";
  3572. i += 8;
  3573. } else {
  3574. for (uint32_t j = i; j < indent; j++)
  3575. outs() << " ";
  3576. return;
  3577. }
  3578. }
  3579. }
  3580. static bool print_method_description_list(uint32_t p, uint32_t indent,
  3581. struct DisassembleInfo *info) {
  3582. uint32_t offset, left, xleft;
  3583. SectionRef S;
  3584. struct objc_method_description_list_t mdl;
  3585. struct objc_method_description_t md;
  3586. const char *r, *list, *name;
  3587. int32_t i;
  3588. r = get_pointer_32(p, offset, left, S, info, true);
  3589. if (r == nullptr)
  3590. return true;
  3591. outs() << "\n";
  3592. if (left > sizeof(struct objc_method_description_list_t)) {
  3593. memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
  3594. } else {
  3595. print_indent(indent);
  3596. outs() << " objc_method_description_list extends past end of the section\n";
  3597. memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
  3598. memcpy(&mdl, r, left);
  3599. }
  3600. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3601. swapStruct(mdl);
  3602. print_indent(indent);
  3603. outs() << " count " << mdl.count << "\n";
  3604. list = r + sizeof(struct objc_method_description_list_t);
  3605. for (i = 0; i < mdl.count; i++) {
  3606. if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
  3607. print_indent(indent);
  3608. outs() << " remaining list entries extend past the of the section\n";
  3609. break;
  3610. }
  3611. print_indent(indent);
  3612. outs() << " list[" << i << "]\n";
  3613. memcpy(&md, list + i * sizeof(struct objc_method_description_t),
  3614. sizeof(struct objc_method_description_t));
  3615. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3616. swapStruct(md);
  3617. print_indent(indent);
  3618. outs() << " name " << format("0x%08" PRIx32, md.name);
  3619. if (info->verbose) {
  3620. name = get_pointer_32(md.name, offset, xleft, S, info, true);
  3621. if (name != nullptr)
  3622. outs() << format(" %.*s", xleft, name);
  3623. else
  3624. outs() << " (not in an __OBJC section)";
  3625. }
  3626. outs() << "\n";
  3627. print_indent(indent);
  3628. outs() << " types " << format("0x%08" PRIx32, md.types);
  3629. if (info->verbose) {
  3630. name = get_pointer_32(md.types, offset, xleft, S, info, true);
  3631. if (name != nullptr)
  3632. outs() << format(" %.*s", xleft, name);
  3633. else
  3634. outs() << " (not in an __OBJC section)";
  3635. }
  3636. outs() << "\n";
  3637. }
  3638. return false;
  3639. }
  3640. static bool print_protocol_list(uint32_t p, uint32_t indent,
  3641. struct DisassembleInfo *info);
  3642. static bool print_protocol(uint32_t p, uint32_t indent,
  3643. struct DisassembleInfo *info) {
  3644. uint32_t offset, left;
  3645. SectionRef S;
  3646. struct objc_protocol_t protocol;
  3647. const char *r, *name;
  3648. r = get_pointer_32(p, offset, left, S, info, true);
  3649. if (r == nullptr)
  3650. return true;
  3651. outs() << "\n";
  3652. if (left >= sizeof(struct objc_protocol_t)) {
  3653. memcpy(&protocol, r, sizeof(struct objc_protocol_t));
  3654. } else {
  3655. print_indent(indent);
  3656. outs() << " Protocol extends past end of the section\n";
  3657. memset(&protocol, '\0', sizeof(struct objc_protocol_t));
  3658. memcpy(&protocol, r, left);
  3659. }
  3660. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3661. swapStruct(protocol);
  3662. print_indent(indent);
  3663. outs() << " isa " << format("0x%08" PRIx32, protocol.isa)
  3664. << "\n";
  3665. print_indent(indent);
  3666. outs() << " protocol_name "
  3667. << format("0x%08" PRIx32, protocol.protocol_name);
  3668. if (info->verbose) {
  3669. name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
  3670. if (name != nullptr)
  3671. outs() << format(" %.*s", left, name);
  3672. else
  3673. outs() << " (not in an __OBJC section)";
  3674. }
  3675. outs() << "\n";
  3676. print_indent(indent);
  3677. outs() << " protocol_list "
  3678. << format("0x%08" PRIx32, protocol.protocol_list);
  3679. if (print_protocol_list(protocol.protocol_list, indent + 4, info))
  3680. outs() << " (not in an __OBJC section)\n";
  3681. print_indent(indent);
  3682. outs() << " instance_methods "
  3683. << format("0x%08" PRIx32, protocol.instance_methods);
  3684. if (print_method_description_list(protocol.instance_methods, indent, info))
  3685. outs() << " (not in an __OBJC section)\n";
  3686. print_indent(indent);
  3687. outs() << " class_methods "
  3688. << format("0x%08" PRIx32, protocol.class_methods);
  3689. if (print_method_description_list(protocol.class_methods, indent, info))
  3690. outs() << " (not in an __OBJC section)\n";
  3691. return false;
  3692. }
  3693. static bool print_protocol_list(uint32_t p, uint32_t indent,
  3694. struct DisassembleInfo *info) {
  3695. uint32_t offset, left, l;
  3696. SectionRef S;
  3697. struct objc_protocol_list_t protocol_list;
  3698. const char *r, *list;
  3699. int32_t i;
  3700. r = get_pointer_32(p, offset, left, S, info, true);
  3701. if (r == nullptr)
  3702. return true;
  3703. outs() << "\n";
  3704. if (left > sizeof(struct objc_protocol_list_t)) {
  3705. memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
  3706. } else {
  3707. outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
  3708. memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
  3709. memcpy(&protocol_list, r, left);
  3710. }
  3711. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3712. swapStruct(protocol_list);
  3713. print_indent(indent);
  3714. outs() << " next " << format("0x%08" PRIx32, protocol_list.next)
  3715. << "\n";
  3716. print_indent(indent);
  3717. outs() << " count " << protocol_list.count << "\n";
  3718. list = r + sizeof(struct objc_protocol_list_t);
  3719. for (i = 0; i < protocol_list.count; i++) {
  3720. if ((i + 1) * sizeof(uint32_t) > left) {
  3721. outs() << "\t\t remaining list entries extend past the of the section\n";
  3722. break;
  3723. }
  3724. memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
  3725. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3726. sys::swapByteOrder(l);
  3727. print_indent(indent);
  3728. outs() << " list[" << i << "] " << format("0x%08" PRIx32, l);
  3729. if (print_protocol(l, indent, info))
  3730. outs() << "(not in an __OBJC section)\n";
  3731. }
  3732. return false;
  3733. }
  3734. static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
  3735. struct ivar_list64_t il;
  3736. struct ivar64_t i;
  3737. const char *r;
  3738. uint32_t offset, xoffset, left, j;
  3739. SectionRef S, xS;
  3740. const char *name, *sym_name, *ivar_offset_p;
  3741. uint64_t ivar_offset, n_value;
  3742. r = get_pointer_64(p, offset, left, S, info);
  3743. if (r == nullptr)
  3744. return;
  3745. memset(&il, '\0', sizeof(struct ivar_list64_t));
  3746. if (left < sizeof(struct ivar_list64_t)) {
  3747. memcpy(&il, r, left);
  3748. outs() << " (ivar_list_t entends past the end of the section)\n";
  3749. } else
  3750. memcpy(&il, r, sizeof(struct ivar_list64_t));
  3751. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3752. swapStruct(il);
  3753. outs() << " entsize " << il.entsize << "\n";
  3754. outs() << " count " << il.count << "\n";
  3755. p += sizeof(struct ivar_list64_t);
  3756. offset += sizeof(struct ivar_list64_t);
  3757. for (j = 0; j < il.count; j++) {
  3758. r = get_pointer_64(p, offset, left, S, info);
  3759. if (r == nullptr)
  3760. return;
  3761. memset(&i, '\0', sizeof(struct ivar64_t));
  3762. if (left < sizeof(struct ivar64_t)) {
  3763. memcpy(&i, r, left);
  3764. outs() << " (ivar_t entends past the end of the section)\n";
  3765. } else
  3766. memcpy(&i, r, sizeof(struct ivar64_t));
  3767. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3768. swapStruct(i);
  3769. outs() << "\t\t\t offset ";
  3770. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
  3771. info, n_value, i.offset);
  3772. if (n_value != 0) {
  3773. if (info->verbose && sym_name != nullptr)
  3774. outs() << sym_name;
  3775. else
  3776. outs() << format("0x%" PRIx64, n_value);
  3777. if (i.offset != 0)
  3778. outs() << " + " << format("0x%" PRIx64, i.offset);
  3779. } else
  3780. outs() << format("0x%" PRIx64, i.offset);
  3781. ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
  3782. if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
  3783. memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
  3784. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3785. sys::swapByteOrder(ivar_offset);
  3786. outs() << " " << ivar_offset << "\n";
  3787. } else
  3788. outs() << "\n";
  3789. outs() << "\t\t\t name ";
  3790. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
  3791. n_value, i.name);
  3792. if (n_value != 0) {
  3793. if (info->verbose && sym_name != nullptr)
  3794. outs() << sym_name;
  3795. else
  3796. outs() << format("0x%" PRIx64, n_value);
  3797. if (i.name != 0)
  3798. outs() << " + " << format("0x%" PRIx64, i.name);
  3799. } else
  3800. outs() << format("0x%" PRIx64, i.name);
  3801. name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
  3802. if (name != nullptr)
  3803. outs() << format(" %.*s", left, name);
  3804. outs() << "\n";
  3805. outs() << "\t\t\t type ";
  3806. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
  3807. n_value, i.name);
  3808. name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
  3809. if (n_value != 0) {
  3810. if (info->verbose && sym_name != nullptr)
  3811. outs() << sym_name;
  3812. else
  3813. outs() << format("0x%" PRIx64, n_value);
  3814. if (i.type != 0)
  3815. outs() << " + " << format("0x%" PRIx64, i.type);
  3816. } else
  3817. outs() << format("0x%" PRIx64, i.type);
  3818. if (name != nullptr)
  3819. outs() << format(" %.*s", left, name);
  3820. outs() << "\n";
  3821. outs() << "\t\t\talignment " << i.alignment << "\n";
  3822. outs() << "\t\t\t size " << i.size << "\n";
  3823. p += sizeof(struct ivar64_t);
  3824. offset += sizeof(struct ivar64_t);
  3825. }
  3826. }
  3827. static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
  3828. struct ivar_list32_t il;
  3829. struct ivar32_t i;
  3830. const char *r;
  3831. uint32_t offset, xoffset, left, j;
  3832. SectionRef S, xS;
  3833. const char *name, *ivar_offset_p;
  3834. uint32_t ivar_offset;
  3835. r = get_pointer_32(p, offset, left, S, info);
  3836. if (r == nullptr)
  3837. return;
  3838. memset(&il, '\0', sizeof(struct ivar_list32_t));
  3839. if (left < sizeof(struct ivar_list32_t)) {
  3840. memcpy(&il, r, left);
  3841. outs() << " (ivar_list_t entends past the end of the section)\n";
  3842. } else
  3843. memcpy(&il, r, sizeof(struct ivar_list32_t));
  3844. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3845. swapStruct(il);
  3846. outs() << " entsize " << il.entsize << "\n";
  3847. outs() << " count " << il.count << "\n";
  3848. p += sizeof(struct ivar_list32_t);
  3849. offset += sizeof(struct ivar_list32_t);
  3850. for (j = 0; j < il.count; j++) {
  3851. r = get_pointer_32(p, offset, left, S, info);
  3852. if (r == nullptr)
  3853. return;
  3854. memset(&i, '\0', sizeof(struct ivar32_t));
  3855. if (left < sizeof(struct ivar32_t)) {
  3856. memcpy(&i, r, left);
  3857. outs() << " (ivar_t entends past the end of the section)\n";
  3858. } else
  3859. memcpy(&i, r, sizeof(struct ivar32_t));
  3860. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3861. swapStruct(i);
  3862. outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset);
  3863. ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
  3864. if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
  3865. memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
  3866. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3867. sys::swapByteOrder(ivar_offset);
  3868. outs() << " " << ivar_offset << "\n";
  3869. } else
  3870. outs() << "\n";
  3871. outs() << "\t\t\t name " << format("0x%" PRIx32, i.name);
  3872. name = get_pointer_32(i.name, xoffset, left, xS, info);
  3873. if (name != nullptr)
  3874. outs() << format(" %.*s", left, name);
  3875. outs() << "\n";
  3876. outs() << "\t\t\t type " << format("0x%" PRIx32, i.type);
  3877. name = get_pointer_32(i.type, xoffset, left, xS, info);
  3878. if (name != nullptr)
  3879. outs() << format(" %.*s", left, name);
  3880. outs() << "\n";
  3881. outs() << "\t\t\talignment " << i.alignment << "\n";
  3882. outs() << "\t\t\t size " << i.size << "\n";
  3883. p += sizeof(struct ivar32_t);
  3884. offset += sizeof(struct ivar32_t);
  3885. }
  3886. }
  3887. static void print_objc_property_list64(uint64_t p,
  3888. struct DisassembleInfo *info) {
  3889. struct objc_property_list64 opl;
  3890. struct objc_property64 op;
  3891. const char *r;
  3892. uint32_t offset, xoffset, left, j;
  3893. SectionRef S, xS;
  3894. const char *name, *sym_name;
  3895. uint64_t n_value;
  3896. r = get_pointer_64(p, offset, left, S, info);
  3897. if (r == nullptr)
  3898. return;
  3899. memset(&opl, '\0', sizeof(struct objc_property_list64));
  3900. if (left < sizeof(struct objc_property_list64)) {
  3901. memcpy(&opl, r, left);
  3902. outs() << " (objc_property_list entends past the end of the section)\n";
  3903. } else
  3904. memcpy(&opl, r, sizeof(struct objc_property_list64));
  3905. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3906. swapStruct(opl);
  3907. outs() << " entsize " << opl.entsize << "\n";
  3908. outs() << " count " << opl.count << "\n";
  3909. p += sizeof(struct objc_property_list64);
  3910. offset += sizeof(struct objc_property_list64);
  3911. for (j = 0; j < opl.count; j++) {
  3912. r = get_pointer_64(p, offset, left, S, info);
  3913. if (r == nullptr)
  3914. return;
  3915. memset(&op, '\0', sizeof(struct objc_property64));
  3916. if (left < sizeof(struct objc_property64)) {
  3917. memcpy(&op, r, left);
  3918. outs() << " (objc_property entends past the end of the section)\n";
  3919. } else
  3920. memcpy(&op, r, sizeof(struct objc_property64));
  3921. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3922. swapStruct(op);
  3923. outs() << "\t\t\t name ";
  3924. sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
  3925. info, n_value, op.name);
  3926. if (n_value != 0) {
  3927. if (info->verbose && sym_name != nullptr)
  3928. outs() << sym_name;
  3929. else
  3930. outs() << format("0x%" PRIx64, n_value);
  3931. if (op.name != 0)
  3932. outs() << " + " << format("0x%" PRIx64, op.name);
  3933. } else
  3934. outs() << format("0x%" PRIx64, op.name);
  3935. name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
  3936. if (name != nullptr)
  3937. outs() << format(" %.*s", left, name);
  3938. outs() << "\n";
  3939. outs() << "\t\t\tattributes ";
  3940. sym_name =
  3941. get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
  3942. info, n_value, op.attributes);
  3943. if (n_value != 0) {
  3944. if (info->verbose && sym_name != nullptr)
  3945. outs() << sym_name;
  3946. else
  3947. outs() << format("0x%" PRIx64, n_value);
  3948. if (op.attributes != 0)
  3949. outs() << " + " << format("0x%" PRIx64, op.attributes);
  3950. } else
  3951. outs() << format("0x%" PRIx64, op.attributes);
  3952. name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
  3953. if (name != nullptr)
  3954. outs() << format(" %.*s", left, name);
  3955. outs() << "\n";
  3956. p += sizeof(struct objc_property64);
  3957. offset += sizeof(struct objc_property64);
  3958. }
  3959. }
  3960. static void print_objc_property_list32(uint32_t p,
  3961. struct DisassembleInfo *info) {
  3962. struct objc_property_list32 opl;
  3963. struct objc_property32 op;
  3964. const char *r;
  3965. uint32_t offset, xoffset, left, j;
  3966. SectionRef S, xS;
  3967. const char *name;
  3968. r = get_pointer_32(p, offset, left, S, info);
  3969. if (r == nullptr)
  3970. return;
  3971. memset(&opl, '\0', sizeof(struct objc_property_list32));
  3972. if (left < sizeof(struct objc_property_list32)) {
  3973. memcpy(&opl, r, left);
  3974. outs() << " (objc_property_list entends past the end of the section)\n";
  3975. } else
  3976. memcpy(&opl, r, sizeof(struct objc_property_list32));
  3977. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3978. swapStruct(opl);
  3979. outs() << " entsize " << opl.entsize << "\n";
  3980. outs() << " count " << opl.count << "\n";
  3981. p += sizeof(struct objc_property_list32);
  3982. offset += sizeof(struct objc_property_list32);
  3983. for (j = 0; j < opl.count; j++) {
  3984. r = get_pointer_32(p, offset, left, S, info);
  3985. if (r == nullptr)
  3986. return;
  3987. memset(&op, '\0', sizeof(struct objc_property32));
  3988. if (left < sizeof(struct objc_property32)) {
  3989. memcpy(&op, r, left);
  3990. outs() << " (objc_property entends past the end of the section)\n";
  3991. } else
  3992. memcpy(&op, r, sizeof(struct objc_property32));
  3993. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3994. swapStruct(op);
  3995. outs() << "\t\t\t name " << format("0x%" PRIx32, op.name);
  3996. name = get_pointer_32(op.name, xoffset, left, xS, info);
  3997. if (name != nullptr)
  3998. outs() << format(" %.*s", left, name);
  3999. outs() << "\n";
  4000. outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
  4001. name = get_pointer_32(op.attributes, xoffset, left, xS, info);
  4002. if (name != nullptr)
  4003. outs() << format(" %.*s", left, name);
  4004. outs() << "\n";
  4005. p += sizeof(struct objc_property32);
  4006. offset += sizeof(struct objc_property32);
  4007. }
  4008. }
  4009. static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
  4010. bool &is_meta_class) {
  4011. struct class_ro64_t cro;
  4012. const char *r;
  4013. uint32_t offset, xoffset, left;
  4014. SectionRef S, xS;
  4015. const char *name, *sym_name;
  4016. uint64_t n_value;
  4017. r = get_pointer_64(p, offset, left, S, info);
  4018. if (r == nullptr || left < sizeof(struct class_ro64_t))
  4019. return false;
  4020. memcpy(&cro, r, sizeof(struct class_ro64_t));
  4021. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4022. swapStruct(cro);
  4023. outs() << " flags " << format("0x%" PRIx32, cro.flags);
  4024. if (cro.flags & RO_META)
  4025. outs() << " RO_META";
  4026. if (cro.flags & RO_ROOT)
  4027. outs() << " RO_ROOT";
  4028. if (cro.flags & RO_HAS_CXX_STRUCTORS)
  4029. outs() << " RO_HAS_CXX_STRUCTORS";
  4030. outs() << "\n";
  4031. outs() << " instanceStart " << cro.instanceStart << "\n";
  4032. outs() << " instanceSize " << cro.instanceSize << "\n";
  4033. outs() << " reserved " << format("0x%" PRIx32, cro.reserved)
  4034. << "\n";
  4035. outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
  4036. << "\n";
  4037. print_layout_map64(cro.ivarLayout, info);
  4038. outs() << " name ";
  4039. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
  4040. info, n_value, cro.name);
  4041. if (n_value != 0) {
  4042. if (info->verbose && sym_name != nullptr)
  4043. outs() << sym_name;
  4044. else
  4045. outs() << format("0x%" PRIx64, n_value);
  4046. if (cro.name != 0)
  4047. outs() << " + " << format("0x%" PRIx64, cro.name);
  4048. } else
  4049. outs() << format("0x%" PRIx64, cro.name);
  4050. name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
  4051. if (name != nullptr)
  4052. outs() << format(" %.*s", left, name);
  4053. outs() << "\n";
  4054. outs() << " baseMethods ";
  4055. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
  4056. S, info, n_value, cro.baseMethods);
  4057. if (n_value != 0) {
  4058. if (info->verbose && sym_name != nullptr)
  4059. outs() << sym_name;
  4060. else
  4061. outs() << format("0x%" PRIx64, n_value);
  4062. if (cro.baseMethods != 0)
  4063. outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
  4064. } else
  4065. outs() << format("0x%" PRIx64, cro.baseMethods);
  4066. outs() << " (struct method_list_t *)\n";
  4067. if (cro.baseMethods + n_value != 0)
  4068. print_method_list64_t(cro.baseMethods + n_value, info, "");
  4069. outs() << " baseProtocols ";
  4070. sym_name =
  4071. get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
  4072. info, n_value, cro.baseProtocols);
  4073. if (n_value != 0) {
  4074. if (info->verbose && sym_name != nullptr)
  4075. outs() << sym_name;
  4076. else
  4077. outs() << format("0x%" PRIx64, n_value);
  4078. if (cro.baseProtocols != 0)
  4079. outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
  4080. } else
  4081. outs() << format("0x%" PRIx64, cro.baseProtocols);
  4082. outs() << "\n";
  4083. if (cro.baseProtocols + n_value != 0)
  4084. print_protocol_list64_t(cro.baseProtocols + n_value, info);
  4085. outs() << " ivars ";
  4086. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
  4087. info, n_value, cro.ivars);
  4088. if (n_value != 0) {
  4089. if (info->verbose && sym_name != nullptr)
  4090. outs() << sym_name;
  4091. else
  4092. outs() << format("0x%" PRIx64, n_value);
  4093. if (cro.ivars != 0)
  4094. outs() << " + " << format("0x%" PRIx64, cro.ivars);
  4095. } else
  4096. outs() << format("0x%" PRIx64, cro.ivars);
  4097. outs() << "\n";
  4098. if (cro.ivars + n_value != 0)
  4099. print_ivar_list64_t(cro.ivars + n_value, info);
  4100. outs() << " weakIvarLayout ";
  4101. sym_name =
  4102. get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
  4103. info, n_value, cro.weakIvarLayout);
  4104. if (n_value != 0) {
  4105. if (info->verbose && sym_name != nullptr)
  4106. outs() << sym_name;
  4107. else
  4108. outs() << format("0x%" PRIx64, n_value);
  4109. if (cro.weakIvarLayout != 0)
  4110. outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
  4111. } else
  4112. outs() << format("0x%" PRIx64, cro.weakIvarLayout);
  4113. outs() << "\n";
  4114. print_layout_map64(cro.weakIvarLayout + n_value, info);
  4115. outs() << " baseProperties ";
  4116. sym_name =
  4117. get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
  4118. info, n_value, cro.baseProperties);
  4119. if (n_value != 0) {
  4120. if (info->verbose && sym_name != nullptr)
  4121. outs() << sym_name;
  4122. else
  4123. outs() << format("0x%" PRIx64, n_value);
  4124. if (cro.baseProperties != 0)
  4125. outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
  4126. } else
  4127. outs() << format("0x%" PRIx64, cro.baseProperties);
  4128. outs() << "\n";
  4129. if (cro.baseProperties + n_value != 0)
  4130. print_objc_property_list64(cro.baseProperties + n_value, info);
  4131. is_meta_class = (cro.flags & RO_META) != 0;
  4132. return true;
  4133. }
  4134. static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
  4135. bool &is_meta_class) {
  4136. struct class_ro32_t cro;
  4137. const char *r;
  4138. uint32_t offset, xoffset, left;
  4139. SectionRef S, xS;
  4140. const char *name;
  4141. r = get_pointer_32(p, offset, left, S, info);
  4142. if (r == nullptr)
  4143. return false;
  4144. memset(&cro, '\0', sizeof(struct class_ro32_t));
  4145. if (left < sizeof(struct class_ro32_t)) {
  4146. memcpy(&cro, r, left);
  4147. outs() << " (class_ro_t entends past the end of the section)\n";
  4148. } else
  4149. memcpy(&cro, r, sizeof(struct class_ro32_t));
  4150. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4151. swapStruct(cro);
  4152. outs() << " flags " << format("0x%" PRIx32, cro.flags);
  4153. if (cro.flags & RO_META)
  4154. outs() << " RO_META";
  4155. if (cro.flags & RO_ROOT)
  4156. outs() << " RO_ROOT";
  4157. if (cro.flags & RO_HAS_CXX_STRUCTORS)
  4158. outs() << " RO_HAS_CXX_STRUCTORS";
  4159. outs() << "\n";
  4160. outs() << " instanceStart " << cro.instanceStart << "\n";
  4161. outs() << " instanceSize " << cro.instanceSize << "\n";
  4162. outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
  4163. << "\n";
  4164. print_layout_map32(cro.ivarLayout, info);
  4165. outs() << " name " << format("0x%" PRIx32, cro.name);
  4166. name = get_pointer_32(cro.name, xoffset, left, xS, info);
  4167. if (name != nullptr)
  4168. outs() << format(" %.*s", left, name);
  4169. outs() << "\n";
  4170. outs() << " baseMethods "
  4171. << format("0x%" PRIx32, cro.baseMethods)
  4172. << " (struct method_list_t *)\n";
  4173. if (cro.baseMethods != 0)
  4174. print_method_list32_t(cro.baseMethods, info, "");
  4175. outs() << " baseProtocols "
  4176. << format("0x%" PRIx32, cro.baseProtocols) << "\n";
  4177. if (cro.baseProtocols != 0)
  4178. print_protocol_list32_t(cro.baseProtocols, info);
  4179. outs() << " ivars " << format("0x%" PRIx32, cro.ivars)
  4180. << "\n";
  4181. if (cro.ivars != 0)
  4182. print_ivar_list32_t(cro.ivars, info);
  4183. outs() << " weakIvarLayout "
  4184. << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
  4185. print_layout_map32(cro.weakIvarLayout, info);
  4186. outs() << " baseProperties "
  4187. << format("0x%" PRIx32, cro.baseProperties) << "\n";
  4188. if (cro.baseProperties != 0)
  4189. print_objc_property_list32(cro.baseProperties, info);
  4190. is_meta_class = (cro.flags & RO_META) != 0;
  4191. return true;
  4192. }
  4193. static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
  4194. struct class64_t c;
  4195. const char *r;
  4196. uint32_t offset, left;
  4197. SectionRef S;
  4198. const char *name;
  4199. uint64_t isa_n_value, n_value;
  4200. r = get_pointer_64(p, offset, left, S, info);
  4201. if (r == nullptr || left < sizeof(struct class64_t))
  4202. return;
  4203. memcpy(&c, r, sizeof(struct class64_t));
  4204. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4205. swapStruct(c);
  4206. outs() << " isa " << format("0x%" PRIx64, c.isa);
  4207. name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
  4208. isa_n_value, c.isa);
  4209. if (name != nullptr)
  4210. outs() << " " << name;
  4211. outs() << "\n";
  4212. outs() << " superclass " << format("0x%" PRIx64, c.superclass);
  4213. name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
  4214. n_value, c.superclass);
  4215. if (name != nullptr)
  4216. outs() << " " << name;
  4217. outs() << "\n";
  4218. outs() << " cache " << format("0x%" PRIx64, c.cache);
  4219. name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
  4220. n_value, c.cache);
  4221. if (name != nullptr)
  4222. outs() << " " << name;
  4223. outs() << "\n";
  4224. outs() << " vtable " << format("0x%" PRIx64, c.vtable);
  4225. name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
  4226. n_value, c.vtable);
  4227. if (name != nullptr)
  4228. outs() << " " << name;
  4229. outs() << "\n";
  4230. name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
  4231. n_value, c.data);
  4232. outs() << " data ";
  4233. if (n_value != 0) {
  4234. if (info->verbose && name != nullptr)
  4235. outs() << name;
  4236. else
  4237. outs() << format("0x%" PRIx64, n_value);
  4238. if (c.data != 0)
  4239. outs() << " + " << format("0x%" PRIx64, c.data);
  4240. } else
  4241. outs() << format("0x%" PRIx64, c.data);
  4242. outs() << " (struct class_ro_t *)";
  4243. // This is a Swift class if some of the low bits of the pointer are set.
  4244. if ((c.data + n_value) & 0x7)
  4245. outs() << " Swift class";
  4246. outs() << "\n";
  4247. bool is_meta_class;
  4248. if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
  4249. return;
  4250. if (!is_meta_class &&
  4251. c.isa + isa_n_value != p &&
  4252. c.isa + isa_n_value != 0 &&
  4253. info->depth < 100) {
  4254. info->depth++;
  4255. outs() << "Meta Class\n";
  4256. print_class64_t(c.isa + isa_n_value, info);
  4257. }
  4258. }
  4259. static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
  4260. struct class32_t c;
  4261. const char *r;
  4262. uint32_t offset, left;
  4263. SectionRef S;
  4264. const char *name;
  4265. r = get_pointer_32(p, offset, left, S, info);
  4266. if (r == nullptr)
  4267. return;
  4268. memset(&c, '\0', sizeof(struct class32_t));
  4269. if (left < sizeof(struct class32_t)) {
  4270. memcpy(&c, r, left);
  4271. outs() << " (class_t entends past the end of the section)\n";
  4272. } else
  4273. memcpy(&c, r, sizeof(struct class32_t));
  4274. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4275. swapStruct(c);
  4276. outs() << " isa " << format("0x%" PRIx32, c.isa);
  4277. name =
  4278. get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
  4279. if (name != nullptr)
  4280. outs() << " " << name;
  4281. outs() << "\n";
  4282. outs() << " superclass " << format("0x%" PRIx32, c.superclass);
  4283. name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
  4284. c.superclass);
  4285. if (name != nullptr)
  4286. outs() << " " << name;
  4287. outs() << "\n";
  4288. outs() << " cache " << format("0x%" PRIx32, c.cache);
  4289. name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
  4290. c.cache);
  4291. if (name != nullptr)
  4292. outs() << " " << name;
  4293. outs() << "\n";
  4294. outs() << " vtable " << format("0x%" PRIx32, c.vtable);
  4295. name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
  4296. c.vtable);
  4297. if (name != nullptr)
  4298. outs() << " " << name;
  4299. outs() << "\n";
  4300. name =
  4301. get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
  4302. outs() << " data " << format("0x%" PRIx32, c.data)
  4303. << " (struct class_ro_t *)";
  4304. // This is a Swift class if some of the low bits of the pointer are set.
  4305. if (c.data & 0x3)
  4306. outs() << " Swift class";
  4307. outs() << "\n";
  4308. bool is_meta_class;
  4309. if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
  4310. return;
  4311. if (!is_meta_class) {
  4312. outs() << "Meta Class\n";
  4313. print_class32_t(c.isa, info);
  4314. }
  4315. }
  4316. static void print_objc_class_t(struct objc_class_t *objc_class,
  4317. struct DisassembleInfo *info) {
  4318. uint32_t offset, left, xleft;
  4319. const char *name, *p, *ivar_list;
  4320. SectionRef S;
  4321. int32_t i;
  4322. struct objc_ivar_list_t objc_ivar_list;
  4323. struct objc_ivar_t ivar;
  4324. outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa);
  4325. if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
  4326. name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
  4327. if (name != nullptr)
  4328. outs() << format(" %.*s", left, name);
  4329. else
  4330. outs() << " (not in an __OBJC section)";
  4331. }
  4332. outs() << "\n";
  4333. outs() << "\t super_class "
  4334. << format("0x%08" PRIx32, objc_class->super_class);
  4335. if (info->verbose) {
  4336. name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
  4337. if (name != nullptr)
  4338. outs() << format(" %.*s", left, name);
  4339. else
  4340. outs() << " (not in an __OBJC section)";
  4341. }
  4342. outs() << "\n";
  4343. outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name);
  4344. if (info->verbose) {
  4345. name = get_pointer_32(objc_class->name, offset, left, S, info, true);
  4346. if (name != nullptr)
  4347. outs() << format(" %.*s", left, name);
  4348. else
  4349. outs() << " (not in an __OBJC section)";
  4350. }
  4351. outs() << "\n";
  4352. outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version)
  4353. << "\n";
  4354. outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info);
  4355. if (info->verbose) {
  4356. if (CLS_GETINFO(objc_class, CLS_CLASS))
  4357. outs() << " CLS_CLASS";
  4358. else if (CLS_GETINFO(objc_class, CLS_META))
  4359. outs() << " CLS_META";
  4360. }
  4361. outs() << "\n";
  4362. outs() << "\t instance_size "
  4363. << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
  4364. p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
  4365. outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars);
  4366. if (p != nullptr) {
  4367. if (left > sizeof(struct objc_ivar_list_t)) {
  4368. outs() << "\n";
  4369. memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
  4370. } else {
  4371. outs() << " (entends past the end of the section)\n";
  4372. memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
  4373. memcpy(&objc_ivar_list, p, left);
  4374. }
  4375. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4376. swapStruct(objc_ivar_list);
  4377. outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
  4378. ivar_list = p + sizeof(struct objc_ivar_list_t);
  4379. for (i = 0; i < objc_ivar_list.ivar_count; i++) {
  4380. if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
  4381. outs() << "\t\t remaining ivar's extend past the of the section\n";
  4382. break;
  4383. }
  4384. memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
  4385. sizeof(struct objc_ivar_t));
  4386. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4387. swapStruct(ivar);
  4388. outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
  4389. if (info->verbose) {
  4390. name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
  4391. if (name != nullptr)
  4392. outs() << format(" %.*s", xleft, name);
  4393. else
  4394. outs() << " (not in an __OBJC section)";
  4395. }
  4396. outs() << "\n";
  4397. outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
  4398. if (info->verbose) {
  4399. name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
  4400. if (name != nullptr)
  4401. outs() << format(" %.*s", xleft, name);
  4402. else
  4403. outs() << " (not in an __OBJC section)";
  4404. }
  4405. outs() << "\n";
  4406. outs() << "\t\t ivar_offset "
  4407. << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
  4408. }
  4409. } else {
  4410. outs() << " (not in an __OBJC section)\n";
  4411. }
  4412. outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists);
  4413. if (print_method_list(objc_class->methodLists, info))
  4414. outs() << " (not in an __OBJC section)\n";
  4415. outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache)
  4416. << "\n";
  4417. outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
  4418. if (print_protocol_list(objc_class->protocols, 16, info))
  4419. outs() << " (not in an __OBJC section)\n";
  4420. }
  4421. static void print_objc_objc_category_t(struct objc_category_t *objc_category,
  4422. struct DisassembleInfo *info) {
  4423. uint32_t offset, left;
  4424. const char *name;
  4425. SectionRef S;
  4426. outs() << "\t category name "
  4427. << format("0x%08" PRIx32, objc_category->category_name);
  4428. if (info->verbose) {
  4429. name = get_pointer_32(objc_category->category_name, offset, left, S, info,
  4430. true);
  4431. if (name != nullptr)
  4432. outs() << format(" %.*s", left, name);
  4433. else
  4434. outs() << " (not in an __OBJC section)";
  4435. }
  4436. outs() << "\n";
  4437. outs() << "\t\t class name "
  4438. << format("0x%08" PRIx32, objc_category->class_name);
  4439. if (info->verbose) {
  4440. name =
  4441. get_pointer_32(objc_category->class_name, offset, left, S, info, true);
  4442. if (name != nullptr)
  4443. outs() << format(" %.*s", left, name);
  4444. else
  4445. outs() << " (not in an __OBJC section)";
  4446. }
  4447. outs() << "\n";
  4448. outs() << "\t instance methods "
  4449. << format("0x%08" PRIx32, objc_category->instance_methods);
  4450. if (print_method_list(objc_category->instance_methods, info))
  4451. outs() << " (not in an __OBJC section)\n";
  4452. outs() << "\t class methods "
  4453. << format("0x%08" PRIx32, objc_category->class_methods);
  4454. if (print_method_list(objc_category->class_methods, info))
  4455. outs() << " (not in an __OBJC section)\n";
  4456. }
  4457. static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
  4458. struct category64_t c;
  4459. const char *r;
  4460. uint32_t offset, xoffset, left;
  4461. SectionRef S, xS;
  4462. const char *name, *sym_name;
  4463. uint64_t n_value;
  4464. r = get_pointer_64(p, offset, left, S, info);
  4465. if (r == nullptr)
  4466. return;
  4467. memset(&c, '\0', sizeof(struct category64_t));
  4468. if (left < sizeof(struct category64_t)) {
  4469. memcpy(&c, r, left);
  4470. outs() << " (category_t entends past the end of the section)\n";
  4471. } else
  4472. memcpy(&c, r, sizeof(struct category64_t));
  4473. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4474. swapStruct(c);
  4475. outs() << " name ";
  4476. sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
  4477. info, n_value, c.name);
  4478. if (n_value != 0) {
  4479. if (info->verbose && sym_name != nullptr)
  4480. outs() << sym_name;
  4481. else
  4482. outs() << format("0x%" PRIx64, n_value);
  4483. if (c.name != 0)
  4484. outs() << " + " << format("0x%" PRIx64, c.name);
  4485. } else
  4486. outs() << format("0x%" PRIx64, c.name);
  4487. name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
  4488. if (name != nullptr)
  4489. outs() << format(" %.*s", left, name);
  4490. outs() << "\n";
  4491. outs() << " cls ";
  4492. sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
  4493. n_value, c.cls);
  4494. if (n_value != 0) {
  4495. if (info->verbose && sym_name != nullptr)
  4496. outs() << sym_name;
  4497. else
  4498. outs() << format("0x%" PRIx64, n_value);
  4499. if (c.cls != 0)
  4500. outs() << " + " << format("0x%" PRIx64, c.cls);
  4501. } else
  4502. outs() << format("0x%" PRIx64, c.cls);
  4503. outs() << "\n";
  4504. if (c.cls + n_value != 0)
  4505. print_class64_t(c.cls + n_value, info);
  4506. outs() << " instanceMethods ";
  4507. sym_name =
  4508. get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
  4509. info, n_value, c.instanceMethods);
  4510. if (n_value != 0) {
  4511. if (info->verbose && sym_name != nullptr)
  4512. outs() << sym_name;
  4513. else
  4514. outs() << format("0x%" PRIx64, n_value);
  4515. if (c.instanceMethods != 0)
  4516. outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
  4517. } else
  4518. outs() << format("0x%" PRIx64, c.instanceMethods);
  4519. outs() << "\n";
  4520. if (c.instanceMethods + n_value != 0)
  4521. print_method_list64_t(c.instanceMethods + n_value, info, "");
  4522. outs() << " classMethods ";
  4523. sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
  4524. S, info, n_value, c.classMethods);
  4525. if (n_value != 0) {
  4526. if (info->verbose && sym_name != nullptr)
  4527. outs() << sym_name;
  4528. else
  4529. outs() << format("0x%" PRIx64, n_value);
  4530. if (c.classMethods != 0)
  4531. outs() << " + " << format("0x%" PRIx64, c.classMethods);
  4532. } else
  4533. outs() << format("0x%" PRIx64, c.classMethods);
  4534. outs() << "\n";
  4535. if (c.classMethods + n_value != 0)
  4536. print_method_list64_t(c.classMethods + n_value, info, "");
  4537. outs() << " protocols ";
  4538. sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
  4539. info, n_value, c.protocols);
  4540. if (n_value != 0) {
  4541. if (info->verbose && sym_name != nullptr)
  4542. outs() << sym_name;
  4543. else
  4544. outs() << format("0x%" PRIx64, n_value);
  4545. if (c.protocols != 0)
  4546. outs() << " + " << format("0x%" PRIx64, c.protocols);
  4547. } else
  4548. outs() << format("0x%" PRIx64, c.protocols);
  4549. outs() << "\n";
  4550. if (c.protocols + n_value != 0)
  4551. print_protocol_list64_t(c.protocols + n_value, info);
  4552. outs() << "instanceProperties ";
  4553. sym_name =
  4554. get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
  4555. S, info, n_value, c.instanceProperties);
  4556. if (n_value != 0) {
  4557. if (info->verbose && sym_name != nullptr)
  4558. outs() << sym_name;
  4559. else
  4560. outs() << format("0x%" PRIx64, n_value);
  4561. if (c.instanceProperties != 0)
  4562. outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
  4563. } else
  4564. outs() << format("0x%" PRIx64, c.instanceProperties);
  4565. outs() << "\n";
  4566. if (c.instanceProperties + n_value != 0)
  4567. print_objc_property_list64(c.instanceProperties + n_value, info);
  4568. }
  4569. static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
  4570. struct category32_t c;
  4571. const char *r;
  4572. uint32_t offset, left;
  4573. SectionRef S, xS;
  4574. const char *name;
  4575. r = get_pointer_32(p, offset, left, S, info);
  4576. if (r == nullptr)
  4577. return;
  4578. memset(&c, '\0', sizeof(struct category32_t));
  4579. if (left < sizeof(struct category32_t)) {
  4580. memcpy(&c, r, left);
  4581. outs() << " (category_t entends past the end of the section)\n";
  4582. } else
  4583. memcpy(&c, r, sizeof(struct category32_t));
  4584. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4585. swapStruct(c);
  4586. outs() << " name " << format("0x%" PRIx32, c.name);
  4587. name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
  4588. c.name);
  4589. if (name)
  4590. outs() << " " << name;
  4591. outs() << "\n";
  4592. outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n";
  4593. if (c.cls != 0)
  4594. print_class32_t(c.cls, info);
  4595. outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
  4596. << "\n";
  4597. if (c.instanceMethods != 0)
  4598. print_method_list32_t(c.instanceMethods, info, "");
  4599. outs() << " classMethods " << format("0x%" PRIx32, c.classMethods)
  4600. << "\n";
  4601. if (c.classMethods != 0)
  4602. print_method_list32_t(c.classMethods, info, "");
  4603. outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n";
  4604. if (c.protocols != 0)
  4605. print_protocol_list32_t(c.protocols, info);
  4606. outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
  4607. << "\n";
  4608. if (c.instanceProperties != 0)
  4609. print_objc_property_list32(c.instanceProperties, info);
  4610. }
  4611. static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
  4612. uint32_t i, left, offset, xoffset;
  4613. uint64_t p, n_value;
  4614. struct message_ref64 mr;
  4615. const char *name, *sym_name;
  4616. const char *r;
  4617. SectionRef xS;
  4618. if (S == SectionRef())
  4619. return;
  4620. StringRef SectName;
  4621. S.getName(SectName);
  4622. DataRefImpl Ref = S.getRawDataRefImpl();
  4623. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4624. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4625. offset = 0;
  4626. for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
  4627. p = S.getAddress() + i;
  4628. r = get_pointer_64(p, offset, left, S, info);
  4629. if (r == nullptr)
  4630. return;
  4631. memset(&mr, '\0', sizeof(struct message_ref64));
  4632. if (left < sizeof(struct message_ref64)) {
  4633. memcpy(&mr, r, left);
  4634. outs() << " (message_ref entends past the end of the section)\n";
  4635. } else
  4636. memcpy(&mr, r, sizeof(struct message_ref64));
  4637. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4638. swapStruct(mr);
  4639. outs() << " imp ";
  4640. name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
  4641. n_value, mr.imp);
  4642. if (n_value != 0) {
  4643. outs() << format("0x%" PRIx64, n_value) << " ";
  4644. if (mr.imp != 0)
  4645. outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
  4646. } else
  4647. outs() << format("0x%" PRIx64, mr.imp) << " ";
  4648. if (name != nullptr)
  4649. outs() << " " << name;
  4650. outs() << "\n";
  4651. outs() << " sel ";
  4652. sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
  4653. info, n_value, mr.sel);
  4654. if (n_value != 0) {
  4655. if (info->verbose && sym_name != nullptr)
  4656. outs() << sym_name;
  4657. else
  4658. outs() << format("0x%" PRIx64, n_value);
  4659. if (mr.sel != 0)
  4660. outs() << " + " << format("0x%" PRIx64, mr.sel);
  4661. } else
  4662. outs() << format("0x%" PRIx64, mr.sel);
  4663. name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
  4664. if (name != nullptr)
  4665. outs() << format(" %.*s", left, name);
  4666. outs() << "\n";
  4667. offset += sizeof(struct message_ref64);
  4668. }
  4669. }
  4670. static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
  4671. uint32_t i, left, offset, xoffset, p;
  4672. struct message_ref32 mr;
  4673. const char *name, *r;
  4674. SectionRef xS;
  4675. if (S == SectionRef())
  4676. return;
  4677. StringRef SectName;
  4678. S.getName(SectName);
  4679. DataRefImpl Ref = S.getRawDataRefImpl();
  4680. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4681. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4682. offset = 0;
  4683. for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
  4684. p = S.getAddress() + i;
  4685. r = get_pointer_32(p, offset, left, S, info);
  4686. if (r == nullptr)
  4687. return;
  4688. memset(&mr, '\0', sizeof(struct message_ref32));
  4689. if (left < sizeof(struct message_ref32)) {
  4690. memcpy(&mr, r, left);
  4691. outs() << " (message_ref entends past the end of the section)\n";
  4692. } else
  4693. memcpy(&mr, r, sizeof(struct message_ref32));
  4694. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4695. swapStruct(mr);
  4696. outs() << " imp " << format("0x%" PRIx32, mr.imp);
  4697. name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
  4698. mr.imp);
  4699. if (name != nullptr)
  4700. outs() << " " << name;
  4701. outs() << "\n";
  4702. outs() << " sel " << format("0x%" PRIx32, mr.sel);
  4703. name = get_pointer_32(mr.sel, xoffset, left, xS, info);
  4704. if (name != nullptr)
  4705. outs() << " " << name;
  4706. outs() << "\n";
  4707. offset += sizeof(struct message_ref32);
  4708. }
  4709. }
  4710. static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
  4711. uint32_t left, offset, swift_version;
  4712. uint64_t p;
  4713. struct objc_image_info64 o;
  4714. const char *r;
  4715. if (S == SectionRef())
  4716. return;
  4717. StringRef SectName;
  4718. S.getName(SectName);
  4719. DataRefImpl Ref = S.getRawDataRefImpl();
  4720. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4721. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4722. p = S.getAddress();
  4723. r = get_pointer_64(p, offset, left, S, info);
  4724. if (r == nullptr)
  4725. return;
  4726. memset(&o, '\0', sizeof(struct objc_image_info64));
  4727. if (left < sizeof(struct objc_image_info64)) {
  4728. memcpy(&o, r, left);
  4729. outs() << " (objc_image_info entends past the end of the section)\n";
  4730. } else
  4731. memcpy(&o, r, sizeof(struct objc_image_info64));
  4732. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4733. swapStruct(o);
  4734. outs() << " version " << o.version << "\n";
  4735. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4736. if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
  4737. outs() << " OBJC_IMAGE_IS_REPLACEMENT";
  4738. if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
  4739. outs() << " OBJC_IMAGE_SUPPORTS_GC";
  4740. swift_version = (o.flags >> 8) & 0xff;
  4741. if (swift_version != 0) {
  4742. if (swift_version == 1)
  4743. outs() << " Swift 1.0";
  4744. else if (swift_version == 2)
  4745. outs() << " Swift 1.1";
  4746. else
  4747. outs() << " unknown future Swift version (" << swift_version << ")";
  4748. }
  4749. outs() << "\n";
  4750. }
  4751. static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
  4752. uint32_t left, offset, swift_version, p;
  4753. struct objc_image_info32 o;
  4754. const char *r;
  4755. if (S == SectionRef())
  4756. return;
  4757. StringRef SectName;
  4758. S.getName(SectName);
  4759. DataRefImpl Ref = S.getRawDataRefImpl();
  4760. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4761. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4762. p = S.getAddress();
  4763. r = get_pointer_32(p, offset, left, S, info);
  4764. if (r == nullptr)
  4765. return;
  4766. memset(&o, '\0', sizeof(struct objc_image_info32));
  4767. if (left < sizeof(struct objc_image_info32)) {
  4768. memcpy(&o, r, left);
  4769. outs() << " (objc_image_info entends past the end of the section)\n";
  4770. } else
  4771. memcpy(&o, r, sizeof(struct objc_image_info32));
  4772. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4773. swapStruct(o);
  4774. outs() << " version " << o.version << "\n";
  4775. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4776. if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
  4777. outs() << " OBJC_IMAGE_IS_REPLACEMENT";
  4778. if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
  4779. outs() << " OBJC_IMAGE_SUPPORTS_GC";
  4780. swift_version = (o.flags >> 8) & 0xff;
  4781. if (swift_version != 0) {
  4782. if (swift_version == 1)
  4783. outs() << " Swift 1.0";
  4784. else if (swift_version == 2)
  4785. outs() << " Swift 1.1";
  4786. else
  4787. outs() << " unknown future Swift version (" << swift_version << ")";
  4788. }
  4789. outs() << "\n";
  4790. }
  4791. static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
  4792. uint32_t left, offset, p;
  4793. struct imageInfo_t o;
  4794. const char *r;
  4795. StringRef SectName;
  4796. S.getName(SectName);
  4797. DataRefImpl Ref = S.getRawDataRefImpl();
  4798. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4799. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4800. p = S.getAddress();
  4801. r = get_pointer_32(p, offset, left, S, info);
  4802. if (r == nullptr)
  4803. return;
  4804. memset(&o, '\0', sizeof(struct imageInfo_t));
  4805. if (left < sizeof(struct imageInfo_t)) {
  4806. memcpy(&o, r, left);
  4807. outs() << " (imageInfo entends past the end of the section)\n";
  4808. } else
  4809. memcpy(&o, r, sizeof(struct imageInfo_t));
  4810. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4811. swapStruct(o);
  4812. outs() << " version " << o.version << "\n";
  4813. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4814. if (o.flags & 0x1)
  4815. outs() << " F&C";
  4816. if (o.flags & 0x2)
  4817. outs() << " GC";
  4818. if (o.flags & 0x4)
  4819. outs() << " GC-only";
  4820. else
  4821. outs() << " RR";
  4822. outs() << "\n";
  4823. }
  4824. static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
  4825. SymbolAddressMap AddrMap;
  4826. if (verbose)
  4827. CreateSymbolAddressMap(O, &AddrMap);
  4828. std::vector<SectionRef> Sections;
  4829. for (const SectionRef &Section : O->sections()) {
  4830. StringRef SectName;
  4831. Section.getName(SectName);
  4832. Sections.push_back(Section);
  4833. }
  4834. struct DisassembleInfo info;
  4835. // Set up the block of info used by the Symbolizer call backs.
  4836. info.verbose = verbose;
  4837. info.O = O;
  4838. info.AddrMap = &AddrMap;
  4839. info.Sections = &Sections;
  4840. info.class_name = nullptr;
  4841. info.selector_name = nullptr;
  4842. info.method = nullptr;
  4843. info.demangled_name = nullptr;
  4844. info.bindtable = nullptr;
  4845. info.adrp_addr = 0;
  4846. info.adrp_inst = 0;
  4847. info.depth = 0;
  4848. SectionRef CL = get_section(O, "__OBJC2", "__class_list");
  4849. if (CL == SectionRef())
  4850. CL = get_section(O, "__DATA", "__objc_classlist");
  4851. info.S = CL;
  4852. walk_pointer_list_64("class", CL, O, &info, print_class64_t);
  4853. SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
  4854. if (CR == SectionRef())
  4855. CR = get_section(O, "__DATA", "__objc_classrefs");
  4856. info.S = CR;
  4857. walk_pointer_list_64("class refs", CR, O, &info, nullptr);
  4858. SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
  4859. if (SR == SectionRef())
  4860. SR = get_section(O, "__DATA", "__objc_superrefs");
  4861. info.S = SR;
  4862. walk_pointer_list_64("super refs", SR, O, &info, nullptr);
  4863. SectionRef CA = get_section(O, "__OBJC2", "__category_list");
  4864. if (CA == SectionRef())
  4865. CA = get_section(O, "__DATA", "__objc_catlist");
  4866. info.S = CA;
  4867. walk_pointer_list_64("category", CA, O, &info, print_category64_t);
  4868. SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
  4869. if (PL == SectionRef())
  4870. PL = get_section(O, "__DATA", "__objc_protolist");
  4871. info.S = PL;
  4872. walk_pointer_list_64("protocol", PL, O, &info, nullptr);
  4873. SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
  4874. if (MR == SectionRef())
  4875. MR = get_section(O, "__DATA", "__objc_msgrefs");
  4876. info.S = MR;
  4877. print_message_refs64(MR, &info);
  4878. SectionRef II = get_section(O, "__OBJC2", "__image_info");
  4879. if (II == SectionRef())
  4880. II = get_section(O, "__DATA", "__objc_imageinfo");
  4881. info.S = II;
  4882. print_image_info64(II, &info);
  4883. if (info.bindtable != nullptr)
  4884. delete info.bindtable;
  4885. }
  4886. static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
  4887. SymbolAddressMap AddrMap;
  4888. if (verbose)
  4889. CreateSymbolAddressMap(O, &AddrMap);
  4890. std::vector<SectionRef> Sections;
  4891. for (const SectionRef &Section : O->sections()) {
  4892. StringRef SectName;
  4893. Section.getName(SectName);
  4894. Sections.push_back(Section);
  4895. }
  4896. struct DisassembleInfo info;
  4897. // Set up the block of info used by the Symbolizer call backs.
  4898. info.verbose = verbose;
  4899. info.O = O;
  4900. info.AddrMap = &AddrMap;
  4901. info.Sections = &Sections;
  4902. info.class_name = nullptr;
  4903. info.selector_name = nullptr;
  4904. info.method = nullptr;
  4905. info.demangled_name = nullptr;
  4906. info.bindtable = nullptr;
  4907. info.adrp_addr = 0;
  4908. info.adrp_inst = 0;
  4909. const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
  4910. if (CL != SectionRef()) {
  4911. info.S = CL;
  4912. walk_pointer_list_32("class", CL, O, &info, print_class32_t);
  4913. } else {
  4914. const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
  4915. info.S = CL;
  4916. walk_pointer_list_32("class", CL, O, &info, print_class32_t);
  4917. }
  4918. const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
  4919. if (CR != SectionRef()) {
  4920. info.S = CR;
  4921. walk_pointer_list_32("class refs", CR, O, &info, nullptr);
  4922. } else {
  4923. const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
  4924. info.S = CR;
  4925. walk_pointer_list_32("class refs", CR, O, &info, nullptr);
  4926. }
  4927. const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
  4928. if (SR != SectionRef()) {
  4929. info.S = SR;
  4930. walk_pointer_list_32("super refs", SR, O, &info, nullptr);
  4931. } else {
  4932. const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
  4933. info.S = SR;
  4934. walk_pointer_list_32("super refs", SR, O, &info, nullptr);
  4935. }
  4936. const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
  4937. if (CA != SectionRef()) {
  4938. info.S = CA;
  4939. walk_pointer_list_32("category", CA, O, &info, print_category32_t);
  4940. } else {
  4941. const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
  4942. info.S = CA;
  4943. walk_pointer_list_32("category", CA, O, &info, print_category32_t);
  4944. }
  4945. const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
  4946. if (PL != SectionRef()) {
  4947. info.S = PL;
  4948. walk_pointer_list_32("protocol", PL, O, &info, nullptr);
  4949. } else {
  4950. const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
  4951. info.S = PL;
  4952. walk_pointer_list_32("protocol", PL, O, &info, nullptr);
  4953. }
  4954. const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
  4955. if (MR != SectionRef()) {
  4956. info.S = MR;
  4957. print_message_refs32(MR, &info);
  4958. } else {
  4959. const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
  4960. info.S = MR;
  4961. print_message_refs32(MR, &info);
  4962. }
  4963. const SectionRef II = get_section(O, "__OBJC2", "__image_info");
  4964. if (II != SectionRef()) {
  4965. info.S = II;
  4966. print_image_info32(II, &info);
  4967. } else {
  4968. const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
  4969. info.S = II;
  4970. print_image_info32(II, &info);
  4971. }
  4972. }
  4973. static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
  4974. uint32_t i, j, p, offset, xoffset, left, defs_left, def;
  4975. const char *r, *name, *defs;
  4976. struct objc_module_t module;
  4977. SectionRef S, xS;
  4978. struct objc_symtab_t symtab;
  4979. struct objc_class_t objc_class;
  4980. struct objc_category_t objc_category;
  4981. outs() << "Objective-C segment\n";
  4982. S = get_section(O, "__OBJC", "__module_info");
  4983. if (S == SectionRef())
  4984. return false;
  4985. SymbolAddressMap AddrMap;
  4986. if (verbose)
  4987. CreateSymbolAddressMap(O, &AddrMap);
  4988. std::vector<SectionRef> Sections;
  4989. for (const SectionRef &Section : O->sections()) {
  4990. StringRef SectName;
  4991. Section.getName(SectName);
  4992. Sections.push_back(Section);
  4993. }
  4994. struct DisassembleInfo info;
  4995. // Set up the block of info used by the Symbolizer call backs.
  4996. info.verbose = verbose;
  4997. info.O = O;
  4998. info.AddrMap = &AddrMap;
  4999. info.Sections = &Sections;
  5000. info.class_name = nullptr;
  5001. info.selector_name = nullptr;
  5002. info.method = nullptr;
  5003. info.demangled_name = nullptr;
  5004. info.bindtable = nullptr;
  5005. info.adrp_addr = 0;
  5006. info.adrp_inst = 0;
  5007. for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
  5008. p = S.getAddress() + i;
  5009. r = get_pointer_32(p, offset, left, S, &info, true);
  5010. if (r == nullptr)
  5011. return true;
  5012. memset(&module, '\0', sizeof(struct objc_module_t));
  5013. if (left < sizeof(struct objc_module_t)) {
  5014. memcpy(&module, r, left);
  5015. outs() << " (module extends past end of __module_info section)\n";
  5016. } else
  5017. memcpy(&module, r, sizeof(struct objc_module_t));
  5018. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5019. swapStruct(module);
  5020. outs() << "Module " << format("0x%" PRIx32, p) << "\n";
  5021. outs() << " version " << module.version << "\n";
  5022. outs() << " size " << module.size << "\n";
  5023. outs() << " name ";
  5024. name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
  5025. if (name != nullptr)
  5026. outs() << format("%.*s", left, name);
  5027. else
  5028. outs() << format("0x%08" PRIx32, module.name)
  5029. << "(not in an __OBJC section)";
  5030. outs() << "\n";
  5031. r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
  5032. if (module.symtab == 0 || r == nullptr) {
  5033. outs() << " symtab " << format("0x%08" PRIx32, module.symtab)
  5034. << " (not in an __OBJC section)\n";
  5035. continue;
  5036. }
  5037. outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
  5038. memset(&symtab, '\0', sizeof(struct objc_symtab_t));
  5039. defs_left = 0;
  5040. defs = nullptr;
  5041. if (left < sizeof(struct objc_symtab_t)) {
  5042. memcpy(&symtab, r, left);
  5043. outs() << "\tsymtab extends past end of an __OBJC section)\n";
  5044. } else {
  5045. memcpy(&symtab, r, sizeof(struct objc_symtab_t));
  5046. if (left > sizeof(struct objc_symtab_t)) {
  5047. defs_left = left - sizeof(struct objc_symtab_t);
  5048. defs = r + sizeof(struct objc_symtab_t);
  5049. }
  5050. }
  5051. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5052. swapStruct(symtab);
  5053. outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
  5054. r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
  5055. outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
  5056. if (r == nullptr)
  5057. outs() << " (not in an __OBJC section)";
  5058. outs() << "\n";
  5059. outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
  5060. outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
  5061. if (symtab.cls_def_cnt > 0)
  5062. outs() << "\tClass Definitions\n";
  5063. for (j = 0; j < symtab.cls_def_cnt; j++) {
  5064. if ((j + 1) * sizeof(uint32_t) > defs_left) {
  5065. outs() << "\t(remaining class defs entries entends past the end of the "
  5066. << "section)\n";
  5067. break;
  5068. }
  5069. memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
  5070. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5071. sys::swapByteOrder(def);
  5072. r = get_pointer_32(def, xoffset, left, xS, &info, true);
  5073. outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
  5074. if (r != nullptr) {
  5075. if (left > sizeof(struct objc_class_t)) {
  5076. outs() << "\n";
  5077. memcpy(&objc_class, r, sizeof(struct objc_class_t));
  5078. } else {
  5079. outs() << " (entends past the end of the section)\n";
  5080. memset(&objc_class, '\0', sizeof(struct objc_class_t));
  5081. memcpy(&objc_class, r, left);
  5082. }
  5083. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5084. swapStruct(objc_class);
  5085. print_objc_class_t(&objc_class, &info);
  5086. } else {
  5087. outs() << "(not in an __OBJC section)\n";
  5088. }
  5089. if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
  5090. outs() << "\tMeta Class";
  5091. r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
  5092. if (r != nullptr) {
  5093. if (left > sizeof(struct objc_class_t)) {
  5094. outs() << "\n";
  5095. memcpy(&objc_class, r, sizeof(struct objc_class_t));
  5096. } else {
  5097. outs() << " (entends past the end of the section)\n";
  5098. memset(&objc_class, '\0', sizeof(struct objc_class_t));
  5099. memcpy(&objc_class, r, left);
  5100. }
  5101. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5102. swapStruct(objc_class);
  5103. print_objc_class_t(&objc_class, &info);
  5104. } else {
  5105. outs() << "(not in an __OBJC section)\n";
  5106. }
  5107. }
  5108. }
  5109. if (symtab.cat_def_cnt > 0)
  5110. outs() << "\tCategory Definitions\n";
  5111. for (j = 0; j < symtab.cat_def_cnt; j++) {
  5112. if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
  5113. outs() << "\t(remaining category defs entries entends past the end of "
  5114. << "the section)\n";
  5115. break;
  5116. }
  5117. memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
  5118. sizeof(uint32_t));
  5119. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5120. sys::swapByteOrder(def);
  5121. r = get_pointer_32(def, xoffset, left, xS, &info, true);
  5122. outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
  5123. << format("0x%08" PRIx32, def);
  5124. if (r != nullptr) {
  5125. if (left > sizeof(struct objc_category_t)) {
  5126. outs() << "\n";
  5127. memcpy(&objc_category, r, sizeof(struct objc_category_t));
  5128. } else {
  5129. outs() << " (entends past the end of the section)\n";
  5130. memset(&objc_category, '\0', sizeof(struct objc_category_t));
  5131. memcpy(&objc_category, r, left);
  5132. }
  5133. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5134. swapStruct(objc_category);
  5135. print_objc_objc_category_t(&objc_category, &info);
  5136. } else {
  5137. outs() << "(not in an __OBJC section)\n";
  5138. }
  5139. }
  5140. }
  5141. const SectionRef II = get_section(O, "__OBJC", "__image_info");
  5142. if (II != SectionRef())
  5143. print_image_info(II, &info);
  5144. return true;
  5145. }
  5146. static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
  5147. uint32_t size, uint32_t addr) {
  5148. SymbolAddressMap AddrMap;
  5149. CreateSymbolAddressMap(O, &AddrMap);
  5150. std::vector<SectionRef> Sections;
  5151. for (const SectionRef &Section : O->sections()) {
  5152. StringRef SectName;
  5153. Section.getName(SectName);
  5154. Sections.push_back(Section);
  5155. }
  5156. struct DisassembleInfo info;
  5157. // Set up the block of info used by the Symbolizer call backs.
  5158. info.verbose = true;
  5159. info.O = O;
  5160. info.AddrMap = &AddrMap;
  5161. info.Sections = &Sections;
  5162. info.class_name = nullptr;
  5163. info.selector_name = nullptr;
  5164. info.method = nullptr;
  5165. info.demangled_name = nullptr;
  5166. info.bindtable = nullptr;
  5167. info.adrp_addr = 0;
  5168. info.adrp_inst = 0;
  5169. const char *p;
  5170. struct objc_protocol_t protocol;
  5171. uint32_t left, paddr;
  5172. for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
  5173. memset(&protocol, '\0', sizeof(struct objc_protocol_t));
  5174. left = size - (p - sect);
  5175. if (left < sizeof(struct objc_protocol_t)) {
  5176. outs() << "Protocol extends past end of __protocol section\n";
  5177. memcpy(&protocol, p, left);
  5178. } else
  5179. memcpy(&protocol, p, sizeof(struct objc_protocol_t));
  5180. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5181. swapStruct(protocol);
  5182. paddr = addr + (p - sect);
  5183. outs() << "Protocol " << format("0x%" PRIx32, paddr);
  5184. if (print_protocol(paddr, 0, &info))
  5185. outs() << "(not in an __OBJC section)\n";
  5186. }
  5187. }
  5188. #ifdef HAVE_LIBXAR
  5189. inline void swapStruct(struct xar_header &xar) {
  5190. sys::swapByteOrder(xar.magic);
  5191. sys::swapByteOrder(xar.size);
  5192. sys::swapByteOrder(xar.version);
  5193. sys::swapByteOrder(xar.toc_length_compressed);
  5194. sys::swapByteOrder(xar.toc_length_uncompressed);
  5195. sys::swapByteOrder(xar.cksum_alg);
  5196. }
  5197. static void PrintModeVerbose(uint32_t mode) {
  5198. switch(mode & S_IFMT){
  5199. case S_IFDIR:
  5200. outs() << "d";
  5201. break;
  5202. case S_IFCHR:
  5203. outs() << "c";
  5204. break;
  5205. case S_IFBLK:
  5206. outs() << "b";
  5207. break;
  5208. case S_IFREG:
  5209. outs() << "-";
  5210. break;
  5211. case S_IFLNK:
  5212. outs() << "l";
  5213. break;
  5214. case S_IFSOCK:
  5215. outs() << "s";
  5216. break;
  5217. default:
  5218. outs() << "?";
  5219. break;
  5220. }
  5221. /* owner permissions */
  5222. if(mode & S_IREAD)
  5223. outs() << "r";
  5224. else
  5225. outs() << "-";
  5226. if(mode & S_IWRITE)
  5227. outs() << "w";
  5228. else
  5229. outs() << "-";
  5230. if(mode & S_ISUID)
  5231. outs() << "s";
  5232. else if(mode & S_IEXEC)
  5233. outs() << "x";
  5234. else
  5235. outs() << "-";
  5236. /* group permissions */
  5237. if(mode & (S_IREAD >> 3))
  5238. outs() << "r";
  5239. else
  5240. outs() << "-";
  5241. if(mode & (S_IWRITE >> 3))
  5242. outs() << "w";
  5243. else
  5244. outs() << "-";
  5245. if(mode & S_ISGID)
  5246. outs() << "s";
  5247. else if(mode & (S_IEXEC >> 3))
  5248. outs() << "x";
  5249. else
  5250. outs() << "-";
  5251. /* other permissions */
  5252. if(mode & (S_IREAD >> 6))
  5253. outs() << "r";
  5254. else
  5255. outs() << "-";
  5256. if(mode & (S_IWRITE >> 6))
  5257. outs() << "w";
  5258. else
  5259. outs() << "-";
  5260. if(mode & S_ISVTX)
  5261. outs() << "t";
  5262. else if(mode & (S_IEXEC >> 6))
  5263. outs() << "x";
  5264. else
  5265. outs() << "-";
  5266. }
  5267. static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
  5268. xar_iter_t xi;
  5269. xar_file_t xf;
  5270. xar_iter_t xp;
  5271. const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
  5272. char *endp;
  5273. uint32_t mode_value;
  5274. xi = xar_iter_new();
  5275. if (!xi) {
  5276. errs() << "Can't obtain an xar iterator for xar archive "
  5277. << XarFilename << "\n";
  5278. return;
  5279. }
  5280. // Go through the xar's files.
  5281. for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
  5282. xp = xar_iter_new();
  5283. if(!xp){
  5284. errs() << "Can't obtain an xar iterator for xar archive "
  5285. << XarFilename << "\n";
  5286. return;
  5287. }
  5288. type = nullptr;
  5289. mode = nullptr;
  5290. user = nullptr;
  5291. group = nullptr;
  5292. size = nullptr;
  5293. mtime = nullptr;
  5294. name = nullptr;
  5295. for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
  5296. const char *val = nullptr;
  5297. xar_prop_get(xf, key, &val);
  5298. #if 0 // Useful for debugging.
  5299. outs() << "key: " << key << " value: " << val << "\n";
  5300. #endif
  5301. if(strcmp(key, "type") == 0)
  5302. type = val;
  5303. if(strcmp(key, "mode") == 0)
  5304. mode = val;
  5305. if(strcmp(key, "user") == 0)
  5306. user = val;
  5307. if(strcmp(key, "group") == 0)
  5308. group = val;
  5309. if(strcmp(key, "data/size") == 0)
  5310. size = val;
  5311. if(strcmp(key, "mtime") == 0)
  5312. mtime = val;
  5313. if(strcmp(key, "name") == 0)
  5314. name = val;
  5315. }
  5316. if(mode != nullptr){
  5317. mode_value = strtoul(mode, &endp, 8);
  5318. if(*endp != '\0')
  5319. outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
  5320. if(strcmp(type, "file") == 0)
  5321. mode_value |= S_IFREG;
  5322. PrintModeVerbose(mode_value);
  5323. outs() << " ";
  5324. }
  5325. if(user != nullptr)
  5326. outs() << format("%10s/", user);
  5327. if(group != nullptr)
  5328. outs() << format("%-10s ", group);
  5329. if(size != nullptr)
  5330. outs() << format("%7s ", size);
  5331. if(mtime != nullptr){
  5332. for(m = mtime; *m != 'T' && *m != '\0'; m++)
  5333. outs() << *m;
  5334. if(*m == 'T')
  5335. m++;
  5336. outs() << " ";
  5337. for( ; *m != 'Z' && *m != '\0'; m++)
  5338. outs() << *m;
  5339. outs() << " ";
  5340. }
  5341. if(name != nullptr)
  5342. outs() << name;
  5343. outs() << "\n";
  5344. }
  5345. }
  5346. static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
  5347. uint32_t size, bool verbose,
  5348. bool PrintXarHeader, bool PrintXarFileHeaders,
  5349. std::string XarMemberName) {
  5350. if(size < sizeof(struct xar_header)) {
  5351. outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
  5352. "of struct xar_header)\n";
  5353. return;
  5354. }
  5355. struct xar_header XarHeader;
  5356. memcpy(&XarHeader, sect, sizeof(struct xar_header));
  5357. if (sys::IsLittleEndianHost)
  5358. swapStruct(XarHeader);
  5359. if (PrintXarHeader) {
  5360. if (!XarMemberName.empty())
  5361. outs() << "In xar member " << XarMemberName << ": ";
  5362. else
  5363. outs() << "For (__LLVM,__bundle) section: ";
  5364. outs() << "xar header\n";
  5365. if (XarHeader.magic == XAR_HEADER_MAGIC)
  5366. outs() << " magic XAR_HEADER_MAGIC\n";
  5367. else
  5368. outs() << " magic "
  5369. << format_hex(XarHeader.magic, 10, true)
  5370. << " (not XAR_HEADER_MAGIC)\n";
  5371. outs() << " size " << XarHeader.size << "\n";
  5372. outs() << " version " << XarHeader.version << "\n";
  5373. outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
  5374. << "\n";
  5375. outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
  5376. << "\n";
  5377. outs() << " cksum_alg ";
  5378. switch (XarHeader.cksum_alg) {
  5379. case XAR_CKSUM_NONE:
  5380. outs() << "XAR_CKSUM_NONE\n";
  5381. break;
  5382. case XAR_CKSUM_SHA1:
  5383. outs() << "XAR_CKSUM_SHA1\n";
  5384. break;
  5385. case XAR_CKSUM_MD5:
  5386. outs() << "XAR_CKSUM_MD5\n";
  5387. break;
  5388. #ifdef XAR_CKSUM_SHA256
  5389. case XAR_CKSUM_SHA256:
  5390. outs() << "XAR_CKSUM_SHA256\n";
  5391. break;
  5392. #endif
  5393. #ifdef XAR_CKSUM_SHA512
  5394. case XAR_CKSUM_SHA512:
  5395. outs() << "XAR_CKSUM_SHA512\n";
  5396. break;
  5397. #endif
  5398. default:
  5399. outs() << XarHeader.cksum_alg << "\n";
  5400. }
  5401. }
  5402. SmallString<128> XarFilename;
  5403. int FD;
  5404. std::error_code XarEC =
  5405. sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
  5406. if (XarEC) {
  5407. errs() << XarEC.message() << "\n";
  5408. return;
  5409. }
  5410. tool_output_file XarFile(XarFilename, FD);
  5411. raw_fd_ostream &XarOut = XarFile.os();
  5412. StringRef XarContents(sect, size);
  5413. XarOut << XarContents;
  5414. XarOut.close();
  5415. if (XarOut.has_error())
  5416. return;
  5417. xar_t xar = xar_open(XarFilename.c_str(), READ);
  5418. if (!xar) {
  5419. errs() << "Can't create temporary xar archive " << XarFilename << "\n";
  5420. return;
  5421. }
  5422. SmallString<128> TocFilename;
  5423. std::error_code TocEC =
  5424. sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
  5425. if (TocEC) {
  5426. errs() << TocEC.message() << "\n";
  5427. return;
  5428. }
  5429. xar_serialize(xar, TocFilename.c_str());
  5430. if (PrintXarFileHeaders) {
  5431. if (!XarMemberName.empty())
  5432. outs() << "In xar member " << XarMemberName << ": ";
  5433. else
  5434. outs() << "For (__LLVM,__bundle) section: ";
  5435. outs() << "xar archive files:\n";
  5436. PrintXarFilesSummary(XarFilename.c_str(), xar);
  5437. }
  5438. ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
  5439. MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
  5440. if (std::error_code EC = FileOrErr.getError()) {
  5441. errs() << EC.message() << "\n";
  5442. return;
  5443. }
  5444. std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
  5445. if (!XarMemberName.empty())
  5446. outs() << "In xar member " << XarMemberName << ": ";
  5447. else
  5448. outs() << "For (__LLVM,__bundle) section: ";
  5449. outs() << "xar table of contents:\n";
  5450. outs() << Buffer->getBuffer() << "\n";
  5451. // TODO: Go through the xar's files.
  5452. xar_iter_t xi = xar_iter_new();
  5453. if(!xi){
  5454. errs() << "Can't obtain an xar iterator for xar archive "
  5455. << XarFilename.c_str() << "\n";
  5456. xar_close(xar);
  5457. return;
  5458. }
  5459. for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
  5460. const char *key;
  5461. xar_iter_t xp;
  5462. const char *member_name, *member_type, *member_size_string;
  5463. size_t member_size;
  5464. xp = xar_iter_new();
  5465. if(!xp){
  5466. errs() << "Can't obtain an xar iterator for xar archive "
  5467. << XarFilename.c_str() << "\n";
  5468. xar_close(xar);
  5469. return;
  5470. }
  5471. member_name = NULL;
  5472. member_type = NULL;
  5473. member_size_string = NULL;
  5474. for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
  5475. const char *val = nullptr;
  5476. xar_prop_get(xf, key, &val);
  5477. #if 0 // Useful for debugging.
  5478. outs() << "key: " << key << " value: " << val << "\n";
  5479. #endif
  5480. if(strcmp(key, "name") == 0)
  5481. member_name = val;
  5482. if(strcmp(key, "type") == 0)
  5483. member_type = val;
  5484. if(strcmp(key, "data/size") == 0)
  5485. member_size_string = val;
  5486. }
  5487. /*
  5488. * If we find a file with a name, date/size and type properties
  5489. * and with the type being "file" see if that is a xar file.
  5490. */
  5491. if (member_name != NULL && member_type != NULL &&
  5492. strcmp(member_type, "file") == 0 &&
  5493. member_size_string != NULL){
  5494. // Extract the file into a buffer.
  5495. char *endptr;
  5496. member_size = strtoul(member_size_string, &endptr, 10);
  5497. if (*endptr == '\0' && member_size != 0) {
  5498. char *buffer = (char *) ::operator new (member_size);
  5499. if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
  5500. #if 0 // Useful for debugging.
  5501. outs() << "xar member: " << member_name << " extracted\n";
  5502. #endif
  5503. // Set the XarMemberName we want to see printed in the header.
  5504. std::string OldXarMemberName;
  5505. // If XarMemberName is already set this is nested. So
  5506. // save the old name and create the nested name.
  5507. if (!XarMemberName.empty()) {
  5508. OldXarMemberName = XarMemberName;
  5509. XarMemberName =
  5510. (Twine("[") + XarMemberName + "]" + member_name).str();
  5511. } else {
  5512. OldXarMemberName = "";
  5513. XarMemberName = member_name;
  5514. }
  5515. // See if this is could be a xar file (nested).
  5516. if (member_size >= sizeof(struct xar_header)) {
  5517. #if 0 // Useful for debugging.
  5518. outs() << "could be a xar file: " << member_name << "\n";
  5519. #endif
  5520. memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
  5521. if (sys::IsLittleEndianHost)
  5522. swapStruct(XarHeader);
  5523. if(XarHeader.magic == XAR_HEADER_MAGIC)
  5524. DumpBitcodeSection(O, buffer, member_size, verbose,
  5525. PrintXarHeader, PrintXarFileHeaders,
  5526. XarMemberName);
  5527. }
  5528. XarMemberName = OldXarMemberName;
  5529. }
  5530. delete buffer;
  5531. }
  5532. }
  5533. xar_iter_free(xp);
  5534. }
  5535. xar_close(xar);
  5536. }
  5537. #endif // defined(HAVE_LIBXAR)
  5538. static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
  5539. if (O->is64Bit())
  5540. printObjc2_64bit_MetaData(O, verbose);
  5541. else {
  5542. MachO::mach_header H;
  5543. H = O->getHeader();
  5544. if (H.cputype == MachO::CPU_TYPE_ARM)
  5545. printObjc2_32bit_MetaData(O, verbose);
  5546. else {
  5547. // This is the 32-bit non-arm cputype case. Which is normally
  5548. // the first Objective-C ABI. But it may be the case of a
  5549. // binary for the iOS simulator which is the second Objective-C
  5550. // ABI. In that case printObjc1_32bit_MetaData() will determine that
  5551. // and return false.
  5552. if (!printObjc1_32bit_MetaData(O, verbose))
  5553. printObjc2_32bit_MetaData(O, verbose);
  5554. }
  5555. }
  5556. }
  5557. // GuessLiteralPointer returns a string which for the item in the Mach-O file
  5558. // for the address passed in as ReferenceValue for printing as a comment with
  5559. // the instruction and also returns the corresponding type of that item
  5560. // indirectly through ReferenceType.
  5561. //
  5562. // If ReferenceValue is an address of literal cstring then a pointer to the
  5563. // cstring is returned and ReferenceType is set to
  5564. // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
  5565. //
  5566. // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
  5567. // Class ref that name is returned and the ReferenceType is set accordingly.
  5568. //
  5569. // Lastly, literals which are Symbol address in a literal pool are looked for
  5570. // and if found the symbol name is returned and ReferenceType is set to
  5571. // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
  5572. //
  5573. // If there is no item in the Mach-O file for the address passed in as
  5574. // ReferenceValue nullptr is returned and ReferenceType is unchanged.
  5575. static const char *GuessLiteralPointer(uint64_t ReferenceValue,
  5576. uint64_t ReferencePC,
  5577. uint64_t *ReferenceType,
  5578. struct DisassembleInfo *info) {
  5579. // First see if there is an external relocation entry at the ReferencePC.
  5580. if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
  5581. uint64_t sect_addr = info->S.getAddress();
  5582. uint64_t sect_offset = ReferencePC - sect_addr;
  5583. bool reloc_found = false;
  5584. DataRefImpl Rel;
  5585. MachO::any_relocation_info RE;
  5586. bool isExtern = false;
  5587. SymbolRef Symbol;
  5588. for (const RelocationRef &Reloc : info->S.relocations()) {
  5589. uint64_t RelocOffset = Reloc.getOffset();
  5590. if (RelocOffset == sect_offset) {
  5591. Rel = Reloc.getRawDataRefImpl();
  5592. RE = info->O->getRelocation(Rel);
  5593. if (info->O->isRelocationScattered(RE))
  5594. continue;
  5595. isExtern = info->O->getPlainRelocationExternal(RE);
  5596. if (isExtern) {
  5597. symbol_iterator RelocSym = Reloc.getSymbol();
  5598. Symbol = *RelocSym;
  5599. }
  5600. reloc_found = true;
  5601. break;
  5602. }
  5603. }
  5604. // If there is an external relocation entry for a symbol in a section
  5605. // then used that symbol's value for the value of the reference.
  5606. if (reloc_found && isExtern) {
  5607. if (info->O->getAnyRelocationPCRel(RE)) {
  5608. unsigned Type = info->O->getAnyRelocationType(RE);
  5609. if (Type == MachO::X86_64_RELOC_SIGNED) {
  5610. ReferenceValue = Symbol.getValue();
  5611. }
  5612. }
  5613. }
  5614. }
  5615. // Look for literals such as Objective-C CFStrings refs, Selector refs,
  5616. // Message refs and Class refs.
  5617. bool classref, selref, msgref, cfstring;
  5618. uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
  5619. selref, msgref, cfstring);
  5620. if (classref && pointer_value == 0) {
  5621. // Note the ReferenceValue is a pointer into the __objc_classrefs section.
  5622. // And the pointer_value in that section is typically zero as it will be
  5623. // set by dyld as part of the "bind information".
  5624. const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
  5625. if (name != nullptr) {
  5626. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
  5627. const char *class_name = strrchr(name, '$');
  5628. if (class_name != nullptr && class_name[1] == '_' &&
  5629. class_name[2] != '\0') {
  5630. info->class_name = class_name + 2;
  5631. return name;
  5632. }
  5633. }
  5634. }
  5635. if (classref) {
  5636. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
  5637. const char *name =
  5638. get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
  5639. if (name != nullptr)
  5640. info->class_name = name;
  5641. else
  5642. name = "bad class ref";
  5643. return name;
  5644. }
  5645. if (cfstring) {
  5646. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
  5647. const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
  5648. return name;
  5649. }
  5650. if (selref && pointer_value == 0)
  5651. pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
  5652. if (pointer_value != 0)
  5653. ReferenceValue = pointer_value;
  5654. const char *name = GuessCstringPointer(ReferenceValue, info);
  5655. if (name) {
  5656. if (pointer_value != 0 && selref) {
  5657. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
  5658. info->selector_name = name;
  5659. } else if (pointer_value != 0 && msgref) {
  5660. info->class_name = nullptr;
  5661. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
  5662. info->selector_name = name;
  5663. } else
  5664. *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
  5665. return name;
  5666. }
  5667. // Lastly look for an indirect symbol with this ReferenceValue which is in
  5668. // a literal pool. If found return that symbol name.
  5669. name = GuessIndirectSymbol(ReferenceValue, info);
  5670. if (name) {
  5671. *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
  5672. return name;
  5673. }
  5674. return nullptr;
  5675. }
  5676. // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
  5677. // the Symbolizer. It looks up the ReferenceValue using the info passed via the
  5678. // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
  5679. // is created and returns the symbol name that matches the ReferenceValue or
  5680. // nullptr if none. The ReferenceType is passed in for the IN type of
  5681. // reference the instruction is making from the values in defined in the header
  5682. // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific
  5683. // Out type and the ReferenceName will also be set which is added as a comment
  5684. // to the disassembled instruction.
  5685. //
  5686. // If the symbol name is a C++ mangled name then the demangled name is
  5687. // returned through ReferenceName and ReferenceType is set to
  5688. // LLVMDisassembler_ReferenceType_DeMangled_Name .
  5689. //
  5690. // When this is called to get a symbol name for a branch target then the
  5691. // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
  5692. // SymbolValue will be looked for in the indirect symbol table to determine if
  5693. // it is an address for a symbol stub. If so then the symbol name for that
  5694. // stub is returned indirectly through ReferenceName and then ReferenceType is
  5695. // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
  5696. //
  5697. // When this is called with an value loaded via a PC relative load then
  5698. // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
  5699. // SymbolValue is checked to be an address of literal pointer, symbol pointer,
  5700. // or an Objective-C meta data reference. If so the output ReferenceType is
  5701. // set to correspond to that as well as setting the ReferenceName.
  5702. static const char *SymbolizerSymbolLookUp(void *DisInfo,
  5703. uint64_t ReferenceValue,
  5704. uint64_t *ReferenceType,
  5705. uint64_t ReferencePC,
  5706. const char **ReferenceName) {
  5707. struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
  5708. // If no verbose symbolic information is wanted then just return nullptr.
  5709. if (!info->verbose) {
  5710. *ReferenceName = nullptr;
  5711. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5712. return nullptr;
  5713. }
  5714. const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
  5715. if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
  5716. *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
  5717. if (*ReferenceName != nullptr) {
  5718. method_reference(info, ReferenceType, ReferenceName);
  5719. if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
  5720. *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
  5721. } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
  5722. if (info->demangled_name != nullptr)
  5723. free(info->demangled_name);
  5724. int status;
  5725. info->demangled_name =
  5726. itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
  5727. if (info->demangled_name != nullptr) {
  5728. *ReferenceName = info->demangled_name;
  5729. *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
  5730. } else
  5731. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5732. } else
  5733. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5734. } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
  5735. *ReferenceName =
  5736. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5737. if (*ReferenceName)
  5738. method_reference(info, ReferenceType, ReferenceName);
  5739. else
  5740. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5741. // If this is arm64 and the reference is an adrp instruction save the
  5742. // instruction, passed in ReferenceValue and the address of the instruction
  5743. // for use later if we see and add immediate instruction.
  5744. } else if (info->O->getArch() == Triple::aarch64 &&
  5745. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
  5746. info->adrp_inst = ReferenceValue;
  5747. info->adrp_addr = ReferencePC;
  5748. SymbolName = nullptr;
  5749. *ReferenceName = nullptr;
  5750. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5751. // If this is arm64 and reference is an add immediate instruction and we
  5752. // have
  5753. // seen an adrp instruction just before it and the adrp's Xd register
  5754. // matches
  5755. // this add's Xn register reconstruct the value being referenced and look to
  5756. // see if it is a literal pointer. Note the add immediate instruction is
  5757. // passed in ReferenceValue.
  5758. } else if (info->O->getArch() == Triple::aarch64 &&
  5759. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
  5760. ReferencePC - 4 == info->adrp_addr &&
  5761. (info->adrp_inst & 0x9f000000) == 0x90000000 &&
  5762. (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
  5763. uint32_t addxri_inst;
  5764. uint64_t adrp_imm, addxri_imm;
  5765. adrp_imm =
  5766. ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
  5767. if (info->adrp_inst & 0x0200000)
  5768. adrp_imm |= 0xfffffffffc000000LL;
  5769. addxri_inst = ReferenceValue;
  5770. addxri_imm = (addxri_inst >> 10) & 0xfff;
  5771. if (((addxri_inst >> 22) & 0x3) == 1)
  5772. addxri_imm <<= 12;
  5773. ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
  5774. (adrp_imm << 12) + addxri_imm;
  5775. *ReferenceName =
  5776. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5777. if (*ReferenceName == nullptr)
  5778. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5779. // If this is arm64 and the reference is a load register instruction and we
  5780. // have seen an adrp instruction just before it and the adrp's Xd register
  5781. // matches this add's Xn register reconstruct the value being referenced and
  5782. // look to see if it is a literal pointer. Note the load register
  5783. // instruction is passed in ReferenceValue.
  5784. } else if (info->O->getArch() == Triple::aarch64 &&
  5785. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
  5786. ReferencePC - 4 == info->adrp_addr &&
  5787. (info->adrp_inst & 0x9f000000) == 0x90000000 &&
  5788. (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
  5789. uint32_t ldrxui_inst;
  5790. uint64_t adrp_imm, ldrxui_imm;
  5791. adrp_imm =
  5792. ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
  5793. if (info->adrp_inst & 0x0200000)
  5794. adrp_imm |= 0xfffffffffc000000LL;
  5795. ldrxui_inst = ReferenceValue;
  5796. ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
  5797. ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
  5798. (adrp_imm << 12) + (ldrxui_imm << 3);
  5799. *ReferenceName =
  5800. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5801. if (*ReferenceName == nullptr)
  5802. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5803. }
  5804. // If this arm64 and is an load register (PC-relative) instruction the
  5805. // ReferenceValue is the PC plus the immediate value.
  5806. else if (info->O->getArch() == Triple::aarch64 &&
  5807. (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
  5808. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
  5809. *ReferenceName =
  5810. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5811. if (*ReferenceName == nullptr)
  5812. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5813. } else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
  5814. if (info->demangled_name != nullptr)
  5815. free(info->demangled_name);
  5816. int status;
  5817. info->demangled_name =
  5818. itaniumDemangle(SymbolName + 1, nullptr, nullptr, &status);
  5819. if (info->demangled_name != nullptr) {
  5820. *ReferenceName = info->demangled_name;
  5821. *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
  5822. }
  5823. }
  5824. else {
  5825. *ReferenceName = nullptr;
  5826. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5827. }
  5828. return SymbolName;
  5829. }
  5830. /// \brief Emits the comments that are stored in the CommentStream.
  5831. /// Each comment in the CommentStream must end with a newline.
  5832. static void emitComments(raw_svector_ostream &CommentStream,
  5833. SmallString<128> &CommentsToEmit,
  5834. formatted_raw_ostream &FormattedOS,
  5835. const MCAsmInfo &MAI) {
  5836. // Flush the stream before taking its content.
  5837. StringRef Comments = CommentsToEmit.str();
  5838. // Get the default information for printing a comment.
  5839. StringRef CommentBegin = MAI.getCommentString();
  5840. unsigned CommentColumn = MAI.getCommentColumn();
  5841. bool IsFirst = true;
  5842. while (!Comments.empty()) {
  5843. if (!IsFirst)
  5844. FormattedOS << '\n';
  5845. // Emit a line of comments.
  5846. FormattedOS.PadToColumn(CommentColumn);
  5847. size_t Position = Comments.find('\n');
  5848. FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
  5849. // Move after the newline character.
  5850. Comments = Comments.substr(Position + 1);
  5851. IsFirst = false;
  5852. }
  5853. FormattedOS.flush();
  5854. // Tell the comment stream that the vector changed underneath it.
  5855. CommentsToEmit.clear();
  5856. }
  5857. static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
  5858. StringRef DisSegName, StringRef DisSectName) {
  5859. const char *McpuDefault = nullptr;
  5860. const Target *ThumbTarget = nullptr;
  5861. const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
  5862. if (!TheTarget) {
  5863. // GetTarget prints out stuff.
  5864. return;
  5865. }
  5866. if (MCPU.empty() && McpuDefault)
  5867. MCPU = McpuDefault;
  5868. std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
  5869. std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
  5870. if (ThumbTarget)
  5871. ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
  5872. // Package up features to be passed to target/subtarget
  5873. std::string FeaturesStr;
  5874. if (MAttrs.size()) {
  5875. SubtargetFeatures Features;
  5876. for (unsigned i = 0; i != MAttrs.size(); ++i)
  5877. Features.AddFeature(MAttrs[i]);
  5878. FeaturesStr = Features.getString();
  5879. }
  5880. // Set up disassembler.
  5881. std::unique_ptr<const MCRegisterInfo> MRI(
  5882. TheTarget->createMCRegInfo(TripleName));
  5883. std::unique_ptr<const MCAsmInfo> AsmInfo(
  5884. TheTarget->createMCAsmInfo(*MRI, TripleName));
  5885. std::unique_ptr<const MCSubtargetInfo> STI(
  5886. TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
  5887. MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
  5888. std::unique_ptr<MCDisassembler> DisAsm(
  5889. TheTarget->createMCDisassembler(*STI, Ctx));
  5890. std::unique_ptr<MCSymbolizer> Symbolizer;
  5891. struct DisassembleInfo SymbolizerInfo;
  5892. std::unique_ptr<MCRelocationInfo> RelInfo(
  5893. TheTarget->createMCRelocationInfo(TripleName, Ctx));
  5894. if (RelInfo) {
  5895. Symbolizer.reset(TheTarget->createMCSymbolizer(
  5896. TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
  5897. &SymbolizerInfo, &Ctx, std::move(RelInfo)));
  5898. DisAsm->setSymbolizer(std::move(Symbolizer));
  5899. }
  5900. int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
  5901. std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
  5902. Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
  5903. // Set the display preference for hex vs. decimal immediates.
  5904. IP->setPrintImmHex(PrintImmHex);
  5905. // Comment stream and backing vector.
  5906. SmallString<128> CommentsToEmit;
  5907. raw_svector_ostream CommentStream(CommentsToEmit);
  5908. // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
  5909. // if it is done then arm64 comments for string literals don't get printed
  5910. // and some constant get printed instead and not setting it causes intel
  5911. // (32-bit and 64-bit) comments printed with different spacing before the
  5912. // comment causing different diffs with the 'C' disassembler library API.
  5913. // IP->setCommentStream(CommentStream);
  5914. if (!AsmInfo || !STI || !DisAsm || !IP) {
  5915. errs() << "error: couldn't initialize disassembler for target "
  5916. << TripleName << '\n';
  5917. return;
  5918. }
  5919. // Set up separate thumb disassembler if needed.
  5920. std::unique_ptr<const MCRegisterInfo> ThumbMRI;
  5921. std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
  5922. std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
  5923. std::unique_ptr<MCDisassembler> ThumbDisAsm;
  5924. std::unique_ptr<MCInstPrinter> ThumbIP;
  5925. std::unique_ptr<MCContext> ThumbCtx;
  5926. std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
  5927. struct DisassembleInfo ThumbSymbolizerInfo;
  5928. std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
  5929. if (ThumbTarget) {
  5930. ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
  5931. ThumbAsmInfo.reset(
  5932. ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
  5933. ThumbSTI.reset(
  5934. ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr));
  5935. ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
  5936. ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
  5937. MCContext *PtrThumbCtx = ThumbCtx.get();
  5938. ThumbRelInfo.reset(
  5939. ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
  5940. if (ThumbRelInfo) {
  5941. ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
  5942. ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
  5943. &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
  5944. ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
  5945. }
  5946. int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
  5947. ThumbIP.reset(ThumbTarget->createMCInstPrinter(
  5948. Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
  5949. *ThumbInstrInfo, *ThumbMRI));
  5950. // Set the display preference for hex vs. decimal immediates.
  5951. ThumbIP->setPrintImmHex(PrintImmHex);
  5952. }
  5953. if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
  5954. errs() << "error: couldn't initialize disassembler for target "
  5955. << ThumbTripleName << '\n';
  5956. return;
  5957. }
  5958. MachO::mach_header Header = MachOOF->getHeader();
  5959. // FIXME: Using the -cfg command line option, this code used to be able to
  5960. // annotate relocations with the referenced symbol's name, and if this was
  5961. // inside a __[cf]string section, the data it points to. This is now replaced
  5962. // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
  5963. std::vector<SectionRef> Sections;
  5964. std::vector<SymbolRef> Symbols;
  5965. SmallVector<uint64_t, 8> FoundFns;
  5966. uint64_t BaseSegmentAddress;
  5967. getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
  5968. BaseSegmentAddress);
  5969. // Sort the symbols by address, just in case they didn't come in that way.
  5970. std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
  5971. // Build a data in code table that is sorted on by the address of each entry.
  5972. uint64_t BaseAddress = 0;
  5973. if (Header.filetype == MachO::MH_OBJECT)
  5974. BaseAddress = Sections[0].getAddress();
  5975. else
  5976. BaseAddress = BaseSegmentAddress;
  5977. DiceTable Dices;
  5978. for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
  5979. DI != DE; ++DI) {
  5980. uint32_t Offset;
  5981. DI->getOffset(Offset);
  5982. Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
  5983. }
  5984. array_pod_sort(Dices.begin(), Dices.end());
  5985. #ifndef NDEBUG
  5986. raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
  5987. #else
  5988. raw_ostream &DebugOut = nulls();
  5989. #endif
  5990. std::unique_ptr<DIContext> diContext;
  5991. ObjectFile *DbgObj = MachOOF;
  5992. // Try to find debug info and set up the DIContext for it.
  5993. if (UseDbg) {
  5994. // A separate DSym file path was specified, parse it as a macho file,
  5995. // get the sections and supply it to the section name parsing machinery.
  5996. if (!DSYMFile.empty()) {
  5997. ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
  5998. MemoryBuffer::getFileOrSTDIN(DSYMFile);
  5999. if (std::error_code EC = BufOrErr.getError()) {
  6000. errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
  6001. return;
  6002. }
  6003. DbgObj =
  6004. ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
  6005. .get()
  6006. .release();
  6007. }
  6008. // Setup the DIContext
  6009. diContext.reset(new DWARFContextInMemory(*DbgObj));
  6010. }
  6011. if (FilterSections.size() == 0)
  6012. outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
  6013. for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
  6014. StringRef SectName;
  6015. if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
  6016. continue;
  6017. DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
  6018. StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
  6019. if (SegmentName != DisSegName)
  6020. continue;
  6021. StringRef BytesStr;
  6022. Sections[SectIdx].getContents(BytesStr);
  6023. ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
  6024. BytesStr.size());
  6025. uint64_t SectAddress = Sections[SectIdx].getAddress();
  6026. bool symbolTableWorked = false;
  6027. // Create a map of symbol addresses to symbol names for use by
  6028. // the SymbolizerSymbolLookUp() routine.
  6029. SymbolAddressMap AddrMap;
  6030. bool DisSymNameFound = false;
  6031. for (const SymbolRef &Symbol : MachOOF->symbols()) {
  6032. Expected<SymbolRef::Type> STOrErr = Symbol.getType();
  6033. if (!STOrErr)
  6034. report_error(MachOOF->getFileName(), STOrErr.takeError());
  6035. SymbolRef::Type ST = *STOrErr;
  6036. if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
  6037. ST == SymbolRef::ST_Other) {
  6038. uint64_t Address = Symbol.getValue();
  6039. Expected<StringRef> SymNameOrErr = Symbol.getName();
  6040. if (!SymNameOrErr)
  6041. report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
  6042. StringRef SymName = *SymNameOrErr;
  6043. AddrMap[Address] = SymName;
  6044. if (!DisSymName.empty() && DisSymName == SymName)
  6045. DisSymNameFound = true;
  6046. }
  6047. }
  6048. if (!DisSymName.empty() && !DisSymNameFound) {
  6049. outs() << "Can't find -dis-symname: " << DisSymName << "\n";
  6050. return;
  6051. }
  6052. // Set up the block of info used by the Symbolizer call backs.
  6053. SymbolizerInfo.verbose = !NoSymbolicOperands;
  6054. SymbolizerInfo.O = MachOOF;
  6055. SymbolizerInfo.S = Sections[SectIdx];
  6056. SymbolizerInfo.AddrMap = &AddrMap;
  6057. SymbolizerInfo.Sections = &Sections;
  6058. SymbolizerInfo.class_name = nullptr;
  6059. SymbolizerInfo.selector_name = nullptr;
  6060. SymbolizerInfo.method = nullptr;
  6061. SymbolizerInfo.demangled_name = nullptr;
  6062. SymbolizerInfo.bindtable = nullptr;
  6063. SymbolizerInfo.adrp_addr = 0;
  6064. SymbolizerInfo.adrp_inst = 0;
  6065. // Same for the ThumbSymbolizer
  6066. ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
  6067. ThumbSymbolizerInfo.O = MachOOF;
  6068. ThumbSymbolizerInfo.S = Sections[SectIdx];
  6069. ThumbSymbolizerInfo.AddrMap = &AddrMap;
  6070. ThumbSymbolizerInfo.Sections = &Sections;
  6071. ThumbSymbolizerInfo.class_name = nullptr;
  6072. ThumbSymbolizerInfo.selector_name = nullptr;
  6073. ThumbSymbolizerInfo.method = nullptr;
  6074. ThumbSymbolizerInfo.demangled_name = nullptr;
  6075. ThumbSymbolizerInfo.bindtable = nullptr;
  6076. ThumbSymbolizerInfo.adrp_addr = 0;
  6077. ThumbSymbolizerInfo.adrp_inst = 0;
  6078. unsigned int Arch = MachOOF->getArch();
  6079. // Skip all symbols if this is a stubs file.
  6080. if (Bytes.size() == 0)
  6081. return;
  6082. // Disassemble symbol by symbol.
  6083. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
  6084. Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
  6085. if (!SymNameOrErr)
  6086. report_error(MachOOF->getFileName(), SymNameOrErr.takeError());
  6087. StringRef SymName = *SymNameOrErr;
  6088. Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
  6089. if (!STOrErr)
  6090. report_error(MachOOF->getFileName(), STOrErr.takeError());
  6091. SymbolRef::Type ST = *STOrErr;
  6092. if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
  6093. continue;
  6094. // Make sure the symbol is defined in this section.
  6095. bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
  6096. if (!containsSym) {
  6097. if (!DisSymName.empty() && DisSymName == SymName) {
  6098. outs() << "-dis-symname: " << DisSymName << " not in the section\n";
  6099. return;
  6100. }
  6101. continue;
  6102. }
  6103. // The __mh_execute_header is special and we need to deal with that fact
  6104. // this symbol is before the start of the (__TEXT,__text) section and at the
  6105. // address of the start of the __TEXT segment. This is because this symbol
  6106. // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
  6107. // start of the section in a standard MH_EXECUTE filetype.
  6108. if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
  6109. outs() << "-dis-symname: __mh_execute_header not in any section\n";
  6110. return;
  6111. }
  6112. // When this code is trying to disassemble a symbol at a time and in the
  6113. // case there is only the __mh_execute_header symbol left as in a stripped
  6114. // executable, we need to deal with this by ignoring this symbol so the
  6115. // whole section is disassembled and this symbol is then not displayed.
  6116. if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
  6117. SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
  6118. SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
  6119. continue;
  6120. // If we are only disassembling one symbol see if this is that symbol.
  6121. if (!DisSymName.empty() && DisSymName != SymName)
  6122. continue;
  6123. // Start at the address of the symbol relative to the section's address.
  6124. uint64_t SectSize = Sections[SectIdx].getSize();
  6125. uint64_t Start = Symbols[SymIdx].getValue();
  6126. uint64_t SectionAddress = Sections[SectIdx].getAddress();
  6127. Start -= SectionAddress;
  6128. if (Start > SectSize) {
  6129. outs() << "section data ends, " << SymName
  6130. << " lies outside valid range\n";
  6131. return;
  6132. }
  6133. // Stop disassembling either at the beginning of the next symbol or at
  6134. // the end of the section.
  6135. bool containsNextSym = false;
  6136. uint64_t NextSym = 0;
  6137. uint64_t NextSymIdx = SymIdx + 1;
  6138. while (Symbols.size() > NextSymIdx) {
  6139. Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
  6140. if (!STOrErr)
  6141. report_error(MachOOF->getFileName(), STOrErr.takeError());
  6142. SymbolRef::Type NextSymType = *STOrErr;
  6143. if (NextSymType == SymbolRef::ST_Function) {
  6144. containsNextSym =
  6145. Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
  6146. NextSym = Symbols[NextSymIdx].getValue();
  6147. NextSym -= SectionAddress;
  6148. break;
  6149. }
  6150. ++NextSymIdx;
  6151. }
  6152. uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
  6153. uint64_t Size;
  6154. symbolTableWorked = true;
  6155. DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
  6156. bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
  6157. // We only need the dedicated Thumb target if there's a real choice
  6158. // (i.e. we're not targeting M-class) and the function is Thumb.
  6159. bool UseThumbTarget = IsThumb && ThumbTarget;
  6160. outs() << SymName << ":\n";
  6161. DILineInfo lastLine;
  6162. for (uint64_t Index = Start; Index < End; Index += Size) {
  6163. MCInst Inst;
  6164. uint64_t PC = SectAddress + Index;
  6165. if (!NoLeadingAddr) {
  6166. if (FullLeadingAddr) {
  6167. if (MachOOF->is64Bit())
  6168. outs() << format("%016" PRIx64, PC);
  6169. else
  6170. outs() << format("%08" PRIx64, PC);
  6171. } else {
  6172. outs() << format("%8" PRIx64 ":", PC);
  6173. }
  6174. }
  6175. if (!NoShowRawInsn || Arch == Triple::arm)
  6176. outs() << "\t";
  6177. // Check the data in code table here to see if this is data not an
  6178. // instruction to be disassembled.
  6179. DiceTable Dice;
  6180. Dice.push_back(std::make_pair(PC, DiceRef()));
  6181. dice_table_iterator DTI =
  6182. std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
  6183. compareDiceTableEntries);
  6184. if (DTI != Dices.end()) {
  6185. uint16_t Length;
  6186. DTI->second.getLength(Length);
  6187. uint16_t Kind;
  6188. DTI->second.getKind(Kind);
  6189. Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
  6190. if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
  6191. (PC == (DTI->first + Length - 1)) && (Length & 1))
  6192. Size++;
  6193. continue;
  6194. }
  6195. SmallVector<char, 64> AnnotationsBytes;
  6196. raw_svector_ostream Annotations(AnnotationsBytes);
  6197. bool gotInst;
  6198. if (UseThumbTarget)
  6199. gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
  6200. PC, DebugOut, Annotations);
  6201. else
  6202. gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
  6203. DebugOut, Annotations);
  6204. if (gotInst) {
  6205. if (!NoShowRawInsn || Arch == Triple::arm) {
  6206. dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
  6207. }
  6208. formatted_raw_ostream FormattedOS(outs());
  6209. StringRef AnnotationsStr = Annotations.str();
  6210. if (UseThumbTarget)
  6211. ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
  6212. else
  6213. IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
  6214. emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
  6215. // Print debug info.
  6216. if (diContext) {
  6217. DILineInfo dli = diContext->getLineInfoForAddress(PC);
  6218. // Print valid line info if it changed.
  6219. if (dli != lastLine && dli.Line != 0)
  6220. outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
  6221. << dli.Column;
  6222. lastLine = dli;
  6223. }
  6224. outs() << "\n";
  6225. } else {
  6226. unsigned int Arch = MachOOF->getArch();
  6227. if (Arch == Triple::x86_64 || Arch == Triple::x86) {
  6228. outs() << format("\t.byte 0x%02x #bad opcode\n",
  6229. *(Bytes.data() + Index) & 0xff);
  6230. Size = 1; // skip exactly one illegible byte and move on.
  6231. } else if (Arch == Triple::aarch64 ||
  6232. (Arch == Triple::arm && !IsThumb)) {
  6233. uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
  6234. (*(Bytes.data() + Index + 1) & 0xff) << 8 |
  6235. (*(Bytes.data() + Index + 2) & 0xff) << 16 |
  6236. (*(Bytes.data() + Index + 3) & 0xff) << 24;
  6237. outs() << format("\t.long\t0x%08x\n", opcode);
  6238. Size = 4;
  6239. } else if (Arch == Triple::arm) {
  6240. assert(IsThumb && "ARM mode should have been dealt with above");
  6241. uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
  6242. (*(Bytes.data() + Index + 1) & 0xff) << 8;
  6243. outs() << format("\t.short\t0x%04x\n", opcode);
  6244. Size = 2;
  6245. } else{
  6246. errs() << "llvm-objdump: warning: invalid instruction encoding\n";
  6247. if (Size == 0)
  6248. Size = 1; // skip illegible bytes
  6249. }
  6250. }
  6251. }
  6252. }
  6253. if (!symbolTableWorked) {
  6254. // Reading the symbol table didn't work, disassemble the whole section.
  6255. uint64_t SectAddress = Sections[SectIdx].getAddress();
  6256. uint64_t SectSize = Sections[SectIdx].getSize();
  6257. uint64_t InstSize;
  6258. for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
  6259. MCInst Inst;
  6260. uint64_t PC = SectAddress + Index;
  6261. if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
  6262. DebugOut, nulls())) {
  6263. if (!NoLeadingAddr) {
  6264. if (FullLeadingAddr) {
  6265. if (MachOOF->is64Bit())
  6266. outs() << format("%016" PRIx64, PC);
  6267. else
  6268. outs() << format("%08" PRIx64, PC);
  6269. } else {
  6270. outs() << format("%8" PRIx64 ":", PC);
  6271. }
  6272. }
  6273. if (!NoShowRawInsn || Arch == Triple::arm) {
  6274. outs() << "\t";
  6275. dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
  6276. }
  6277. IP->printInst(&Inst, outs(), "", *STI);
  6278. outs() << "\n";
  6279. } else {
  6280. unsigned int Arch = MachOOF->getArch();
  6281. if (Arch == Triple::x86_64 || Arch == Triple::x86) {
  6282. outs() << format("\t.byte 0x%02x #bad opcode\n",
  6283. *(Bytes.data() + Index) & 0xff);
  6284. InstSize = 1; // skip exactly one illegible byte and move on.
  6285. } else {
  6286. errs() << "llvm-objdump: warning: invalid instruction encoding\n";
  6287. if (InstSize == 0)
  6288. InstSize = 1; // skip illegible bytes
  6289. }
  6290. }
  6291. }
  6292. }
  6293. // The TripleName's need to be reset if we are called again for a different
  6294. // archtecture.
  6295. TripleName = "";
  6296. ThumbTripleName = "";
  6297. if (SymbolizerInfo.method != nullptr)
  6298. free(SymbolizerInfo.method);
  6299. if (SymbolizerInfo.demangled_name != nullptr)
  6300. free(SymbolizerInfo.demangled_name);
  6301. if (SymbolizerInfo.bindtable != nullptr)
  6302. delete SymbolizerInfo.bindtable;
  6303. if (ThumbSymbolizerInfo.method != nullptr)
  6304. free(ThumbSymbolizerInfo.method);
  6305. if (ThumbSymbolizerInfo.demangled_name != nullptr)
  6306. free(ThumbSymbolizerInfo.demangled_name);
  6307. if (ThumbSymbolizerInfo.bindtable != nullptr)
  6308. delete ThumbSymbolizerInfo.bindtable;
  6309. }
  6310. }
  6311. //===----------------------------------------------------------------------===//
  6312. // __compact_unwind section dumping
  6313. //===----------------------------------------------------------------------===//
  6314. namespace {
  6315. template <typename T> static uint64_t readNext(const char *&Buf) {
  6316. using llvm::support::little;
  6317. using llvm::support::unaligned;
  6318. uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
  6319. Buf += sizeof(T);
  6320. return Val;
  6321. }
  6322. struct CompactUnwindEntry {
  6323. uint32_t OffsetInSection;
  6324. uint64_t FunctionAddr;
  6325. uint32_t Length;
  6326. uint32_t CompactEncoding;
  6327. uint64_t PersonalityAddr;
  6328. uint64_t LSDAAddr;
  6329. RelocationRef FunctionReloc;
  6330. RelocationRef PersonalityReloc;
  6331. RelocationRef LSDAReloc;
  6332. CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
  6333. : OffsetInSection(Offset) {
  6334. if (Is64)
  6335. read<uint64_t>(Contents.data() + Offset);
  6336. else
  6337. read<uint32_t>(Contents.data() + Offset);
  6338. }
  6339. private:
  6340. template <typename UIntPtr> void read(const char *Buf) {
  6341. FunctionAddr = readNext<UIntPtr>(Buf);
  6342. Length = readNext<uint32_t>(Buf);
  6343. CompactEncoding = readNext<uint32_t>(Buf);
  6344. PersonalityAddr = readNext<UIntPtr>(Buf);
  6345. LSDAAddr = readNext<UIntPtr>(Buf);
  6346. }
  6347. };
  6348. }
  6349. /// Given a relocation from __compact_unwind, consisting of the RelocationRef
  6350. /// and data being relocated, determine the best base Name and Addend to use for
  6351. /// display purposes.
  6352. ///
  6353. /// 1. An Extern relocation will directly reference a symbol (and the data is
  6354. /// then already an addend), so use that.
  6355. /// 2. Otherwise the data is an offset in the object file's layout; try to find
  6356. // a symbol before it in the same section, and use the offset from there.
  6357. /// 3. Finally, if all that fails, fall back to an offset from the start of the
  6358. /// referenced section.
  6359. static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
  6360. std::map<uint64_t, SymbolRef> &Symbols,
  6361. const RelocationRef &Reloc, uint64_t Addr,
  6362. StringRef &Name, uint64_t &Addend) {
  6363. if (Reloc.getSymbol() != Obj->symbol_end()) {
  6364. Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
  6365. if (!NameOrErr)
  6366. report_error(Obj->getFileName(), NameOrErr.takeError());
  6367. Name = *NameOrErr;
  6368. Addend = Addr;
  6369. return;
  6370. }
  6371. auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
  6372. SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
  6373. uint64_t SectionAddr = RelocSection.getAddress();
  6374. auto Sym = Symbols.upper_bound(Addr);
  6375. if (Sym == Symbols.begin()) {
  6376. // The first symbol in the object is after this reference, the best we can
  6377. // do is section-relative notation.
  6378. RelocSection.getName(Name);
  6379. Addend = Addr - SectionAddr;
  6380. return;
  6381. }
  6382. // Go back one so that SymbolAddress <= Addr.
  6383. --Sym;
  6384. auto SectOrErr = Sym->second.getSection();
  6385. if (!SectOrErr)
  6386. report_error(Obj->getFileName(), SectOrErr.takeError());
  6387. section_iterator SymSection = *SectOrErr;
  6388. if (RelocSection == *SymSection) {
  6389. // There's a valid symbol in the same section before this reference.
  6390. Expected<StringRef> NameOrErr = Sym->second.getName();
  6391. if (!NameOrErr)
  6392. report_error(Obj->getFileName(), NameOrErr.takeError());
  6393. Name = *NameOrErr;
  6394. Addend = Addr - Sym->first;
  6395. return;
  6396. }
  6397. // There is a symbol before this reference, but it's in a different
  6398. // section. Probably not helpful to mention it, so use the section name.
  6399. RelocSection.getName(Name);
  6400. Addend = Addr - SectionAddr;
  6401. }
  6402. static void printUnwindRelocDest(const MachOObjectFile *Obj,
  6403. std::map<uint64_t, SymbolRef> &Symbols,
  6404. const RelocationRef &Reloc, uint64_t Addr) {
  6405. StringRef Name;
  6406. uint64_t Addend;
  6407. if (!Reloc.getObject())
  6408. return;
  6409. findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
  6410. outs() << Name;
  6411. if (Addend)
  6412. outs() << " + " << format("0x%" PRIx64, Addend);
  6413. }
  6414. static void
  6415. printMachOCompactUnwindSection(const MachOObjectFile *Obj,
  6416. std::map<uint64_t, SymbolRef> &Symbols,
  6417. const SectionRef &CompactUnwind) {
  6418. if (!Obj->isLittleEndian()) {
  6419. outs() << "Skipping big-endian __compact_unwind section\n";
  6420. return;
  6421. }
  6422. bool Is64 = Obj->is64Bit();
  6423. uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
  6424. uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
  6425. StringRef Contents;
  6426. CompactUnwind.getContents(Contents);
  6427. SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
  6428. // First populate the initial raw offsets, encodings and so on from the entry.
  6429. for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
  6430. CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
  6431. CompactUnwinds.push_back(Entry);
  6432. }
  6433. // Next we need to look at the relocations to find out what objects are
  6434. // actually being referred to.
  6435. for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
  6436. uint64_t RelocAddress = Reloc.getOffset();
  6437. uint32_t EntryIdx = RelocAddress / EntrySize;
  6438. uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
  6439. CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
  6440. if (OffsetInEntry == 0)
  6441. Entry.FunctionReloc = Reloc;
  6442. else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
  6443. Entry.PersonalityReloc = Reloc;
  6444. else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
  6445. Entry.LSDAReloc = Reloc;
  6446. else {
  6447. outs() << "Invalid relocation in __compact_unwind section\n";
  6448. return;
  6449. }
  6450. }
  6451. // Finally, we're ready to print the data we've gathered.
  6452. outs() << "Contents of __compact_unwind section:\n";
  6453. for (auto &Entry : CompactUnwinds) {
  6454. outs() << " Entry at offset "
  6455. << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
  6456. // 1. Start of the region this entry applies to.
  6457. outs() << " start: " << format("0x%" PRIx64,
  6458. Entry.FunctionAddr) << ' ';
  6459. printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
  6460. outs() << '\n';
  6461. // 2. Length of the region this entry applies to.
  6462. outs() << " length: " << format("0x%" PRIx32, Entry.Length)
  6463. << '\n';
  6464. // 3. The 32-bit compact encoding.
  6465. outs() << " compact encoding: "
  6466. << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
  6467. // 4. The personality function, if present.
  6468. if (Entry.PersonalityReloc.getObject()) {
  6469. outs() << " personality function: "
  6470. << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
  6471. printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
  6472. Entry.PersonalityAddr);
  6473. outs() << '\n';
  6474. }
  6475. // 5. This entry's language-specific data area.
  6476. if (Entry.LSDAReloc.getObject()) {
  6477. outs() << " LSDA: " << format("0x%" PRIx64,
  6478. Entry.LSDAAddr) << ' ';
  6479. printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
  6480. outs() << '\n';
  6481. }
  6482. }
  6483. }
  6484. //===----------------------------------------------------------------------===//
  6485. // __unwind_info section dumping
  6486. //===----------------------------------------------------------------------===//
  6487. static void printRegularSecondLevelUnwindPage(const char *PageStart) {
  6488. const char *Pos = PageStart;
  6489. uint32_t Kind = readNext<uint32_t>(Pos);
  6490. (void)Kind;
  6491. assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
  6492. uint16_t EntriesStart = readNext<uint16_t>(Pos);
  6493. uint16_t NumEntries = readNext<uint16_t>(Pos);
  6494. Pos = PageStart + EntriesStart;
  6495. for (unsigned i = 0; i < NumEntries; ++i) {
  6496. uint32_t FunctionOffset = readNext<uint32_t>(Pos);
  6497. uint32_t Encoding = readNext<uint32_t>(Pos);
  6498. outs() << " [" << i << "]: "
  6499. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6500. << ", "
  6501. << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
  6502. }
  6503. }
  6504. static void printCompressedSecondLevelUnwindPage(
  6505. const char *PageStart, uint32_t FunctionBase,
  6506. const SmallVectorImpl<uint32_t> &CommonEncodings) {
  6507. const char *Pos = PageStart;
  6508. uint32_t Kind = readNext<uint32_t>(Pos);
  6509. (void)Kind;
  6510. assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
  6511. uint16_t EntriesStart = readNext<uint16_t>(Pos);
  6512. uint16_t NumEntries = readNext<uint16_t>(Pos);
  6513. uint16_t EncodingsStart = readNext<uint16_t>(Pos);
  6514. readNext<uint16_t>(Pos);
  6515. const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>(
  6516. PageStart + EncodingsStart);
  6517. Pos = PageStart + EntriesStart;
  6518. for (unsigned i = 0; i < NumEntries; ++i) {
  6519. uint32_t Entry = readNext<uint32_t>(Pos);
  6520. uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
  6521. uint32_t EncodingIdx = Entry >> 24;
  6522. uint32_t Encoding;
  6523. if (EncodingIdx < CommonEncodings.size())
  6524. Encoding = CommonEncodings[EncodingIdx];
  6525. else
  6526. Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()];
  6527. outs() << " [" << i << "]: "
  6528. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6529. << ", "
  6530. << "encoding[" << EncodingIdx
  6531. << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
  6532. }
  6533. }
  6534. static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
  6535. std::map<uint64_t, SymbolRef> &Symbols,
  6536. const SectionRef &UnwindInfo) {
  6537. if (!Obj->isLittleEndian()) {
  6538. outs() << "Skipping big-endian __unwind_info section\n";
  6539. return;
  6540. }
  6541. outs() << "Contents of __unwind_info section:\n";
  6542. StringRef Contents;
  6543. UnwindInfo.getContents(Contents);
  6544. const char *Pos = Contents.data();
  6545. //===----------------------------------
  6546. // Section header
  6547. //===----------------------------------
  6548. uint32_t Version = readNext<uint32_t>(Pos);
  6549. outs() << " Version: "
  6550. << format("0x%" PRIx32, Version) << '\n';
  6551. if (Version != 1) {
  6552. outs() << " Skipping section with unknown version\n";
  6553. return;
  6554. }
  6555. uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos);
  6556. outs() << " Common encodings array section offset: "
  6557. << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
  6558. uint32_t NumCommonEncodings = readNext<uint32_t>(Pos);
  6559. outs() << " Number of common encodings in array: "
  6560. << format("0x%" PRIx32, NumCommonEncodings) << '\n';
  6561. uint32_t PersonalitiesStart = readNext<uint32_t>(Pos);
  6562. outs() << " Personality function array section offset: "
  6563. << format("0x%" PRIx32, PersonalitiesStart) << '\n';
  6564. uint32_t NumPersonalities = readNext<uint32_t>(Pos);
  6565. outs() << " Number of personality functions in array: "
  6566. << format("0x%" PRIx32, NumPersonalities) << '\n';
  6567. uint32_t IndicesStart = readNext<uint32_t>(Pos);
  6568. outs() << " Index array section offset: "
  6569. << format("0x%" PRIx32, IndicesStart) << '\n';
  6570. uint32_t NumIndices = readNext<uint32_t>(Pos);
  6571. outs() << " Number of indices in array: "
  6572. << format("0x%" PRIx32, NumIndices) << '\n';
  6573. //===----------------------------------
  6574. // A shared list of common encodings
  6575. //===----------------------------------
  6576. // These occupy indices in the range [0, N] whenever an encoding is referenced
  6577. // from a compressed 2nd level index table. In practice the linker only
  6578. // creates ~128 of these, so that indices are available to embed encodings in
  6579. // the 2nd level index.
  6580. SmallVector<uint32_t, 64> CommonEncodings;
  6581. outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
  6582. Pos = Contents.data() + CommonEncodingsStart;
  6583. for (unsigned i = 0; i < NumCommonEncodings; ++i) {
  6584. uint32_t Encoding = readNext<uint32_t>(Pos);
  6585. CommonEncodings.push_back(Encoding);
  6586. outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
  6587. << '\n';
  6588. }
  6589. //===----------------------------------
  6590. // Personality functions used in this executable
  6591. //===----------------------------------
  6592. // There should be only a handful of these (one per source language,
  6593. // roughly). Particularly since they only get 2 bits in the compact encoding.
  6594. outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
  6595. Pos = Contents.data() + PersonalitiesStart;
  6596. for (unsigned i = 0; i < NumPersonalities; ++i) {
  6597. uint32_t PersonalityFn = readNext<uint32_t>(Pos);
  6598. outs() << " personality[" << i + 1
  6599. << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
  6600. }
  6601. //===----------------------------------
  6602. // The level 1 index entries
  6603. //===----------------------------------
  6604. // These specify an approximate place to start searching for the more detailed
  6605. // information, sorted by PC.
  6606. struct IndexEntry {
  6607. uint32_t FunctionOffset;
  6608. uint32_t SecondLevelPageStart;
  6609. uint32_t LSDAStart;
  6610. };
  6611. SmallVector<IndexEntry, 4> IndexEntries;
  6612. outs() << " Top level indices: (count = " << NumIndices << ")\n";
  6613. Pos = Contents.data() + IndicesStart;
  6614. for (unsigned i = 0; i < NumIndices; ++i) {
  6615. IndexEntry Entry;
  6616. Entry.FunctionOffset = readNext<uint32_t>(Pos);
  6617. Entry.SecondLevelPageStart = readNext<uint32_t>(Pos);
  6618. Entry.LSDAStart = readNext<uint32_t>(Pos);
  6619. IndexEntries.push_back(Entry);
  6620. outs() << " [" << i << "]: "
  6621. << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
  6622. << ", "
  6623. << "2nd level page offset="
  6624. << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
  6625. << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
  6626. }
  6627. //===----------------------------------
  6628. // Next come the LSDA tables
  6629. //===----------------------------------
  6630. // The LSDA layout is rather implicit: it's a contiguous array of entries from
  6631. // the first top-level index's LSDAOffset to the last (sentinel).
  6632. outs() << " LSDA descriptors:\n";
  6633. Pos = Contents.data() + IndexEntries[0].LSDAStart;
  6634. int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) /
  6635. (2 * sizeof(uint32_t));
  6636. for (int i = 0; i < NumLSDAs; ++i) {
  6637. uint32_t FunctionOffset = readNext<uint32_t>(Pos);
  6638. uint32_t LSDAOffset = readNext<uint32_t>(Pos);
  6639. outs() << " [" << i << "]: "
  6640. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6641. << ", "
  6642. << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
  6643. }
  6644. //===----------------------------------
  6645. // Finally, the 2nd level indices
  6646. //===----------------------------------
  6647. // Generally these are 4K in size, and have 2 possible forms:
  6648. // + Regular stores up to 511 entries with disparate encodings
  6649. // + Compressed stores up to 1021 entries if few enough compact encoding
  6650. // values are used.
  6651. outs() << " Second level indices:\n";
  6652. for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
  6653. // The final sentinel top-level index has no associated 2nd level page
  6654. if (IndexEntries[i].SecondLevelPageStart == 0)
  6655. break;
  6656. outs() << " Second level index[" << i << "]: "
  6657. << "offset in section="
  6658. << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
  6659. << ", "
  6660. << "base function offset="
  6661. << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
  6662. Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart;
  6663. uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos);
  6664. if (Kind == 2)
  6665. printRegularSecondLevelUnwindPage(Pos);
  6666. else if (Kind == 3)
  6667. printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset,
  6668. CommonEncodings);
  6669. else
  6670. outs() << " Skipping 2nd level page with unknown kind " << Kind
  6671. << '\n';
  6672. }
  6673. }
  6674. void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
  6675. std::map<uint64_t, SymbolRef> Symbols;
  6676. for (const SymbolRef &SymRef : Obj->symbols()) {
  6677. // Discard any undefined or absolute symbols. They're not going to take part
  6678. // in the convenience lookup for unwind info and just take up resources.
  6679. auto SectOrErr = SymRef.getSection();
  6680. if (!SectOrErr) {
  6681. // TODO: Actually report errors helpfully.
  6682. consumeError(SectOrErr.takeError());
  6683. continue;
  6684. }
  6685. section_iterator Section = *SectOrErr;
  6686. if (Section == Obj->section_end())
  6687. continue;
  6688. uint64_t Addr = SymRef.getValue();
  6689. Symbols.insert(std::make_pair(Addr, SymRef));
  6690. }
  6691. for (const SectionRef &Section : Obj->sections()) {
  6692. StringRef SectName;
  6693. Section.getName(SectName);
  6694. if (SectName == "__compact_unwind")
  6695. printMachOCompactUnwindSection(Obj, Symbols, Section);
  6696. else if (SectName == "__unwind_info")
  6697. printMachOUnwindInfoSection(Obj, Symbols, Section);
  6698. }
  6699. }
  6700. static void PrintMachHeader(uint32_t magic, uint32_t cputype,
  6701. uint32_t cpusubtype, uint32_t filetype,
  6702. uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
  6703. bool verbose) {
  6704. outs() << "Mach header\n";
  6705. outs() << " magic cputype cpusubtype caps filetype ncmds "
  6706. "sizeofcmds flags\n";
  6707. if (verbose) {
  6708. if (magic == MachO::MH_MAGIC)
  6709. outs() << " MH_MAGIC";
  6710. else if (magic == MachO::MH_MAGIC_64)
  6711. outs() << "MH_MAGIC_64";
  6712. else
  6713. outs() << format(" 0x%08" PRIx32, magic);
  6714. switch (cputype) {
  6715. case MachO::CPU_TYPE_I386:
  6716. outs() << " I386";
  6717. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6718. case MachO::CPU_SUBTYPE_I386_ALL:
  6719. outs() << " ALL";
  6720. break;
  6721. default:
  6722. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6723. break;
  6724. }
  6725. break;
  6726. case MachO::CPU_TYPE_X86_64:
  6727. outs() << " X86_64";
  6728. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6729. case MachO::CPU_SUBTYPE_X86_64_ALL:
  6730. outs() << " ALL";
  6731. break;
  6732. case MachO::CPU_SUBTYPE_X86_64_H:
  6733. outs() << " Haswell";
  6734. break;
  6735. default:
  6736. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6737. break;
  6738. }
  6739. break;
  6740. case MachO::CPU_TYPE_ARM:
  6741. outs() << " ARM";
  6742. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6743. case MachO::CPU_SUBTYPE_ARM_ALL:
  6744. outs() << " ALL";
  6745. break;
  6746. case MachO::CPU_SUBTYPE_ARM_V4T:
  6747. outs() << " V4T";
  6748. break;
  6749. case MachO::CPU_SUBTYPE_ARM_V5TEJ:
  6750. outs() << " V5TEJ";
  6751. break;
  6752. case MachO::CPU_SUBTYPE_ARM_XSCALE:
  6753. outs() << " XSCALE";
  6754. break;
  6755. case MachO::CPU_SUBTYPE_ARM_V6:
  6756. outs() << " V6";
  6757. break;
  6758. case MachO::CPU_SUBTYPE_ARM_V6M:
  6759. outs() << " V6M";
  6760. break;
  6761. case MachO::CPU_SUBTYPE_ARM_V7:
  6762. outs() << " V7";
  6763. break;
  6764. case MachO::CPU_SUBTYPE_ARM_V7EM:
  6765. outs() << " V7EM";
  6766. break;
  6767. case MachO::CPU_SUBTYPE_ARM_V7K:
  6768. outs() << " V7K";
  6769. break;
  6770. case MachO::CPU_SUBTYPE_ARM_V7M:
  6771. outs() << " V7M";
  6772. break;
  6773. case MachO::CPU_SUBTYPE_ARM_V7S:
  6774. outs() << " V7S";
  6775. break;
  6776. default:
  6777. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6778. break;
  6779. }
  6780. break;
  6781. case MachO::CPU_TYPE_ARM64:
  6782. outs() << " ARM64";
  6783. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6784. case MachO::CPU_SUBTYPE_ARM64_ALL:
  6785. outs() << " ALL";
  6786. break;
  6787. default:
  6788. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6789. break;
  6790. }
  6791. break;
  6792. case MachO::CPU_TYPE_POWERPC:
  6793. outs() << " PPC";
  6794. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6795. case MachO::CPU_SUBTYPE_POWERPC_ALL:
  6796. outs() << " ALL";
  6797. break;
  6798. default:
  6799. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6800. break;
  6801. }
  6802. break;
  6803. case MachO::CPU_TYPE_POWERPC64:
  6804. outs() << " PPC64";
  6805. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6806. case MachO::CPU_SUBTYPE_POWERPC_ALL:
  6807. outs() << " ALL";
  6808. break;
  6809. default:
  6810. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6811. break;
  6812. }
  6813. break;
  6814. default:
  6815. outs() << format(" %7d", cputype);
  6816. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6817. break;
  6818. }
  6819. if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
  6820. outs() << " LIB64";
  6821. } else {
  6822. outs() << format(" 0x%02" PRIx32,
  6823. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
  6824. }
  6825. switch (filetype) {
  6826. case MachO::MH_OBJECT:
  6827. outs() << " OBJECT";
  6828. break;
  6829. case MachO::MH_EXECUTE:
  6830. outs() << " EXECUTE";
  6831. break;
  6832. case MachO::MH_FVMLIB:
  6833. outs() << " FVMLIB";
  6834. break;
  6835. case MachO::MH_CORE:
  6836. outs() << " CORE";
  6837. break;
  6838. case MachO::MH_PRELOAD:
  6839. outs() << " PRELOAD";
  6840. break;
  6841. case MachO::MH_DYLIB:
  6842. outs() << " DYLIB";
  6843. break;
  6844. case MachO::MH_DYLIB_STUB:
  6845. outs() << " DYLIB_STUB";
  6846. break;
  6847. case MachO::MH_DYLINKER:
  6848. outs() << " DYLINKER";
  6849. break;
  6850. case MachO::MH_BUNDLE:
  6851. outs() << " BUNDLE";
  6852. break;
  6853. case MachO::MH_DSYM:
  6854. outs() << " DSYM";
  6855. break;
  6856. case MachO::MH_KEXT_BUNDLE:
  6857. outs() << " KEXTBUNDLE";
  6858. break;
  6859. default:
  6860. outs() << format(" %10u", filetype);
  6861. break;
  6862. }
  6863. outs() << format(" %5u", ncmds);
  6864. outs() << format(" %10u", sizeofcmds);
  6865. uint32_t f = flags;
  6866. if (f & MachO::MH_NOUNDEFS) {
  6867. outs() << " NOUNDEFS";
  6868. f &= ~MachO::MH_NOUNDEFS;
  6869. }
  6870. if (f & MachO::MH_INCRLINK) {
  6871. outs() << " INCRLINK";
  6872. f &= ~MachO::MH_INCRLINK;
  6873. }
  6874. if (f & MachO::MH_DYLDLINK) {
  6875. outs() << " DYLDLINK";
  6876. f &= ~MachO::MH_DYLDLINK;
  6877. }
  6878. if (f & MachO::MH_BINDATLOAD) {
  6879. outs() << " BINDATLOAD";
  6880. f &= ~MachO::MH_BINDATLOAD;
  6881. }
  6882. if (f & MachO::MH_PREBOUND) {
  6883. outs() << " PREBOUND";
  6884. f &= ~MachO::MH_PREBOUND;
  6885. }
  6886. if (f & MachO::MH_SPLIT_SEGS) {
  6887. outs() << " SPLIT_SEGS";
  6888. f &= ~MachO::MH_SPLIT_SEGS;
  6889. }
  6890. if (f & MachO::MH_LAZY_INIT) {
  6891. outs() << " LAZY_INIT";
  6892. f &= ~MachO::MH_LAZY_INIT;
  6893. }
  6894. if (f & MachO::MH_TWOLEVEL) {
  6895. outs() << " TWOLEVEL";
  6896. f &= ~MachO::MH_TWOLEVEL;
  6897. }
  6898. if (f & MachO::MH_FORCE_FLAT) {
  6899. outs() << " FORCE_FLAT";
  6900. f &= ~MachO::MH_FORCE_FLAT;
  6901. }
  6902. if (f & MachO::MH_NOMULTIDEFS) {
  6903. outs() << " NOMULTIDEFS";
  6904. f &= ~MachO::MH_NOMULTIDEFS;
  6905. }
  6906. if (f & MachO::MH_NOFIXPREBINDING) {
  6907. outs() << " NOFIXPREBINDING";
  6908. f &= ~MachO::MH_NOFIXPREBINDING;
  6909. }
  6910. if (f & MachO::MH_PREBINDABLE) {
  6911. outs() << " PREBINDABLE";
  6912. f &= ~MachO::MH_PREBINDABLE;
  6913. }
  6914. if (f & MachO::MH_ALLMODSBOUND) {
  6915. outs() << " ALLMODSBOUND";
  6916. f &= ~MachO::MH_ALLMODSBOUND;
  6917. }
  6918. if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
  6919. outs() << " SUBSECTIONS_VIA_SYMBOLS";
  6920. f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
  6921. }
  6922. if (f & MachO::MH_CANONICAL) {
  6923. outs() << " CANONICAL";
  6924. f &= ~MachO::MH_CANONICAL;
  6925. }
  6926. if (f & MachO::MH_WEAK_DEFINES) {
  6927. outs() << " WEAK_DEFINES";
  6928. f &= ~MachO::MH_WEAK_DEFINES;
  6929. }
  6930. if (f & MachO::MH_BINDS_TO_WEAK) {
  6931. outs() << " BINDS_TO_WEAK";
  6932. f &= ~MachO::MH_BINDS_TO_WEAK;
  6933. }
  6934. if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
  6935. outs() << " ALLOW_STACK_EXECUTION";
  6936. f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
  6937. }
  6938. if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
  6939. outs() << " DEAD_STRIPPABLE_DYLIB";
  6940. f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
  6941. }
  6942. if (f & MachO::MH_PIE) {
  6943. outs() << " PIE";
  6944. f &= ~MachO::MH_PIE;
  6945. }
  6946. if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
  6947. outs() << " NO_REEXPORTED_DYLIBS";
  6948. f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
  6949. }
  6950. if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
  6951. outs() << " MH_HAS_TLV_DESCRIPTORS";
  6952. f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
  6953. }
  6954. if (f & MachO::MH_NO_HEAP_EXECUTION) {
  6955. outs() << " MH_NO_HEAP_EXECUTION";
  6956. f &= ~MachO::MH_NO_HEAP_EXECUTION;
  6957. }
  6958. if (f & MachO::MH_APP_EXTENSION_SAFE) {
  6959. outs() << " APP_EXTENSION_SAFE";
  6960. f &= ~MachO::MH_APP_EXTENSION_SAFE;
  6961. }
  6962. if (f != 0 || flags == 0)
  6963. outs() << format(" 0x%08" PRIx32, f);
  6964. } else {
  6965. outs() << format(" 0x%08" PRIx32, magic);
  6966. outs() << format(" %7d", cputype);
  6967. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6968. outs() << format(" 0x%02" PRIx32,
  6969. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
  6970. outs() << format(" %10u", filetype);
  6971. outs() << format(" %5u", ncmds);
  6972. outs() << format(" %10u", sizeofcmds);
  6973. outs() << format(" 0x%08" PRIx32, flags);
  6974. }
  6975. outs() << "\n";
  6976. }
  6977. static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
  6978. StringRef SegName, uint64_t vmaddr,
  6979. uint64_t vmsize, uint64_t fileoff,
  6980. uint64_t filesize, uint32_t maxprot,
  6981. uint32_t initprot, uint32_t nsects,
  6982. uint32_t flags, uint32_t object_size,
  6983. bool verbose) {
  6984. uint64_t expected_cmdsize;
  6985. if (cmd == MachO::LC_SEGMENT) {
  6986. outs() << " cmd LC_SEGMENT\n";
  6987. expected_cmdsize = nsects;
  6988. expected_cmdsize *= sizeof(struct MachO::section);
  6989. expected_cmdsize += sizeof(struct MachO::segment_command);
  6990. } else {
  6991. outs() << " cmd LC_SEGMENT_64\n";
  6992. expected_cmdsize = nsects;
  6993. expected_cmdsize *= sizeof(struct MachO::section_64);
  6994. expected_cmdsize += sizeof(struct MachO::segment_command_64);
  6995. }
  6996. outs() << " cmdsize " << cmdsize;
  6997. if (cmdsize != expected_cmdsize)
  6998. outs() << " Inconsistent size\n";
  6999. else
  7000. outs() << "\n";
  7001. outs() << " segname " << SegName << "\n";
  7002. if (cmd == MachO::LC_SEGMENT_64) {
  7003. outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
  7004. outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
  7005. } else {
  7006. outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
  7007. outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
  7008. }
  7009. outs() << " fileoff " << fileoff;
  7010. if (fileoff > object_size)
  7011. outs() << " (past end of file)\n";
  7012. else
  7013. outs() << "\n";
  7014. outs() << " filesize " << filesize;
  7015. if (fileoff + filesize > object_size)
  7016. outs() << " (past end of file)\n";
  7017. else
  7018. outs() << "\n";
  7019. if (verbose) {
  7020. if ((maxprot &
  7021. ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
  7022. MachO::VM_PROT_EXECUTE)) != 0)
  7023. outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
  7024. else {
  7025. outs() << " maxprot ";
  7026. outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
  7027. outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
  7028. outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
  7029. }
  7030. if ((initprot &
  7031. ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
  7032. MachO::VM_PROT_EXECUTE)) != 0)
  7033. outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
  7034. else {
  7035. outs() << " initprot ";
  7036. outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
  7037. outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
  7038. outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
  7039. }
  7040. } else {
  7041. outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
  7042. outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
  7043. }
  7044. outs() << " nsects " << nsects << "\n";
  7045. if (verbose) {
  7046. outs() << " flags";
  7047. if (flags == 0)
  7048. outs() << " (none)\n";
  7049. else {
  7050. if (flags & MachO::SG_HIGHVM) {
  7051. outs() << " HIGHVM";
  7052. flags &= ~MachO::SG_HIGHVM;
  7053. }
  7054. if (flags & MachO::SG_FVMLIB) {
  7055. outs() << " FVMLIB";
  7056. flags &= ~MachO::SG_FVMLIB;
  7057. }
  7058. if (flags & MachO::SG_NORELOC) {
  7059. outs() << " NORELOC";
  7060. flags &= ~MachO::SG_NORELOC;
  7061. }
  7062. if (flags & MachO::SG_PROTECTED_VERSION_1) {
  7063. outs() << " PROTECTED_VERSION_1";
  7064. flags &= ~MachO::SG_PROTECTED_VERSION_1;
  7065. }
  7066. if (flags)
  7067. outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
  7068. else
  7069. outs() << "\n";
  7070. }
  7071. } else {
  7072. outs() << " flags " << format("0x%" PRIx32, flags) << "\n";
  7073. }
  7074. }
  7075. static void PrintSection(const char *sectname, const char *segname,
  7076. uint64_t addr, uint64_t size, uint32_t offset,
  7077. uint32_t align, uint32_t reloff, uint32_t nreloc,
  7078. uint32_t flags, uint32_t reserved1, uint32_t reserved2,
  7079. uint32_t cmd, const char *sg_segname,
  7080. uint32_t filetype, uint32_t object_size,
  7081. bool verbose) {
  7082. outs() << "Section\n";
  7083. outs() << " sectname " << format("%.16s\n", sectname);
  7084. outs() << " segname " << format("%.16s", segname);
  7085. if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
  7086. outs() << " (does not match segment)\n";
  7087. else
  7088. outs() << "\n";
  7089. if (cmd == MachO::LC_SEGMENT_64) {
  7090. outs() << " addr " << format("0x%016" PRIx64, addr) << "\n";
  7091. outs() << " size " << format("0x%016" PRIx64, size);
  7092. } else {
  7093. outs() << " addr " << format("0x%08" PRIx64, addr) << "\n";
  7094. outs() << " size " << format("0x%08" PRIx64, size);
  7095. }
  7096. if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
  7097. outs() << " (past end of file)\n";
  7098. else
  7099. outs() << "\n";
  7100. outs() << " offset " << offset;
  7101. if (offset > object_size)
  7102. outs() << " (past end of file)\n";
  7103. else
  7104. outs() << "\n";
  7105. uint32_t align_shifted = 1 << align;
  7106. outs() << " align 2^" << align << " (" << align_shifted << ")\n";
  7107. outs() << " reloff " << reloff;
  7108. if (reloff > object_size)
  7109. outs() << " (past end of file)\n";
  7110. else
  7111. outs() << "\n";
  7112. outs() << " nreloc " << nreloc;
  7113. if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
  7114. outs() << " (past end of file)\n";
  7115. else
  7116. outs() << "\n";
  7117. uint32_t section_type = flags & MachO::SECTION_TYPE;
  7118. if (verbose) {
  7119. outs() << " type";
  7120. if (section_type == MachO::S_REGULAR)
  7121. outs() << " S_REGULAR\n";
  7122. else if (section_type == MachO::S_ZEROFILL)
  7123. outs() << " S_ZEROFILL\n";
  7124. else if (section_type == MachO::S_CSTRING_LITERALS)
  7125. outs() << " S_CSTRING_LITERALS\n";
  7126. else if (section_type == MachO::S_4BYTE_LITERALS)
  7127. outs() << " S_4BYTE_LITERALS\n";
  7128. else if (section_type == MachO::S_8BYTE_LITERALS)
  7129. outs() << " S_8BYTE_LITERALS\n";
  7130. else if (section_type == MachO::S_16BYTE_LITERALS)
  7131. outs() << " S_16BYTE_LITERALS\n";
  7132. else if (section_type == MachO::S_LITERAL_POINTERS)
  7133. outs() << " S_LITERAL_POINTERS\n";
  7134. else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
  7135. outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
  7136. else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
  7137. outs() << " S_LAZY_SYMBOL_POINTERS\n";
  7138. else if (section_type == MachO::S_SYMBOL_STUBS)
  7139. outs() << " S_SYMBOL_STUBS\n";
  7140. else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
  7141. outs() << " S_MOD_INIT_FUNC_POINTERS\n";
  7142. else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
  7143. outs() << " S_MOD_TERM_FUNC_POINTERS\n";
  7144. else if (section_type == MachO::S_COALESCED)
  7145. outs() << " S_COALESCED\n";
  7146. else if (section_type == MachO::S_INTERPOSING)
  7147. outs() << " S_INTERPOSING\n";
  7148. else if (section_type == MachO::S_DTRACE_DOF)
  7149. outs() << " S_DTRACE_DOF\n";
  7150. else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
  7151. outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
  7152. else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
  7153. outs() << " S_THREAD_LOCAL_REGULAR\n";
  7154. else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
  7155. outs() << " S_THREAD_LOCAL_ZEROFILL\n";
  7156. else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
  7157. outs() << " S_THREAD_LOCAL_VARIABLES\n";
  7158. else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
  7159. outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
  7160. else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
  7161. outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
  7162. else
  7163. outs() << format("0x%08" PRIx32, section_type) << "\n";
  7164. outs() << "attributes";
  7165. uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
  7166. if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
  7167. outs() << " PURE_INSTRUCTIONS";
  7168. if (section_attributes & MachO::S_ATTR_NO_TOC)
  7169. outs() << " NO_TOC";
  7170. if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
  7171. outs() << " STRIP_STATIC_SYMS";
  7172. if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
  7173. outs() << " NO_DEAD_STRIP";
  7174. if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
  7175. outs() << " LIVE_SUPPORT";
  7176. if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
  7177. outs() << " SELF_MODIFYING_CODE";
  7178. if (section_attributes & MachO::S_ATTR_DEBUG)
  7179. outs() << " DEBUG";
  7180. if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
  7181. outs() << " SOME_INSTRUCTIONS";
  7182. if (section_attributes & MachO::S_ATTR_EXT_RELOC)
  7183. outs() << " EXT_RELOC";
  7184. if (section_attributes & MachO::S_ATTR_LOC_RELOC)
  7185. outs() << " LOC_RELOC";
  7186. if (section_attributes == 0)
  7187. outs() << " (none)";
  7188. outs() << "\n";
  7189. } else
  7190. outs() << " flags " << format("0x%08" PRIx32, flags) << "\n";
  7191. outs() << " reserved1 " << reserved1;
  7192. if (section_type == MachO::S_SYMBOL_STUBS ||
  7193. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  7194. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  7195. section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  7196. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
  7197. outs() << " (index into indirect symbol table)\n";
  7198. else
  7199. outs() << "\n";
  7200. outs() << " reserved2 " << reserved2;
  7201. if (section_type == MachO::S_SYMBOL_STUBS)
  7202. outs() << " (size of stubs)\n";
  7203. else
  7204. outs() << "\n";
  7205. }
  7206. static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
  7207. uint32_t object_size) {
  7208. outs() << " cmd LC_SYMTAB\n";
  7209. outs() << " cmdsize " << st.cmdsize;
  7210. if (st.cmdsize != sizeof(struct MachO::symtab_command))
  7211. outs() << " Incorrect size\n";
  7212. else
  7213. outs() << "\n";
  7214. outs() << " symoff " << st.symoff;
  7215. if (st.symoff > object_size)
  7216. outs() << " (past end of file)\n";
  7217. else
  7218. outs() << "\n";
  7219. outs() << " nsyms " << st.nsyms;
  7220. uint64_t big_size;
  7221. if (Is64Bit) {
  7222. big_size = st.nsyms;
  7223. big_size *= sizeof(struct MachO::nlist_64);
  7224. big_size += st.symoff;
  7225. if (big_size > object_size)
  7226. outs() << " (past end of file)\n";
  7227. else
  7228. outs() << "\n";
  7229. } else {
  7230. big_size = st.nsyms;
  7231. big_size *= sizeof(struct MachO::nlist);
  7232. big_size += st.symoff;
  7233. if (big_size > object_size)
  7234. outs() << " (past end of file)\n";
  7235. else
  7236. outs() << "\n";
  7237. }
  7238. outs() << " stroff " << st.stroff;
  7239. if (st.stroff > object_size)
  7240. outs() << " (past end of file)\n";
  7241. else
  7242. outs() << "\n";
  7243. outs() << " strsize " << st.strsize;
  7244. big_size = st.stroff;
  7245. big_size += st.strsize;
  7246. if (big_size > object_size)
  7247. outs() << " (past end of file)\n";
  7248. else
  7249. outs() << "\n";
  7250. }
  7251. static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
  7252. uint32_t nsyms, uint32_t object_size,
  7253. bool Is64Bit) {
  7254. outs() << " cmd LC_DYSYMTAB\n";
  7255. outs() << " cmdsize " << dyst.cmdsize;
  7256. if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
  7257. outs() << " Incorrect size\n";
  7258. else
  7259. outs() << "\n";
  7260. outs() << " ilocalsym " << dyst.ilocalsym;
  7261. if (dyst.ilocalsym > nsyms)
  7262. outs() << " (greater than the number of symbols)\n";
  7263. else
  7264. outs() << "\n";
  7265. outs() << " nlocalsym " << dyst.nlocalsym;
  7266. uint64_t big_size;
  7267. big_size = dyst.ilocalsym;
  7268. big_size += dyst.nlocalsym;
  7269. if (big_size > nsyms)
  7270. outs() << " (past the end of the symbol table)\n";
  7271. else
  7272. outs() << "\n";
  7273. outs() << " iextdefsym " << dyst.iextdefsym;
  7274. if (dyst.iextdefsym > nsyms)
  7275. outs() << " (greater than the number of symbols)\n";
  7276. else
  7277. outs() << "\n";
  7278. outs() << " nextdefsym " << dyst.nextdefsym;
  7279. big_size = dyst.iextdefsym;
  7280. big_size += dyst.nextdefsym;
  7281. if (big_size > nsyms)
  7282. outs() << " (past the end of the symbol table)\n";
  7283. else
  7284. outs() << "\n";
  7285. outs() << " iundefsym " << dyst.iundefsym;
  7286. if (dyst.iundefsym > nsyms)
  7287. outs() << " (greater than the number of symbols)\n";
  7288. else
  7289. outs() << "\n";
  7290. outs() << " nundefsym " << dyst.nundefsym;
  7291. big_size = dyst.iundefsym;
  7292. big_size += dyst.nundefsym;
  7293. if (big_size > nsyms)
  7294. outs() << " (past the end of the symbol table)\n";
  7295. else
  7296. outs() << "\n";
  7297. outs() << " tocoff " << dyst.tocoff;
  7298. if (dyst.tocoff > object_size)
  7299. outs() << " (past end of file)\n";
  7300. else
  7301. outs() << "\n";
  7302. outs() << " ntoc " << dyst.ntoc;
  7303. big_size = dyst.ntoc;
  7304. big_size *= sizeof(struct MachO::dylib_table_of_contents);
  7305. big_size += dyst.tocoff;
  7306. if (big_size > object_size)
  7307. outs() << " (past end of file)\n";
  7308. else
  7309. outs() << "\n";
  7310. outs() << " modtaboff " << dyst.modtaboff;
  7311. if (dyst.modtaboff > object_size)
  7312. outs() << " (past end of file)\n";
  7313. else
  7314. outs() << "\n";
  7315. outs() << " nmodtab " << dyst.nmodtab;
  7316. uint64_t modtabend;
  7317. if (Is64Bit) {
  7318. modtabend = dyst.nmodtab;
  7319. modtabend *= sizeof(struct MachO::dylib_module_64);
  7320. modtabend += dyst.modtaboff;
  7321. } else {
  7322. modtabend = dyst.nmodtab;
  7323. modtabend *= sizeof(struct MachO::dylib_module);
  7324. modtabend += dyst.modtaboff;
  7325. }
  7326. if (modtabend > object_size)
  7327. outs() << " (past end of file)\n";
  7328. else
  7329. outs() << "\n";
  7330. outs() << " extrefsymoff " << dyst.extrefsymoff;
  7331. if (dyst.extrefsymoff > object_size)
  7332. outs() << " (past end of file)\n";
  7333. else
  7334. outs() << "\n";
  7335. outs() << " nextrefsyms " << dyst.nextrefsyms;
  7336. big_size = dyst.nextrefsyms;
  7337. big_size *= sizeof(struct MachO::dylib_reference);
  7338. big_size += dyst.extrefsymoff;
  7339. if (big_size > object_size)
  7340. outs() << " (past end of file)\n";
  7341. else
  7342. outs() << "\n";
  7343. outs() << " indirectsymoff " << dyst.indirectsymoff;
  7344. if (dyst.indirectsymoff > object_size)
  7345. outs() << " (past end of file)\n";
  7346. else
  7347. outs() << "\n";
  7348. outs() << " nindirectsyms " << dyst.nindirectsyms;
  7349. big_size = dyst.nindirectsyms;
  7350. big_size *= sizeof(uint32_t);
  7351. big_size += dyst.indirectsymoff;
  7352. if (big_size > object_size)
  7353. outs() << " (past end of file)\n";
  7354. else
  7355. outs() << "\n";
  7356. outs() << " extreloff " << dyst.extreloff;
  7357. if (dyst.extreloff > object_size)
  7358. outs() << " (past end of file)\n";
  7359. else
  7360. outs() << "\n";
  7361. outs() << " nextrel " << dyst.nextrel;
  7362. big_size = dyst.nextrel;
  7363. big_size *= sizeof(struct MachO::relocation_info);
  7364. big_size += dyst.extreloff;
  7365. if (big_size > object_size)
  7366. outs() << " (past end of file)\n";
  7367. else
  7368. outs() << "\n";
  7369. outs() << " locreloff " << dyst.locreloff;
  7370. if (dyst.locreloff > object_size)
  7371. outs() << " (past end of file)\n";
  7372. else
  7373. outs() << "\n";
  7374. outs() << " nlocrel " << dyst.nlocrel;
  7375. big_size = dyst.nlocrel;
  7376. big_size *= sizeof(struct MachO::relocation_info);
  7377. big_size += dyst.locreloff;
  7378. if (big_size > object_size)
  7379. outs() << " (past end of file)\n";
  7380. else
  7381. outs() << "\n";
  7382. }
  7383. static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
  7384. uint32_t object_size) {
  7385. if (dc.cmd == MachO::LC_DYLD_INFO)
  7386. outs() << " cmd LC_DYLD_INFO\n";
  7387. else
  7388. outs() << " cmd LC_DYLD_INFO_ONLY\n";
  7389. outs() << " cmdsize " << dc.cmdsize;
  7390. if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
  7391. outs() << " Incorrect size\n";
  7392. else
  7393. outs() << "\n";
  7394. outs() << " rebase_off " << dc.rebase_off;
  7395. if (dc.rebase_off > object_size)
  7396. outs() << " (past end of file)\n";
  7397. else
  7398. outs() << "\n";
  7399. outs() << " rebase_size " << dc.rebase_size;
  7400. uint64_t big_size;
  7401. big_size = dc.rebase_off;
  7402. big_size += dc.rebase_size;
  7403. if (big_size > object_size)
  7404. outs() << " (past end of file)\n";
  7405. else
  7406. outs() << "\n";
  7407. outs() << " bind_off " << dc.bind_off;
  7408. if (dc.bind_off > object_size)
  7409. outs() << " (past end of file)\n";
  7410. else
  7411. outs() << "\n";
  7412. outs() << " bind_size " << dc.bind_size;
  7413. big_size = dc.bind_off;
  7414. big_size += dc.bind_size;
  7415. if (big_size > object_size)
  7416. outs() << " (past end of file)\n";
  7417. else
  7418. outs() << "\n";
  7419. outs() << " weak_bind_off " << dc.weak_bind_off;
  7420. if (dc.weak_bind_off > object_size)
  7421. outs() << " (past end of file)\n";
  7422. else
  7423. outs() << "\n";
  7424. outs() << " weak_bind_size " << dc.weak_bind_size;
  7425. big_size = dc.weak_bind_off;
  7426. big_size += dc.weak_bind_size;
  7427. if (big_size > object_size)
  7428. outs() << " (past end of file)\n";
  7429. else
  7430. outs() << "\n";
  7431. outs() << " lazy_bind_off " << dc.lazy_bind_off;
  7432. if (dc.lazy_bind_off > object_size)
  7433. outs() << " (past end of file)\n";
  7434. else
  7435. outs() << "\n";
  7436. outs() << " lazy_bind_size " << dc.lazy_bind_size;
  7437. big_size = dc.lazy_bind_off;
  7438. big_size += dc.lazy_bind_size;
  7439. if (big_size > object_size)
  7440. outs() << " (past end of file)\n";
  7441. else
  7442. outs() << "\n";
  7443. outs() << " export_off " << dc.export_off;
  7444. if (dc.export_off > object_size)
  7445. outs() << " (past end of file)\n";
  7446. else
  7447. outs() << "\n";
  7448. outs() << " export_size " << dc.export_size;
  7449. big_size = dc.export_off;
  7450. big_size += dc.export_size;
  7451. if (big_size > object_size)
  7452. outs() << " (past end of file)\n";
  7453. else
  7454. outs() << "\n";
  7455. }
  7456. static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
  7457. const char *Ptr) {
  7458. if (dyld.cmd == MachO::LC_ID_DYLINKER)
  7459. outs() << " cmd LC_ID_DYLINKER\n";
  7460. else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
  7461. outs() << " cmd LC_LOAD_DYLINKER\n";
  7462. else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
  7463. outs() << " cmd LC_DYLD_ENVIRONMENT\n";
  7464. else
  7465. outs() << " cmd ?(" << dyld.cmd << ")\n";
  7466. outs() << " cmdsize " << dyld.cmdsize;
  7467. if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
  7468. outs() << " Incorrect size\n";
  7469. else
  7470. outs() << "\n";
  7471. if (dyld.name >= dyld.cmdsize)
  7472. outs() << " name ?(bad offset " << dyld.name << ")\n";
  7473. else {
  7474. const char *P = (const char *)(Ptr) + dyld.name;
  7475. outs() << " name " << P << " (offset " << dyld.name << ")\n";
  7476. }
  7477. }
  7478. static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
  7479. outs() << " cmd LC_UUID\n";
  7480. outs() << " cmdsize " << uuid.cmdsize;
  7481. if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
  7482. outs() << " Incorrect size\n";
  7483. else
  7484. outs() << "\n";
  7485. outs() << " uuid ";
  7486. for (int i = 0; i < 16; ++i) {
  7487. outs() << format("%02" PRIX32, uuid.uuid[i]);
  7488. if (i == 3 || i == 5 || i == 7 || i == 9)
  7489. outs() << "-";
  7490. }
  7491. outs() << "\n";
  7492. }
  7493. static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
  7494. outs() << " cmd LC_RPATH\n";
  7495. outs() << " cmdsize " << rpath.cmdsize;
  7496. if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
  7497. outs() << " Incorrect size\n";
  7498. else
  7499. outs() << "\n";
  7500. if (rpath.path >= rpath.cmdsize)
  7501. outs() << " path ?(bad offset " << rpath.path << ")\n";
  7502. else {
  7503. const char *P = (const char *)(Ptr) + rpath.path;
  7504. outs() << " path " << P << " (offset " << rpath.path << ")\n";
  7505. }
  7506. }
  7507. static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
  7508. StringRef LoadCmdName;
  7509. switch (vd.cmd) {
  7510. case MachO::LC_VERSION_MIN_MACOSX:
  7511. LoadCmdName = "LC_VERSION_MIN_MACOSX";
  7512. break;
  7513. case MachO::LC_VERSION_MIN_IPHONEOS:
  7514. LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
  7515. break;
  7516. case MachO::LC_VERSION_MIN_TVOS:
  7517. LoadCmdName = "LC_VERSION_MIN_TVOS";
  7518. break;
  7519. case MachO::LC_VERSION_MIN_WATCHOS:
  7520. LoadCmdName = "LC_VERSION_MIN_WATCHOS";
  7521. break;
  7522. default:
  7523. llvm_unreachable("Unknown version min load command");
  7524. }
  7525. outs() << " cmd " << LoadCmdName << '\n';
  7526. outs() << " cmdsize " << vd.cmdsize;
  7527. if (vd.cmdsize != sizeof(struct MachO::version_min_command))
  7528. outs() << " Incorrect size\n";
  7529. else
  7530. outs() << "\n";
  7531. outs() << " version "
  7532. << MachOObjectFile::getVersionMinMajor(vd, false) << "."
  7533. << MachOObjectFile::getVersionMinMinor(vd, false);
  7534. uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
  7535. if (Update != 0)
  7536. outs() << "." << Update;
  7537. outs() << "\n";
  7538. if (vd.sdk == 0)
  7539. outs() << " sdk n/a";
  7540. else {
  7541. outs() << " sdk "
  7542. << MachOObjectFile::getVersionMinMajor(vd, true) << "."
  7543. << MachOObjectFile::getVersionMinMinor(vd, true);
  7544. }
  7545. Update = MachOObjectFile::getVersionMinUpdate(vd, true);
  7546. if (Update != 0)
  7547. outs() << "." << Update;
  7548. outs() << "\n";
  7549. }
  7550. static void PrintSourceVersionCommand(MachO::source_version_command sd) {
  7551. outs() << " cmd LC_SOURCE_VERSION\n";
  7552. outs() << " cmdsize " << sd.cmdsize;
  7553. if (sd.cmdsize != sizeof(struct MachO::source_version_command))
  7554. outs() << " Incorrect size\n";
  7555. else
  7556. outs() << "\n";
  7557. uint64_t a = (sd.version >> 40) & 0xffffff;
  7558. uint64_t b = (sd.version >> 30) & 0x3ff;
  7559. uint64_t c = (sd.version >> 20) & 0x3ff;
  7560. uint64_t d = (sd.version >> 10) & 0x3ff;
  7561. uint64_t e = sd.version & 0x3ff;
  7562. outs() << " version " << a << "." << b;
  7563. if (e != 0)
  7564. outs() << "." << c << "." << d << "." << e;
  7565. else if (d != 0)
  7566. outs() << "." << c << "." << d;
  7567. else if (c != 0)
  7568. outs() << "." << c;
  7569. outs() << "\n";
  7570. }
  7571. static void PrintEntryPointCommand(MachO::entry_point_command ep) {
  7572. outs() << " cmd LC_MAIN\n";
  7573. outs() << " cmdsize " << ep.cmdsize;
  7574. if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
  7575. outs() << " Incorrect size\n";
  7576. else
  7577. outs() << "\n";
  7578. outs() << " entryoff " << ep.entryoff << "\n";
  7579. outs() << " stacksize " << ep.stacksize << "\n";
  7580. }
  7581. static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
  7582. uint32_t object_size) {
  7583. outs() << " cmd LC_ENCRYPTION_INFO\n";
  7584. outs() << " cmdsize " << ec.cmdsize;
  7585. if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
  7586. outs() << " Incorrect size\n";
  7587. else
  7588. outs() << "\n";
  7589. outs() << " cryptoff " << ec.cryptoff;
  7590. if (ec.cryptoff > object_size)
  7591. outs() << " (past end of file)\n";
  7592. else
  7593. outs() << "\n";
  7594. outs() << " cryptsize " << ec.cryptsize;
  7595. if (ec.cryptsize > object_size)
  7596. outs() << " (past end of file)\n";
  7597. else
  7598. outs() << "\n";
  7599. outs() << " cryptid " << ec.cryptid << "\n";
  7600. }
  7601. static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
  7602. uint32_t object_size) {
  7603. outs() << " cmd LC_ENCRYPTION_INFO_64\n";
  7604. outs() << " cmdsize " << ec.cmdsize;
  7605. if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
  7606. outs() << " Incorrect size\n";
  7607. else
  7608. outs() << "\n";
  7609. outs() << " cryptoff " << ec.cryptoff;
  7610. if (ec.cryptoff > object_size)
  7611. outs() << " (past end of file)\n";
  7612. else
  7613. outs() << "\n";
  7614. outs() << " cryptsize " << ec.cryptsize;
  7615. if (ec.cryptsize > object_size)
  7616. outs() << " (past end of file)\n";
  7617. else
  7618. outs() << "\n";
  7619. outs() << " cryptid " << ec.cryptid << "\n";
  7620. outs() << " pad " << ec.pad << "\n";
  7621. }
  7622. static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
  7623. const char *Ptr) {
  7624. outs() << " cmd LC_LINKER_OPTION\n";
  7625. outs() << " cmdsize " << lo.cmdsize;
  7626. if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
  7627. outs() << " Incorrect size\n";
  7628. else
  7629. outs() << "\n";
  7630. outs() << " count " << lo.count << "\n";
  7631. const char *string = Ptr + sizeof(struct MachO::linker_option_command);
  7632. uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
  7633. uint32_t i = 0;
  7634. while (left > 0) {
  7635. while (*string == '\0' && left > 0) {
  7636. string++;
  7637. left--;
  7638. }
  7639. if (left > 0) {
  7640. i++;
  7641. outs() << " string #" << i << " " << format("%.*s\n", left, string);
  7642. uint32_t NullPos = StringRef(string, left).find('\0');
  7643. uint32_t len = std::min(NullPos, left) + 1;
  7644. string += len;
  7645. left -= len;
  7646. }
  7647. }
  7648. if (lo.count != i)
  7649. outs() << " count " << lo.count << " does not match number of strings "
  7650. << i << "\n";
  7651. }
  7652. static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
  7653. const char *Ptr) {
  7654. outs() << " cmd LC_SUB_FRAMEWORK\n";
  7655. outs() << " cmdsize " << sub.cmdsize;
  7656. if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
  7657. outs() << " Incorrect size\n";
  7658. else
  7659. outs() << "\n";
  7660. if (sub.umbrella < sub.cmdsize) {
  7661. const char *P = Ptr + sub.umbrella;
  7662. outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n";
  7663. } else {
  7664. outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n";
  7665. }
  7666. }
  7667. static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
  7668. const char *Ptr) {
  7669. outs() << " cmd LC_SUB_UMBRELLA\n";
  7670. outs() << " cmdsize " << sub.cmdsize;
  7671. if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
  7672. outs() << " Incorrect size\n";
  7673. else
  7674. outs() << "\n";
  7675. if (sub.sub_umbrella < sub.cmdsize) {
  7676. const char *P = Ptr + sub.sub_umbrella;
  7677. outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
  7678. } else {
  7679. outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
  7680. }
  7681. }
  7682. static void PrintSubLibraryCommand(MachO::sub_library_command sub,
  7683. const char *Ptr) {
  7684. outs() << " cmd LC_SUB_LIBRARY\n";
  7685. outs() << " cmdsize " << sub.cmdsize;
  7686. if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
  7687. outs() << " Incorrect size\n";
  7688. else
  7689. outs() << "\n";
  7690. if (sub.sub_library < sub.cmdsize) {
  7691. const char *P = Ptr + sub.sub_library;
  7692. outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n";
  7693. } else {
  7694. outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n";
  7695. }
  7696. }
  7697. static void PrintSubClientCommand(MachO::sub_client_command sub,
  7698. const char *Ptr) {
  7699. outs() << " cmd LC_SUB_CLIENT\n";
  7700. outs() << " cmdsize " << sub.cmdsize;
  7701. if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
  7702. outs() << " Incorrect size\n";
  7703. else
  7704. outs() << "\n";
  7705. if (sub.client < sub.cmdsize) {
  7706. const char *P = Ptr + sub.client;
  7707. outs() << " client " << P << " (offset " << sub.client << ")\n";
  7708. } else {
  7709. outs() << " client ?(bad offset " << sub.client << ")\n";
  7710. }
  7711. }
  7712. static void PrintRoutinesCommand(MachO::routines_command r) {
  7713. outs() << " cmd LC_ROUTINES\n";
  7714. outs() << " cmdsize " << r.cmdsize;
  7715. if (r.cmdsize != sizeof(struct MachO::routines_command))
  7716. outs() << " Incorrect size\n";
  7717. else
  7718. outs() << "\n";
  7719. outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
  7720. outs() << " init_module " << r.init_module << "\n";
  7721. outs() << " reserved1 " << r.reserved1 << "\n";
  7722. outs() << " reserved2 " << r.reserved2 << "\n";
  7723. outs() << " reserved3 " << r.reserved3 << "\n";
  7724. outs() << " reserved4 " << r.reserved4 << "\n";
  7725. outs() << " reserved5 " << r.reserved5 << "\n";
  7726. outs() << " reserved6 " << r.reserved6 << "\n";
  7727. }
  7728. static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
  7729. outs() << " cmd LC_ROUTINES_64\n";
  7730. outs() << " cmdsize " << r.cmdsize;
  7731. if (r.cmdsize != sizeof(struct MachO::routines_command_64))
  7732. outs() << " Incorrect size\n";
  7733. else
  7734. outs() << "\n";
  7735. outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
  7736. outs() << " init_module " << r.init_module << "\n";
  7737. outs() << " reserved1 " << r.reserved1 << "\n";
  7738. outs() << " reserved2 " << r.reserved2 << "\n";
  7739. outs() << " reserved3 " << r.reserved3 << "\n";
  7740. outs() << " reserved4 " << r.reserved4 << "\n";
  7741. outs() << " reserved5 " << r.reserved5 << "\n";
  7742. outs() << " reserved6 " << r.reserved6 << "\n";
  7743. }
  7744. static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
  7745. outs() << " rax " << format("0x%016" PRIx64, cpu64.rax);
  7746. outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
  7747. outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
  7748. outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx);
  7749. outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
  7750. outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
  7751. outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp);
  7752. outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
  7753. outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n";
  7754. outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9);
  7755. outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
  7756. outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n";
  7757. outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12);
  7758. outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
  7759. outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n";
  7760. outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15);
  7761. outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
  7762. outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags);
  7763. outs() << " cs " << format("0x%016" PRIx64, cpu64.cs);
  7764. outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n";
  7765. outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n";
  7766. }
  7767. static void Print_mmst_reg(MachO::mmst_reg_t &r) {
  7768. uint32_t f;
  7769. outs() << "\t mmst_reg ";
  7770. for (f = 0; f < 10; f++)
  7771. outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
  7772. outs() << "\n";
  7773. outs() << "\t mmst_rsrv ";
  7774. for (f = 0; f < 6; f++)
  7775. outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
  7776. outs() << "\n";
  7777. }
  7778. static void Print_xmm_reg(MachO::xmm_reg_t &r) {
  7779. uint32_t f;
  7780. outs() << "\t xmm_reg ";
  7781. for (f = 0; f < 16; f++)
  7782. outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
  7783. outs() << "\n";
  7784. }
  7785. static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
  7786. outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0];
  7787. outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
  7788. outs() << "\t control: invalid " << fpu.fpu_fcw.invalid;
  7789. outs() << " denorm " << fpu.fpu_fcw.denorm;
  7790. outs() << " zdiv " << fpu.fpu_fcw.zdiv;
  7791. outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
  7792. outs() << " undfl " << fpu.fpu_fcw.undfl;
  7793. outs() << " precis " << fpu.fpu_fcw.precis << "\n";
  7794. outs() << "\t\t pc ";
  7795. if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
  7796. outs() << "FP_PREC_24B ";
  7797. else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
  7798. outs() << "FP_PREC_53B ";
  7799. else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
  7800. outs() << "FP_PREC_64B ";
  7801. else
  7802. outs() << fpu.fpu_fcw.pc << " ";
  7803. outs() << "rc ";
  7804. if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
  7805. outs() << "FP_RND_NEAR ";
  7806. else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
  7807. outs() << "FP_RND_DOWN ";
  7808. else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
  7809. outs() << "FP_RND_UP ";
  7810. else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
  7811. outs() << "FP_CHOP ";
  7812. outs() << "\n";
  7813. outs() << "\t status: invalid " << fpu.fpu_fsw.invalid;
  7814. outs() << " denorm " << fpu.fpu_fsw.denorm;
  7815. outs() << " zdiv " << fpu.fpu_fsw.zdiv;
  7816. outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
  7817. outs() << " undfl " << fpu.fpu_fsw.undfl;
  7818. outs() << " precis " << fpu.fpu_fsw.precis;
  7819. outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
  7820. outs() << "\t errsumm " << fpu.fpu_fsw.errsumm;
  7821. outs() << " c0 " << fpu.fpu_fsw.c0;
  7822. outs() << " c1 " << fpu.fpu_fsw.c1;
  7823. outs() << " c2 " << fpu.fpu_fsw.c2;
  7824. outs() << " tos " << fpu.fpu_fsw.tos;
  7825. outs() << " c3 " << fpu.fpu_fsw.c3;
  7826. outs() << " busy " << fpu.fpu_fsw.busy << "\n";
  7827. outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
  7828. outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
  7829. outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
  7830. outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
  7831. outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
  7832. outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
  7833. outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
  7834. outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
  7835. outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
  7836. outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
  7837. outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
  7838. outs() << "\n";
  7839. outs() << "\t fpu_stmm0:\n";
  7840. Print_mmst_reg(fpu.fpu_stmm0);
  7841. outs() << "\t fpu_stmm1:\n";
  7842. Print_mmst_reg(fpu.fpu_stmm1);
  7843. outs() << "\t fpu_stmm2:\n";
  7844. Print_mmst_reg(fpu.fpu_stmm2);
  7845. outs() << "\t fpu_stmm3:\n";
  7846. Print_mmst_reg(fpu.fpu_stmm3);
  7847. outs() << "\t fpu_stmm4:\n";
  7848. Print_mmst_reg(fpu.fpu_stmm4);
  7849. outs() << "\t fpu_stmm5:\n";
  7850. Print_mmst_reg(fpu.fpu_stmm5);
  7851. outs() << "\t fpu_stmm6:\n";
  7852. Print_mmst_reg(fpu.fpu_stmm6);
  7853. outs() << "\t fpu_stmm7:\n";
  7854. Print_mmst_reg(fpu.fpu_stmm7);
  7855. outs() << "\t fpu_xmm0:\n";
  7856. Print_xmm_reg(fpu.fpu_xmm0);
  7857. outs() << "\t fpu_xmm1:\n";
  7858. Print_xmm_reg(fpu.fpu_xmm1);
  7859. outs() << "\t fpu_xmm2:\n";
  7860. Print_xmm_reg(fpu.fpu_xmm2);
  7861. outs() << "\t fpu_xmm3:\n";
  7862. Print_xmm_reg(fpu.fpu_xmm3);
  7863. outs() << "\t fpu_xmm4:\n";
  7864. Print_xmm_reg(fpu.fpu_xmm4);
  7865. outs() << "\t fpu_xmm5:\n";
  7866. Print_xmm_reg(fpu.fpu_xmm5);
  7867. outs() << "\t fpu_xmm6:\n";
  7868. Print_xmm_reg(fpu.fpu_xmm6);
  7869. outs() << "\t fpu_xmm7:\n";
  7870. Print_xmm_reg(fpu.fpu_xmm7);
  7871. outs() << "\t fpu_xmm8:\n";
  7872. Print_xmm_reg(fpu.fpu_xmm8);
  7873. outs() << "\t fpu_xmm9:\n";
  7874. Print_xmm_reg(fpu.fpu_xmm9);
  7875. outs() << "\t fpu_xmm10:\n";
  7876. Print_xmm_reg(fpu.fpu_xmm10);
  7877. outs() << "\t fpu_xmm11:\n";
  7878. Print_xmm_reg(fpu.fpu_xmm11);
  7879. outs() << "\t fpu_xmm12:\n";
  7880. Print_xmm_reg(fpu.fpu_xmm12);
  7881. outs() << "\t fpu_xmm13:\n";
  7882. Print_xmm_reg(fpu.fpu_xmm13);
  7883. outs() << "\t fpu_xmm14:\n";
  7884. Print_xmm_reg(fpu.fpu_xmm14);
  7885. outs() << "\t fpu_xmm15:\n";
  7886. Print_xmm_reg(fpu.fpu_xmm15);
  7887. outs() << "\t fpu_rsrv4:\n";
  7888. for (uint32_t f = 0; f < 6; f++) {
  7889. outs() << "\t ";
  7890. for (uint32_t g = 0; g < 16; g++)
  7891. outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
  7892. outs() << "\n";
  7893. }
  7894. outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
  7895. outs() << "\n";
  7896. }
  7897. static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
  7898. outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno);
  7899. outs() << " err " << format("0x%08" PRIx32, exc64.err);
  7900. outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
  7901. }
  7902. static void Print_arm_thread_state32_t(MachO::arm_thread_state32_t &cpu32) {
  7903. outs() << "\t r0 " << format("0x%08" PRIx32, cpu32.r[0]);
  7904. outs() << " r1 " << format("0x%08" PRIx32, cpu32.r[1]);
  7905. outs() << " r2 " << format("0x%08" PRIx32, cpu32.r[2]);
  7906. outs() << " r3 " << format("0x%08" PRIx32, cpu32.r[3]) << "\n";
  7907. outs() << "\t r4 " << format("0x%08" PRIx32, cpu32.r[4]);
  7908. outs() << " r5 " << format("0x%08" PRIx32, cpu32.r[5]);
  7909. outs() << " r6 " << format("0x%08" PRIx32, cpu32.r[6]);
  7910. outs() << " r7 " << format("0x%08" PRIx32, cpu32.r[7]) << "\n";
  7911. outs() << "\t r8 " << format("0x%08" PRIx32, cpu32.r[8]);
  7912. outs() << " r9 " << format("0x%08" PRIx32, cpu32.r[9]);
  7913. outs() << " r10 " << format("0x%08" PRIx32, cpu32.r[10]);
  7914. outs() << " r11 " << format("0x%08" PRIx32, cpu32.r[11]) << "\n";
  7915. outs() << "\t r12 " << format("0x%08" PRIx32, cpu32.r[12]);
  7916. outs() << " sp " << format("0x%08" PRIx32, cpu32.sp);
  7917. outs() << " lr " << format("0x%08" PRIx32, cpu32.lr);
  7918. outs() << " pc " << format("0x%08" PRIx32, cpu32.pc) << "\n";
  7919. outs() << "\t cpsr " << format("0x%08" PRIx32, cpu32.cpsr) << "\n";
  7920. }
  7921. static void Print_arm_thread_state64_t(MachO::arm_thread_state64_t &cpu64) {
  7922. outs() << "\t x0 " << format("0x%016" PRIx64, cpu64.x[0]);
  7923. outs() << " x1 " << format("0x%016" PRIx64, cpu64.x[1]);
  7924. outs() << " x2 " << format("0x%016" PRIx64, cpu64.x[2]) << "\n";
  7925. outs() << "\t x3 " << format("0x%016" PRIx64, cpu64.x[3]);
  7926. outs() << " x4 " << format("0x%016" PRIx64, cpu64.x[4]);
  7927. outs() << " x5 " << format("0x%016" PRIx64, cpu64.x[5]) << "\n";
  7928. outs() << "\t x6 " << format("0x%016" PRIx64, cpu64.x[6]);
  7929. outs() << " x7 " << format("0x%016" PRIx64, cpu64.x[7]);
  7930. outs() << " x8 " << format("0x%016" PRIx64, cpu64.x[8]) << "\n";
  7931. outs() << "\t x9 " << format("0x%016" PRIx64, cpu64.x[9]);
  7932. outs() << " x10 " << format("0x%016" PRIx64, cpu64.x[10]);
  7933. outs() << " x11 " << format("0x%016" PRIx64, cpu64.x[11]) << "\n";
  7934. outs() << "\t x12 " << format("0x%016" PRIx64, cpu64.x[12]);
  7935. outs() << " x13 " << format("0x%016" PRIx64, cpu64.x[13]);
  7936. outs() << " x14 " << format("0x%016" PRIx64, cpu64.x[14]) << "\n";
  7937. outs() << "\t x15 " << format("0x%016" PRIx64, cpu64.x[15]);
  7938. outs() << " x16 " << format("0x%016" PRIx64, cpu64.x[16]);
  7939. outs() << " x17 " << format("0x%016" PRIx64, cpu64.x[17]) << "\n";
  7940. outs() << "\t x18 " << format("0x%016" PRIx64, cpu64.x[18]);
  7941. outs() << " x19 " << format("0x%016" PRIx64, cpu64.x[19]);
  7942. outs() << " x20 " << format("0x%016" PRIx64, cpu64.x[20]) << "\n";
  7943. outs() << "\t x21 " << format("0x%016" PRIx64, cpu64.x[21]);
  7944. outs() << " x22 " << format("0x%016" PRIx64, cpu64.x[22]);
  7945. outs() << " x23 " << format("0x%016" PRIx64, cpu64.x[23]) << "\n";
  7946. outs() << "\t x24 " << format("0x%016" PRIx64, cpu64.x[24]);
  7947. outs() << " x25 " << format("0x%016" PRIx64, cpu64.x[25]);
  7948. outs() << " x26 " << format("0x%016" PRIx64, cpu64.x[26]) << "\n";
  7949. outs() << "\t x27 " << format("0x%016" PRIx64, cpu64.x[27]);
  7950. outs() << " x28 " << format("0x%016" PRIx64, cpu64.x[28]);
  7951. outs() << " fp " << format("0x%016" PRIx64, cpu64.fp) << "\n";
  7952. outs() << "\t lr " << format("0x%016" PRIx64, cpu64.lr);
  7953. outs() << " sp " << format("0x%016" PRIx64, cpu64.sp);
  7954. outs() << " pc " << format("0x%016" PRIx64, cpu64.pc) << "\n";
  7955. outs() << "\t cpsr " << format("0x%08" PRIx32, cpu64.cpsr) << "\n";
  7956. }
  7957. static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
  7958. bool isLittleEndian, uint32_t cputype) {
  7959. if (t.cmd == MachO::LC_THREAD)
  7960. outs() << " cmd LC_THREAD\n";
  7961. else if (t.cmd == MachO::LC_UNIXTHREAD)
  7962. outs() << " cmd LC_UNIXTHREAD\n";
  7963. else
  7964. outs() << " cmd " << t.cmd << " (unknown)\n";
  7965. outs() << " cmdsize " << t.cmdsize;
  7966. if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
  7967. outs() << " Incorrect size\n";
  7968. else
  7969. outs() << "\n";
  7970. const char *begin = Ptr + sizeof(struct MachO::thread_command);
  7971. const char *end = Ptr + t.cmdsize;
  7972. uint32_t flavor, count, left;
  7973. if (cputype == MachO::CPU_TYPE_X86_64) {
  7974. while (begin < end) {
  7975. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  7976. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  7977. begin += sizeof(uint32_t);
  7978. } else {
  7979. flavor = 0;
  7980. begin = end;
  7981. }
  7982. if (isLittleEndian != sys::IsLittleEndianHost)
  7983. sys::swapByteOrder(flavor);
  7984. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  7985. memcpy((char *)&count, begin, sizeof(uint32_t));
  7986. begin += sizeof(uint32_t);
  7987. } else {
  7988. count = 0;
  7989. begin = end;
  7990. }
  7991. if (isLittleEndian != sys::IsLittleEndianHost)
  7992. sys::swapByteOrder(count);
  7993. if (flavor == MachO::x86_THREAD_STATE64) {
  7994. outs() << " flavor x86_THREAD_STATE64\n";
  7995. if (count == MachO::x86_THREAD_STATE64_COUNT)
  7996. outs() << " count x86_THREAD_STATE64_COUNT\n";
  7997. else
  7998. outs() << " count " << count
  7999. << " (not x86_THREAD_STATE64_COUNT)\n";
  8000. MachO::x86_thread_state64_t cpu64;
  8001. left = end - begin;
  8002. if (left >= sizeof(MachO::x86_thread_state64_t)) {
  8003. memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
  8004. begin += sizeof(MachO::x86_thread_state64_t);
  8005. } else {
  8006. memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
  8007. memcpy(&cpu64, begin, left);
  8008. begin += left;
  8009. }
  8010. if (isLittleEndian != sys::IsLittleEndianHost)
  8011. swapStruct(cpu64);
  8012. Print_x86_thread_state64_t(cpu64);
  8013. } else if (flavor == MachO::x86_THREAD_STATE) {
  8014. outs() << " flavor x86_THREAD_STATE\n";
  8015. if (count == MachO::x86_THREAD_STATE_COUNT)
  8016. outs() << " count x86_THREAD_STATE_COUNT\n";
  8017. else
  8018. outs() << " count " << count
  8019. << " (not x86_THREAD_STATE_COUNT)\n";
  8020. struct MachO::x86_thread_state_t ts;
  8021. left = end - begin;
  8022. if (left >= sizeof(MachO::x86_thread_state_t)) {
  8023. memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
  8024. begin += sizeof(MachO::x86_thread_state_t);
  8025. } else {
  8026. memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
  8027. memcpy(&ts, begin, left);
  8028. begin += left;
  8029. }
  8030. if (isLittleEndian != sys::IsLittleEndianHost)
  8031. swapStruct(ts);
  8032. if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
  8033. outs() << "\t tsh.flavor x86_THREAD_STATE64 ";
  8034. if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
  8035. outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
  8036. else
  8037. outs() << "tsh.count " << ts.tsh.count
  8038. << " (not x86_THREAD_STATE64_COUNT\n";
  8039. Print_x86_thread_state64_t(ts.uts.ts64);
  8040. } else {
  8041. outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
  8042. << ts.tsh.count << "\n";
  8043. }
  8044. } else if (flavor == MachO::x86_FLOAT_STATE) {
  8045. outs() << " flavor x86_FLOAT_STATE\n";
  8046. if (count == MachO::x86_FLOAT_STATE_COUNT)
  8047. outs() << " count x86_FLOAT_STATE_COUNT\n";
  8048. else
  8049. outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
  8050. struct MachO::x86_float_state_t fs;
  8051. left = end - begin;
  8052. if (left >= sizeof(MachO::x86_float_state_t)) {
  8053. memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
  8054. begin += sizeof(MachO::x86_float_state_t);
  8055. } else {
  8056. memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
  8057. memcpy(&fs, begin, left);
  8058. begin += left;
  8059. }
  8060. if (isLittleEndian != sys::IsLittleEndianHost)
  8061. swapStruct(fs);
  8062. if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
  8063. outs() << "\t fsh.flavor x86_FLOAT_STATE64 ";
  8064. if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
  8065. outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
  8066. else
  8067. outs() << "fsh.count " << fs.fsh.count
  8068. << " (not x86_FLOAT_STATE64_COUNT\n";
  8069. Print_x86_float_state_t(fs.ufs.fs64);
  8070. } else {
  8071. outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count "
  8072. << fs.fsh.count << "\n";
  8073. }
  8074. } else if (flavor == MachO::x86_EXCEPTION_STATE) {
  8075. outs() << " flavor x86_EXCEPTION_STATE\n";
  8076. if (count == MachO::x86_EXCEPTION_STATE_COUNT)
  8077. outs() << " count x86_EXCEPTION_STATE_COUNT\n";
  8078. else
  8079. outs() << " count " << count
  8080. << " (not x86_EXCEPTION_STATE_COUNT)\n";
  8081. struct MachO::x86_exception_state_t es;
  8082. left = end - begin;
  8083. if (left >= sizeof(MachO::x86_exception_state_t)) {
  8084. memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
  8085. begin += sizeof(MachO::x86_exception_state_t);
  8086. } else {
  8087. memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
  8088. memcpy(&es, begin, left);
  8089. begin += left;
  8090. }
  8091. if (isLittleEndian != sys::IsLittleEndianHost)
  8092. swapStruct(es);
  8093. if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
  8094. outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n";
  8095. if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
  8096. outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n";
  8097. else
  8098. outs() << "\t esh.count " << es.esh.count
  8099. << " (not x86_EXCEPTION_STATE64_COUNT\n";
  8100. Print_x86_exception_state_t(es.ues.es64);
  8101. } else {
  8102. outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
  8103. << es.esh.count << "\n";
  8104. }
  8105. } else {
  8106. outs() << " flavor " << flavor << " (unknown)\n";
  8107. outs() << " count " << count << "\n";
  8108. outs() << " state (unknown)\n";
  8109. begin += count * sizeof(uint32_t);
  8110. }
  8111. }
  8112. } else if (cputype == MachO::CPU_TYPE_ARM) {
  8113. while (begin < end) {
  8114. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8115. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  8116. begin += sizeof(uint32_t);
  8117. } else {
  8118. flavor = 0;
  8119. begin = end;
  8120. }
  8121. if (isLittleEndian != sys::IsLittleEndianHost)
  8122. sys::swapByteOrder(flavor);
  8123. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8124. memcpy((char *)&count, begin, sizeof(uint32_t));
  8125. begin += sizeof(uint32_t);
  8126. } else {
  8127. count = 0;
  8128. begin = end;
  8129. }
  8130. if (isLittleEndian != sys::IsLittleEndianHost)
  8131. sys::swapByteOrder(count);
  8132. if (flavor == MachO::ARM_THREAD_STATE) {
  8133. outs() << " flavor ARM_THREAD_STATE\n";
  8134. if (count == MachO::ARM_THREAD_STATE_COUNT)
  8135. outs() << " count ARM_THREAD_STATE_COUNT\n";
  8136. else
  8137. outs() << " count " << count
  8138. << " (not ARM_THREAD_STATE_COUNT)\n";
  8139. MachO::arm_thread_state32_t cpu32;
  8140. left = end - begin;
  8141. if (left >= sizeof(MachO::arm_thread_state32_t)) {
  8142. memcpy(&cpu32, begin, sizeof(MachO::arm_thread_state32_t));
  8143. begin += sizeof(MachO::arm_thread_state32_t);
  8144. } else {
  8145. memset(&cpu32, '\0', sizeof(MachO::arm_thread_state32_t));
  8146. memcpy(&cpu32, begin, left);
  8147. begin += left;
  8148. }
  8149. if (isLittleEndian != sys::IsLittleEndianHost)
  8150. swapStruct(cpu32);
  8151. Print_arm_thread_state32_t(cpu32);
  8152. } else {
  8153. outs() << " flavor " << flavor << " (unknown)\n";
  8154. outs() << " count " << count << "\n";
  8155. outs() << " state (unknown)\n";
  8156. begin += count * sizeof(uint32_t);
  8157. }
  8158. }
  8159. } else if (cputype == MachO::CPU_TYPE_ARM64) {
  8160. while (begin < end) {
  8161. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8162. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  8163. begin += sizeof(uint32_t);
  8164. } else {
  8165. flavor = 0;
  8166. begin = end;
  8167. }
  8168. if (isLittleEndian != sys::IsLittleEndianHost)
  8169. sys::swapByteOrder(flavor);
  8170. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8171. memcpy((char *)&count, begin, sizeof(uint32_t));
  8172. begin += sizeof(uint32_t);
  8173. } else {
  8174. count = 0;
  8175. begin = end;
  8176. }
  8177. if (isLittleEndian != sys::IsLittleEndianHost)
  8178. sys::swapByteOrder(count);
  8179. if (flavor == MachO::ARM_THREAD_STATE64) {
  8180. outs() << " flavor ARM_THREAD_STATE64\n";
  8181. if (count == MachO::ARM_THREAD_STATE64_COUNT)
  8182. outs() << " count ARM_THREAD_STATE64_COUNT\n";
  8183. else
  8184. outs() << " count " << count
  8185. << " (not ARM_THREAD_STATE64_COUNT)\n";
  8186. MachO::arm_thread_state64_t cpu64;
  8187. left = end - begin;
  8188. if (left >= sizeof(MachO::arm_thread_state64_t)) {
  8189. memcpy(&cpu64, begin, sizeof(MachO::arm_thread_state64_t));
  8190. begin += sizeof(MachO::arm_thread_state64_t);
  8191. } else {
  8192. memset(&cpu64, '\0', sizeof(MachO::arm_thread_state64_t));
  8193. memcpy(&cpu64, begin, left);
  8194. begin += left;
  8195. }
  8196. if (isLittleEndian != sys::IsLittleEndianHost)
  8197. swapStruct(cpu64);
  8198. Print_arm_thread_state64_t(cpu64);
  8199. } else {
  8200. outs() << " flavor " << flavor << " (unknown)\n";
  8201. outs() << " count " << count << "\n";
  8202. outs() << " state (unknown)\n";
  8203. begin += count * sizeof(uint32_t);
  8204. }
  8205. }
  8206. } else {
  8207. while (begin < end) {
  8208. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8209. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  8210. begin += sizeof(uint32_t);
  8211. } else {
  8212. flavor = 0;
  8213. begin = end;
  8214. }
  8215. if (isLittleEndian != sys::IsLittleEndianHost)
  8216. sys::swapByteOrder(flavor);
  8217. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8218. memcpy((char *)&count, begin, sizeof(uint32_t));
  8219. begin += sizeof(uint32_t);
  8220. } else {
  8221. count = 0;
  8222. begin = end;
  8223. }
  8224. if (isLittleEndian != sys::IsLittleEndianHost)
  8225. sys::swapByteOrder(count);
  8226. outs() << " flavor " << flavor << "\n";
  8227. outs() << " count " << count << "\n";
  8228. outs() << " state (Unknown cputype/cpusubtype)\n";
  8229. begin += count * sizeof(uint32_t);
  8230. }
  8231. }
  8232. }
  8233. static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
  8234. if (dl.cmd == MachO::LC_ID_DYLIB)
  8235. outs() << " cmd LC_ID_DYLIB\n";
  8236. else if (dl.cmd == MachO::LC_LOAD_DYLIB)
  8237. outs() << " cmd LC_LOAD_DYLIB\n";
  8238. else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
  8239. outs() << " cmd LC_LOAD_WEAK_DYLIB\n";
  8240. else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
  8241. outs() << " cmd LC_REEXPORT_DYLIB\n";
  8242. else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
  8243. outs() << " cmd LC_LAZY_LOAD_DYLIB\n";
  8244. else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
  8245. outs() << " cmd LC_LOAD_UPWARD_DYLIB\n";
  8246. else
  8247. outs() << " cmd " << dl.cmd << " (unknown)\n";
  8248. outs() << " cmdsize " << dl.cmdsize;
  8249. if (dl.cmdsize < sizeof(struct MachO::dylib_command))
  8250. outs() << " Incorrect size\n";
  8251. else
  8252. outs() << "\n";
  8253. if (dl.dylib.name < dl.cmdsize) {
  8254. const char *P = (const char *)(Ptr) + dl.dylib.name;
  8255. outs() << " name " << P << " (offset " << dl.dylib.name << ")\n";
  8256. } else {
  8257. outs() << " name ?(bad offset " << dl.dylib.name << ")\n";
  8258. }
  8259. outs() << " time stamp " << dl.dylib.timestamp << " ";
  8260. time_t t = dl.dylib.timestamp;
  8261. outs() << ctime(&t);
  8262. outs() << " current version ";
  8263. if (dl.dylib.current_version == 0xffffffff)
  8264. outs() << "n/a\n";
  8265. else
  8266. outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
  8267. << ((dl.dylib.current_version >> 8) & 0xff) << "."
  8268. << (dl.dylib.current_version & 0xff) << "\n";
  8269. outs() << "compatibility version ";
  8270. if (dl.dylib.compatibility_version == 0xffffffff)
  8271. outs() << "n/a\n";
  8272. else
  8273. outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
  8274. << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
  8275. << (dl.dylib.compatibility_version & 0xff) << "\n";
  8276. }
  8277. static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
  8278. uint32_t object_size) {
  8279. if (ld.cmd == MachO::LC_CODE_SIGNATURE)
  8280. outs() << " cmd LC_CODE_SIGNATURE\n";
  8281. else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
  8282. outs() << " cmd LC_SEGMENT_SPLIT_INFO\n";
  8283. else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
  8284. outs() << " cmd LC_FUNCTION_STARTS\n";
  8285. else if (ld.cmd == MachO::LC_DATA_IN_CODE)
  8286. outs() << " cmd LC_DATA_IN_CODE\n";
  8287. else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
  8288. outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n";
  8289. else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
  8290. outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n";
  8291. else
  8292. outs() << " cmd " << ld.cmd << " (?)\n";
  8293. outs() << " cmdsize " << ld.cmdsize;
  8294. if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
  8295. outs() << " Incorrect size\n";
  8296. else
  8297. outs() << "\n";
  8298. outs() << " dataoff " << ld.dataoff;
  8299. if (ld.dataoff > object_size)
  8300. outs() << " (past end of file)\n";
  8301. else
  8302. outs() << "\n";
  8303. outs() << " datasize " << ld.datasize;
  8304. uint64_t big_size = ld.dataoff;
  8305. big_size += ld.datasize;
  8306. if (big_size > object_size)
  8307. outs() << " (past end of file)\n";
  8308. else
  8309. outs() << "\n";
  8310. }
  8311. static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
  8312. uint32_t cputype, bool verbose) {
  8313. StringRef Buf = Obj->getData();
  8314. unsigned Index = 0;
  8315. for (const auto &Command : Obj->load_commands()) {
  8316. outs() << "Load command " << Index++ << "\n";
  8317. if (Command.C.cmd == MachO::LC_SEGMENT) {
  8318. MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
  8319. const char *sg_segname = SLC.segname;
  8320. PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
  8321. SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
  8322. SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
  8323. verbose);
  8324. for (unsigned j = 0; j < SLC.nsects; j++) {
  8325. MachO::section S = Obj->getSection(Command, j);
  8326. PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
  8327. S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
  8328. SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
  8329. }
  8330. } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
  8331. MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
  8332. const char *sg_segname = SLC_64.segname;
  8333. PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
  8334. SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
  8335. SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
  8336. SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
  8337. for (unsigned j = 0; j < SLC_64.nsects; j++) {
  8338. MachO::section_64 S_64 = Obj->getSection64(Command, j);
  8339. PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
  8340. S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
  8341. S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
  8342. sg_segname, filetype, Buf.size(), verbose);
  8343. }
  8344. } else if (Command.C.cmd == MachO::LC_SYMTAB) {
  8345. MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
  8346. PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
  8347. } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
  8348. MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
  8349. MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
  8350. PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
  8351. Obj->is64Bit());
  8352. } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
  8353. Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
  8354. MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
  8355. PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
  8356. } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
  8357. Command.C.cmd == MachO::LC_ID_DYLINKER ||
  8358. Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
  8359. MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
  8360. PrintDyldLoadCommand(Dyld, Command.Ptr);
  8361. } else if (Command.C.cmd == MachO::LC_UUID) {
  8362. MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
  8363. PrintUuidLoadCommand(Uuid);
  8364. } else if (Command.C.cmd == MachO::LC_RPATH) {
  8365. MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
  8366. PrintRpathLoadCommand(Rpath, Command.Ptr);
  8367. } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
  8368. Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
  8369. Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
  8370. Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
  8371. MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
  8372. PrintVersionMinLoadCommand(Vd);
  8373. } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
  8374. MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
  8375. PrintSourceVersionCommand(Sd);
  8376. } else if (Command.C.cmd == MachO::LC_MAIN) {
  8377. MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
  8378. PrintEntryPointCommand(Ep);
  8379. } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
  8380. MachO::encryption_info_command Ei =
  8381. Obj->getEncryptionInfoCommand(Command);
  8382. PrintEncryptionInfoCommand(Ei, Buf.size());
  8383. } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
  8384. MachO::encryption_info_command_64 Ei =
  8385. Obj->getEncryptionInfoCommand64(Command);
  8386. PrintEncryptionInfoCommand64(Ei, Buf.size());
  8387. } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
  8388. MachO::linker_option_command Lo =
  8389. Obj->getLinkerOptionLoadCommand(Command);
  8390. PrintLinkerOptionCommand(Lo, Command.Ptr);
  8391. } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
  8392. MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
  8393. PrintSubFrameworkCommand(Sf, Command.Ptr);
  8394. } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
  8395. MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
  8396. PrintSubUmbrellaCommand(Sf, Command.Ptr);
  8397. } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
  8398. MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
  8399. PrintSubLibraryCommand(Sl, Command.Ptr);
  8400. } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
  8401. MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
  8402. PrintSubClientCommand(Sc, Command.Ptr);
  8403. } else if (Command.C.cmd == MachO::LC_ROUTINES) {
  8404. MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
  8405. PrintRoutinesCommand(Rc);
  8406. } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
  8407. MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
  8408. PrintRoutinesCommand64(Rc);
  8409. } else if (Command.C.cmd == MachO::LC_THREAD ||
  8410. Command.C.cmd == MachO::LC_UNIXTHREAD) {
  8411. MachO::thread_command Tc = Obj->getThreadCommand(Command);
  8412. PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
  8413. } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
  8414. Command.C.cmd == MachO::LC_ID_DYLIB ||
  8415. Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
  8416. Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
  8417. Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
  8418. Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
  8419. MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
  8420. PrintDylibCommand(Dl, Command.Ptr);
  8421. } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
  8422. Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
  8423. Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
  8424. Command.C.cmd == MachO::LC_DATA_IN_CODE ||
  8425. Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
  8426. Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
  8427. MachO::linkedit_data_command Ld =
  8428. Obj->getLinkeditDataLoadCommand(Command);
  8429. PrintLinkEditDataCommand(Ld, Buf.size());
  8430. } else {
  8431. outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
  8432. << ")\n";
  8433. outs() << " cmdsize " << Command.C.cmdsize << "\n";
  8434. // TODO: get and print the raw bytes of the load command.
  8435. }
  8436. // TODO: print all the other kinds of load commands.
  8437. }
  8438. }
  8439. static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
  8440. if (Obj->is64Bit()) {
  8441. MachO::mach_header_64 H_64;
  8442. H_64 = Obj->getHeader64();
  8443. PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
  8444. H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
  8445. } else {
  8446. MachO::mach_header H;
  8447. H = Obj->getHeader();
  8448. PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
  8449. H.sizeofcmds, H.flags, verbose);
  8450. }
  8451. }
  8452. void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
  8453. const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
  8454. PrintMachHeader(file, !NonVerbose);
  8455. }
  8456. void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
  8457. const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
  8458. uint32_t filetype = 0;
  8459. uint32_t cputype = 0;
  8460. if (file->is64Bit()) {
  8461. MachO::mach_header_64 H_64;
  8462. H_64 = file->getHeader64();
  8463. filetype = H_64.filetype;
  8464. cputype = H_64.cputype;
  8465. } else {
  8466. MachO::mach_header H;
  8467. H = file->getHeader();
  8468. filetype = H.filetype;
  8469. cputype = H.cputype;
  8470. }
  8471. PrintLoadCommands(file, filetype, cputype, !NonVerbose);
  8472. }
  8473. //===----------------------------------------------------------------------===//
  8474. // export trie dumping
  8475. //===----------------------------------------------------------------------===//
  8476. void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
  8477. for (const llvm::object::ExportEntry &Entry : Obj->exports()) {
  8478. uint64_t Flags = Entry.flags();
  8479. bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
  8480. bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
  8481. bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
  8482. MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
  8483. bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
  8484. MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
  8485. bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
  8486. if (ReExport)
  8487. outs() << "[re-export] ";
  8488. else
  8489. outs() << format("0x%08llX ",
  8490. Entry.address()); // FIXME:add in base address
  8491. outs() << Entry.name();
  8492. if (WeakDef || ThreadLocal || Resolver || Abs) {
  8493. bool NeedsComma = false;
  8494. outs() << " [";
  8495. if (WeakDef) {
  8496. outs() << "weak_def";
  8497. NeedsComma = true;
  8498. }
  8499. if (ThreadLocal) {
  8500. if (NeedsComma)
  8501. outs() << ", ";
  8502. outs() << "per-thread";
  8503. NeedsComma = true;
  8504. }
  8505. if (Abs) {
  8506. if (NeedsComma)
  8507. outs() << ", ";
  8508. outs() << "absolute";
  8509. NeedsComma = true;
  8510. }
  8511. if (Resolver) {
  8512. if (NeedsComma)
  8513. outs() << ", ";
  8514. outs() << format("resolver=0x%08llX", Entry.other());
  8515. NeedsComma = true;
  8516. }
  8517. outs() << "]";
  8518. }
  8519. if (ReExport) {
  8520. StringRef DylibName = "unknown";
  8521. int Ordinal = Entry.other() - 1;
  8522. Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
  8523. if (Entry.otherName().empty())
  8524. outs() << " (from " << DylibName << ")";
  8525. else
  8526. outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
  8527. }
  8528. outs() << "\n";
  8529. }
  8530. }
  8531. //===----------------------------------------------------------------------===//
  8532. // rebase table dumping
  8533. //===----------------------------------------------------------------------===//
  8534. namespace {
  8535. class SegInfo {
  8536. public:
  8537. SegInfo(const object::MachOObjectFile *Obj);
  8538. StringRef segmentName(uint32_t SegIndex);
  8539. StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
  8540. uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
  8541. bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset);
  8542. private:
  8543. struct SectionInfo {
  8544. uint64_t Address;
  8545. uint64_t Size;
  8546. StringRef SectionName;
  8547. StringRef SegmentName;
  8548. uint64_t OffsetInSegment;
  8549. uint64_t SegmentStartAddress;
  8550. uint32_t SegmentIndex;
  8551. };
  8552. const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset);
  8553. SmallVector<SectionInfo, 32> Sections;
  8554. };
  8555. }
  8556. SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
  8557. // Build table of sections so segIndex/offset pairs can be translated.
  8558. uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
  8559. StringRef CurSegName;
  8560. uint64_t CurSegAddress;
  8561. for (const SectionRef &Section : Obj->sections()) {
  8562. SectionInfo Info;
  8563. error(Section.getName(Info.SectionName));
  8564. Info.Address = Section.getAddress();
  8565. Info.Size = Section.getSize();
  8566. Info.SegmentName =
  8567. Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
  8568. if (!Info.SegmentName.equals(CurSegName)) {
  8569. ++CurSegIndex;
  8570. CurSegName = Info.SegmentName;
  8571. CurSegAddress = Info.Address;
  8572. }
  8573. Info.SegmentIndex = CurSegIndex - 1;
  8574. Info.OffsetInSegment = Info.Address - CurSegAddress;
  8575. Info.SegmentStartAddress = CurSegAddress;
  8576. Sections.push_back(Info);
  8577. }
  8578. }
  8579. StringRef SegInfo::segmentName(uint32_t SegIndex) {
  8580. for (const SectionInfo &SI : Sections) {
  8581. if (SI.SegmentIndex == SegIndex)
  8582. return SI.SegmentName;
  8583. }
  8584. llvm_unreachable("invalid segIndex");
  8585. }
  8586. bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
  8587. uint64_t OffsetInSeg) {
  8588. for (const SectionInfo &SI : Sections) {
  8589. if (SI.SegmentIndex != SegIndex)
  8590. continue;
  8591. if (SI.OffsetInSegment > OffsetInSeg)
  8592. continue;
  8593. if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
  8594. continue;
  8595. return true;
  8596. }
  8597. return false;
  8598. }
  8599. const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
  8600. uint64_t OffsetInSeg) {
  8601. for (const SectionInfo &SI : Sections) {
  8602. if (SI.SegmentIndex != SegIndex)
  8603. continue;
  8604. if (SI.OffsetInSegment > OffsetInSeg)
  8605. continue;
  8606. if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
  8607. continue;
  8608. return SI;
  8609. }
  8610. llvm_unreachable("segIndex and offset not in any section");
  8611. }
  8612. StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) {
  8613. return findSection(SegIndex, OffsetInSeg).SectionName;
  8614. }
  8615. uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
  8616. const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
  8617. return SI.SegmentStartAddress + OffsetInSeg;
  8618. }
  8619. void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) {
  8620. // Build table of sections so names can used in final output.
  8621. SegInfo sectionTable(Obj);
  8622. outs() << "segment section address type\n";
  8623. for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
  8624. uint32_t SegIndex = Entry.segmentIndex();
  8625. uint64_t OffsetInSeg = Entry.segmentOffset();
  8626. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8627. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8628. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8629. // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer
  8630. outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n",
  8631. SegmentName.str().c_str(), SectionName.str().c_str(),
  8632. Address, Entry.typeName().str().c_str());
  8633. }
  8634. }
  8635. static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
  8636. StringRef DylibName;
  8637. switch (Ordinal) {
  8638. case MachO::BIND_SPECIAL_DYLIB_SELF:
  8639. return "this-image";
  8640. case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
  8641. return "main-executable";
  8642. case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
  8643. return "flat-namespace";
  8644. default:
  8645. if (Ordinal > 0) {
  8646. std::error_code EC =
  8647. Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
  8648. if (EC)
  8649. return "<<bad library ordinal>>";
  8650. return DylibName;
  8651. }
  8652. }
  8653. return "<<unknown special ordinal>>";
  8654. }
  8655. //===----------------------------------------------------------------------===//
  8656. // bind table dumping
  8657. //===----------------------------------------------------------------------===//
  8658. void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
  8659. // Build table of sections so names can used in final output.
  8660. SegInfo sectionTable(Obj);
  8661. outs() << "segment section address type "
  8662. "addend dylib symbol\n";
  8663. for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
  8664. uint32_t SegIndex = Entry.segmentIndex();
  8665. uint64_t OffsetInSeg = Entry.segmentOffset();
  8666. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8667. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8668. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8669. // Table lines look like:
  8670. // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
  8671. StringRef Attr;
  8672. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
  8673. Attr = " (weak_import)";
  8674. outs() << left_justify(SegmentName, 8) << " "
  8675. << left_justify(SectionName, 18) << " "
  8676. << format_hex(Address, 10, true) << " "
  8677. << left_justify(Entry.typeName(), 8) << " "
  8678. << format_decimal(Entry.addend(), 8) << " "
  8679. << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
  8680. << Entry.symbolName() << Attr << "\n";
  8681. }
  8682. }
  8683. //===----------------------------------------------------------------------===//
  8684. // lazy bind table dumping
  8685. //===----------------------------------------------------------------------===//
  8686. void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
  8687. // Build table of sections so names can used in final output.
  8688. SegInfo sectionTable(Obj);
  8689. outs() << "segment section address "
  8690. "dylib symbol\n";
  8691. for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) {
  8692. uint32_t SegIndex = Entry.segmentIndex();
  8693. uint64_t OffsetInSeg = Entry.segmentOffset();
  8694. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8695. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8696. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8697. // Table lines look like:
  8698. // __DATA __got 0x00012010 libSystem ___stack_chk_guard
  8699. outs() << left_justify(SegmentName, 8) << " "
  8700. << left_justify(SectionName, 18) << " "
  8701. << format_hex(Address, 10, true) << " "
  8702. << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
  8703. << Entry.symbolName() << "\n";
  8704. }
  8705. }
  8706. //===----------------------------------------------------------------------===//
  8707. // weak bind table dumping
  8708. //===----------------------------------------------------------------------===//
  8709. void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
  8710. // Build table of sections so names can used in final output.
  8711. SegInfo sectionTable(Obj);
  8712. outs() << "segment section address "
  8713. "type addend symbol\n";
  8714. for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) {
  8715. // Strong symbols don't have a location to update.
  8716. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
  8717. outs() << " strong "
  8718. << Entry.symbolName() << "\n";
  8719. continue;
  8720. }
  8721. uint32_t SegIndex = Entry.segmentIndex();
  8722. uint64_t OffsetInSeg = Entry.segmentOffset();
  8723. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8724. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8725. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8726. // Table lines look like:
  8727. // __DATA __data 0x00001000 pointer 0 _foo
  8728. outs() << left_justify(SegmentName, 8) << " "
  8729. << left_justify(SectionName, 18) << " "
  8730. << format_hex(Address, 10, true) << " "
  8731. << left_justify(Entry.typeName(), 8) << " "
  8732. << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName()
  8733. << "\n";
  8734. }
  8735. }
  8736. // get_dyld_bind_info_symbolname() is used for disassembly and passed an
  8737. // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
  8738. // information for that address. If the address is found its binding symbol
  8739. // name is returned. If not nullptr is returned.
  8740. static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
  8741. struct DisassembleInfo *info) {
  8742. if (info->bindtable == nullptr) {
  8743. info->bindtable = new (BindTable);
  8744. SegInfo sectionTable(info->O);
  8745. for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
  8746. uint32_t SegIndex = Entry.segmentIndex();
  8747. uint64_t OffsetInSeg = Entry.segmentOffset();
  8748. if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg))
  8749. continue;
  8750. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8751. const char *SymbolName = nullptr;
  8752. StringRef name = Entry.symbolName();
  8753. if (!name.empty())
  8754. SymbolName = name.data();
  8755. info->bindtable->push_back(std::make_pair(Address, SymbolName));
  8756. }
  8757. }
  8758. for (bind_table_iterator BI = info->bindtable->begin(),
  8759. BE = info->bindtable->end();
  8760. BI != BE; ++BI) {
  8761. uint64_t Address = BI->first;
  8762. if (ReferenceValue == Address) {
  8763. const char *SymbolName = BI->second;
  8764. return SymbolName;
  8765. }
  8766. }
  8767. return nullptr;
  8768. }