MachODump.cpp 336 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401
  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/MC/MCAsmInfo.h"
  23. #include "llvm/MC/MCContext.h"
  24. #include "llvm/MC/MCDisassembler/MCDisassembler.h"
  25. #include "llvm/MC/MCInst.h"
  26. #include "llvm/MC/MCInstPrinter.h"
  27. #include "llvm/MC/MCInstrDesc.h"
  28. #include "llvm/MC/MCInstrInfo.h"
  29. #include "llvm/MC/MCRegisterInfo.h"
  30. #include "llvm/MC/MCSubtargetInfo.h"
  31. #include "llvm/Object/MachOUniversal.h"
  32. #include "llvm/Support/Casting.h"
  33. #include "llvm/Support/CommandLine.h"
  34. #include "llvm/Support/Debug.h"
  35. #include "llvm/Support/Endian.h"
  36. #include "llvm/Support/Format.h"
  37. #include "llvm/Support/FormattedStream.h"
  38. #include "llvm/Support/GraphWriter.h"
  39. #include "llvm/Support/LEB128.h"
  40. #include "llvm/Support/MachO.h"
  41. #include "llvm/Support/MemoryBuffer.h"
  42. #include "llvm/Support/TargetRegistry.h"
  43. #include "llvm/Support/TargetSelect.h"
  44. #include "llvm/Support/ToolOutputFile.h"
  45. #include "llvm/Support/raw_ostream.h"
  46. #include <algorithm>
  47. #include <cstring>
  48. #include <system_error>
  49. #if HAVE_CXXABI_H
  50. #include <cxxabi.h>
  51. #endif
  52. #ifdef HAVE_LIBXAR
  53. extern "C" {
  54. #include <xar/xar.h>
  55. }
  56. #endif
  57. using namespace llvm;
  58. using namespace object;
  59. static cl::opt<bool>
  60. UseDbg("g",
  61. cl::desc("Print line information from debug info if available"));
  62. static cl::opt<std::string> DSYMFile("dsym",
  63. cl::desc("Use .dSYM file for debug info"));
  64. static cl::opt<bool> FullLeadingAddr("full-leading-addr",
  65. cl::desc("Print full leading address"));
  66. static cl::opt<bool> NoLeadingAddr("no-leading-addr",
  67. cl::desc("Print no leading address"));
  68. cl::opt<bool> llvm::UniversalHeaders("universal-headers",
  69. cl::desc("Print Mach-O universal headers "
  70. "(requires -macho)"));
  71. cl::opt<bool>
  72. llvm::ArchiveHeaders("archive-headers",
  73. cl::desc("Print archive headers for Mach-O archives "
  74. "(requires -macho)"));
  75. cl::opt<bool>
  76. ArchiveMemberOffsets("archive-member-offsets",
  77. cl::desc("Print the offset to each archive member for "
  78. "Mach-O archives (requires -macho and "
  79. "-archive-headers)"));
  80. cl::opt<bool>
  81. llvm::IndirectSymbols("indirect-symbols",
  82. cl::desc("Print indirect symbol table for Mach-O "
  83. "objects (requires -macho)"));
  84. cl::opt<bool>
  85. llvm::DataInCode("data-in-code",
  86. cl::desc("Print the data in code table for Mach-O objects "
  87. "(requires -macho)"));
  88. cl::opt<bool>
  89. llvm::LinkOptHints("link-opt-hints",
  90. cl::desc("Print the linker optimization hints for "
  91. "Mach-O objects (requires -macho)"));
  92. cl::opt<bool>
  93. llvm::InfoPlist("info-plist",
  94. cl::desc("Print the info plist section as strings for "
  95. "Mach-O objects (requires -macho)"));
  96. cl::opt<bool>
  97. llvm::DylibsUsed("dylibs-used",
  98. cl::desc("Print the shared libraries used for linked "
  99. "Mach-O files (requires -macho)"));
  100. cl::opt<bool>
  101. llvm::DylibId("dylib-id",
  102. cl::desc("Print the shared library's id for the dylib Mach-O "
  103. "file (requires -macho)"));
  104. cl::opt<bool>
  105. llvm::NonVerbose("non-verbose",
  106. cl::desc("Print the info for Mach-O objects in "
  107. "non-verbose or numeric form (requires -macho)"));
  108. cl::opt<bool>
  109. llvm::ObjcMetaData("objc-meta-data",
  110. cl::desc("Print the Objective-C runtime meta data for "
  111. "Mach-O files (requires -macho)"));
  112. cl::opt<std::string> llvm::DisSymName(
  113. "dis-symname",
  114. cl::desc("disassemble just this symbol's instructions (requires -macho"));
  115. static cl::opt<bool> NoSymbolicOperands(
  116. "no-symbolic-operands",
  117. cl::desc("do not symbolic operands when disassembling (requires -macho)"));
  118. static cl::list<std::string>
  119. ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
  120. cl::ZeroOrMore);
  121. bool ArchAll = false;
  122. static std::string ThumbTripleName;
  123. static const Target *GetTarget(const MachOObjectFile *MachOObj,
  124. const char **McpuDefault,
  125. const Target **ThumbTarget) {
  126. // Figure out the target triple.
  127. llvm::Triple TT(TripleName);
  128. if (TripleName.empty()) {
  129. TT = MachOObj->getArchTriple(McpuDefault);
  130. TripleName = TT.str();
  131. }
  132. if (TT.getArch() == Triple::arm) {
  133. // We've inferred a 32-bit ARM target from the object file. All MachO CPUs
  134. // that support ARM are also capable of Thumb mode.
  135. llvm::Triple ThumbTriple = TT;
  136. std::string ThumbName = (Twine("thumb") + TT.getArchName().substr(3)).str();
  137. ThumbTriple.setArchName(ThumbName);
  138. ThumbTripleName = ThumbTriple.str();
  139. }
  140. // Get the target specific parser.
  141. std::string Error;
  142. const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
  143. if (TheTarget && ThumbTripleName.empty())
  144. return TheTarget;
  145. *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
  146. if (*ThumbTarget)
  147. return TheTarget;
  148. errs() << "llvm-objdump: error: unable to get target for '";
  149. if (!TheTarget)
  150. errs() << TripleName;
  151. else
  152. errs() << ThumbTripleName;
  153. errs() << "', see --version and --triple.\n";
  154. return nullptr;
  155. }
  156. struct SymbolSorter {
  157. bool operator()(const SymbolRef &A, const SymbolRef &B) {
  158. Expected<SymbolRef::Type> ATypeOrErr = A.getType();
  159. if (!ATypeOrErr) {
  160. std::string Buf;
  161. raw_string_ostream OS(Buf);
  162. logAllUnhandledErrors(ATypeOrErr.takeError(), OS, "");
  163. OS.flush();
  164. report_fatal_error(Buf);
  165. }
  166. SymbolRef::Type AType = *ATypeOrErr;
  167. Expected<SymbolRef::Type> BTypeOrErr = B.getType();
  168. if (!BTypeOrErr) {
  169. std::string Buf;
  170. raw_string_ostream OS(Buf);
  171. logAllUnhandledErrors(BTypeOrErr.takeError(), OS, "");
  172. OS.flush();
  173. report_fatal_error(Buf);
  174. }
  175. SymbolRef::Type BType = *BTypeOrErr;
  176. uint64_t AAddr = (AType != SymbolRef::ST_Function) ? 0 : A.getValue();
  177. uint64_t BAddr = (BType != SymbolRef::ST_Function) ? 0 : B.getValue();
  178. return AAddr < BAddr;
  179. }
  180. };
  181. // Types for the storted data in code table that is built before disassembly
  182. // and the predicate function to sort them.
  183. typedef std::pair<uint64_t, DiceRef> DiceTableEntry;
  184. typedef std::vector<DiceTableEntry> DiceTable;
  185. typedef DiceTable::iterator dice_table_iterator;
  186. // This is used to search for a data in code table entry for the PC being
  187. // disassembled. The j parameter has the PC in j.first. A single data in code
  188. // table entry can cover many bytes for each of its Kind's. So if the offset,
  189. // aka the i.first value, of the data in code table entry plus its Length
  190. // covers the PC being searched for this will return true. If not it will
  191. // return false.
  192. static bool compareDiceTableEntries(const DiceTableEntry &i,
  193. const DiceTableEntry &j) {
  194. uint16_t Length;
  195. i.second.getLength(Length);
  196. return j.first >= i.first && j.first < i.first + Length;
  197. }
  198. static uint64_t DumpDataInCode(const uint8_t *bytes, uint64_t Length,
  199. unsigned short Kind) {
  200. uint32_t Value, Size = 1;
  201. switch (Kind) {
  202. default:
  203. case MachO::DICE_KIND_DATA:
  204. if (Length >= 4) {
  205. if (!NoShowRawInsn)
  206. dumpBytes(makeArrayRef(bytes, 4), outs());
  207. Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
  208. outs() << "\t.long " << Value;
  209. Size = 4;
  210. } else if (Length >= 2) {
  211. if (!NoShowRawInsn)
  212. dumpBytes(makeArrayRef(bytes, 2), outs());
  213. Value = bytes[1] << 8 | bytes[0];
  214. outs() << "\t.short " << Value;
  215. Size = 2;
  216. } else {
  217. if (!NoShowRawInsn)
  218. dumpBytes(makeArrayRef(bytes, 2), outs());
  219. Value = bytes[0];
  220. outs() << "\t.byte " << Value;
  221. Size = 1;
  222. }
  223. if (Kind == MachO::DICE_KIND_DATA)
  224. outs() << "\t@ KIND_DATA\n";
  225. else
  226. outs() << "\t@ data in code kind = " << Kind << "\n";
  227. break;
  228. case MachO::DICE_KIND_JUMP_TABLE8:
  229. if (!NoShowRawInsn)
  230. dumpBytes(makeArrayRef(bytes, 1), outs());
  231. Value = bytes[0];
  232. outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
  233. Size = 1;
  234. break;
  235. case MachO::DICE_KIND_JUMP_TABLE16:
  236. if (!NoShowRawInsn)
  237. dumpBytes(makeArrayRef(bytes, 2), outs());
  238. Value = bytes[1] << 8 | bytes[0];
  239. outs() << "\t.short " << format("%5u", Value & 0xffff)
  240. << "\t@ KIND_JUMP_TABLE16\n";
  241. Size = 2;
  242. break;
  243. case MachO::DICE_KIND_JUMP_TABLE32:
  244. case MachO::DICE_KIND_ABS_JUMP_TABLE32:
  245. if (!NoShowRawInsn)
  246. dumpBytes(makeArrayRef(bytes, 4), outs());
  247. Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
  248. outs() << "\t.long " << Value;
  249. if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
  250. outs() << "\t@ KIND_JUMP_TABLE32\n";
  251. else
  252. outs() << "\t@ KIND_ABS_JUMP_TABLE32\n";
  253. Size = 4;
  254. break;
  255. }
  256. return Size;
  257. }
  258. static void getSectionsAndSymbols(MachOObjectFile *MachOObj,
  259. std::vector<SectionRef> &Sections,
  260. std::vector<SymbolRef> &Symbols,
  261. SmallVectorImpl<uint64_t> &FoundFns,
  262. uint64_t &BaseSegmentAddress) {
  263. for (const SymbolRef &Symbol : MachOObj->symbols()) {
  264. Expected<StringRef> SymName = Symbol.getName();
  265. if (!SymName) {
  266. std::string Buf;
  267. raw_string_ostream OS(Buf);
  268. logAllUnhandledErrors(SymName.takeError(), OS, "");
  269. OS.flush();
  270. report_fatal_error(Buf);
  271. }
  272. if (!SymName->startswith("ltmp"))
  273. Symbols.push_back(Symbol);
  274. }
  275. for (const SectionRef &Section : MachOObj->sections()) {
  276. StringRef SectName;
  277. Section.getName(SectName);
  278. Sections.push_back(Section);
  279. }
  280. bool BaseSegmentAddressSet = false;
  281. for (const auto &Command : MachOObj->load_commands()) {
  282. if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
  283. // We found a function starts segment, parse the addresses for later
  284. // consumption.
  285. MachO::linkedit_data_command LLC =
  286. MachOObj->getLinkeditDataLoadCommand(Command);
  287. MachOObj->ReadULEB128s(LLC.dataoff, FoundFns);
  288. } else if (Command.C.cmd == MachO::LC_SEGMENT) {
  289. MachO::segment_command SLC = MachOObj->getSegmentLoadCommand(Command);
  290. StringRef SegName = SLC.segname;
  291. if (!BaseSegmentAddressSet && SegName != "__PAGEZERO") {
  292. BaseSegmentAddressSet = true;
  293. BaseSegmentAddress = SLC.vmaddr;
  294. }
  295. }
  296. }
  297. }
  298. static void PrintIndirectSymbolTable(MachOObjectFile *O, bool verbose,
  299. uint32_t n, uint32_t count,
  300. uint32_t stride, uint64_t addr) {
  301. MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
  302. uint32_t nindirectsyms = Dysymtab.nindirectsyms;
  303. if (n > nindirectsyms)
  304. outs() << " (entries start past the end of the indirect symbol "
  305. "table) (reserved1 field greater than the table size)";
  306. else if (n + count > nindirectsyms)
  307. outs() << " (entries extends past the end of the indirect symbol "
  308. "table)";
  309. outs() << "\n";
  310. uint32_t cputype = O->getHeader().cputype;
  311. if (cputype & MachO::CPU_ARCH_ABI64)
  312. outs() << "address index";
  313. else
  314. outs() << "address index";
  315. if (verbose)
  316. outs() << " name\n";
  317. else
  318. outs() << "\n";
  319. for (uint32_t j = 0; j < count && n + j < nindirectsyms; j++) {
  320. if (cputype & MachO::CPU_ARCH_ABI64)
  321. outs() << format("0x%016" PRIx64, addr + j * stride) << " ";
  322. else
  323. outs() << format("0x%08" PRIx32, (uint32_t)addr + j * stride) << " ";
  324. MachO::dysymtab_command Dysymtab = O->getDysymtabLoadCommand();
  325. uint32_t indirect_symbol = O->getIndirectSymbolTableEntry(Dysymtab, n + j);
  326. if (indirect_symbol == MachO::INDIRECT_SYMBOL_LOCAL) {
  327. outs() << "LOCAL\n";
  328. continue;
  329. }
  330. if (indirect_symbol ==
  331. (MachO::INDIRECT_SYMBOL_LOCAL | MachO::INDIRECT_SYMBOL_ABS)) {
  332. outs() << "LOCAL ABSOLUTE\n";
  333. continue;
  334. }
  335. if (indirect_symbol == MachO::INDIRECT_SYMBOL_ABS) {
  336. outs() << "ABSOLUTE\n";
  337. continue;
  338. }
  339. outs() << format("%5u ", indirect_symbol);
  340. if (verbose) {
  341. MachO::symtab_command Symtab = O->getSymtabLoadCommand();
  342. if (indirect_symbol < Symtab.nsyms) {
  343. symbol_iterator Sym = O->getSymbolByIndex(indirect_symbol);
  344. SymbolRef Symbol = *Sym;
  345. Expected<StringRef> SymName = Symbol.getName();
  346. if (!SymName) {
  347. std::string Buf;
  348. raw_string_ostream OS(Buf);
  349. logAllUnhandledErrors(SymName.takeError(), OS, "");
  350. OS.flush();
  351. report_fatal_error(Buf);
  352. }
  353. outs() << *SymName;
  354. } else {
  355. outs() << "?";
  356. }
  357. }
  358. outs() << "\n";
  359. }
  360. }
  361. static void PrintIndirectSymbols(MachOObjectFile *O, bool verbose) {
  362. for (const auto &Load : O->load_commands()) {
  363. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  364. MachO::segment_command_64 Seg = O->getSegment64LoadCommand(Load);
  365. for (unsigned J = 0; J < Seg.nsects; ++J) {
  366. MachO::section_64 Sec = O->getSection64(Load, J);
  367. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  368. if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  369. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  370. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  371. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  372. section_type == MachO::S_SYMBOL_STUBS) {
  373. uint32_t stride;
  374. if (section_type == MachO::S_SYMBOL_STUBS)
  375. stride = Sec.reserved2;
  376. else
  377. stride = 8;
  378. if (stride == 0) {
  379. outs() << "Can't print indirect symbols for (" << Sec.segname << ","
  380. << Sec.sectname << ") "
  381. << "(size of stubs in reserved2 field is zero)\n";
  382. continue;
  383. }
  384. uint32_t count = Sec.size / stride;
  385. outs() << "Indirect symbols for (" << Sec.segname << ","
  386. << Sec.sectname << ") " << count << " entries";
  387. uint32_t n = Sec.reserved1;
  388. PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
  389. }
  390. }
  391. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  392. MachO::segment_command Seg = O->getSegmentLoadCommand(Load);
  393. for (unsigned J = 0; J < Seg.nsects; ++J) {
  394. MachO::section Sec = O->getSection(Load, J);
  395. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  396. if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  397. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  398. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  399. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  400. section_type == MachO::S_SYMBOL_STUBS) {
  401. uint32_t stride;
  402. if (section_type == MachO::S_SYMBOL_STUBS)
  403. stride = Sec.reserved2;
  404. else
  405. stride = 4;
  406. if (stride == 0) {
  407. outs() << "Can't print indirect symbols for (" << Sec.segname << ","
  408. << Sec.sectname << ") "
  409. << "(size of stubs in reserved2 field is zero)\n";
  410. continue;
  411. }
  412. uint32_t count = Sec.size / stride;
  413. outs() << "Indirect symbols for (" << Sec.segname << ","
  414. << Sec.sectname << ") " << count << " entries";
  415. uint32_t n = Sec.reserved1;
  416. PrintIndirectSymbolTable(O, verbose, n, count, stride, Sec.addr);
  417. }
  418. }
  419. }
  420. }
  421. }
  422. static void PrintDataInCodeTable(MachOObjectFile *O, bool verbose) {
  423. MachO::linkedit_data_command DIC = O->getDataInCodeLoadCommand();
  424. uint32_t nentries = DIC.datasize / sizeof(struct MachO::data_in_code_entry);
  425. outs() << "Data in code table (" << nentries << " entries)\n";
  426. outs() << "offset length kind\n";
  427. for (dice_iterator DI = O->begin_dices(), DE = O->end_dices(); DI != DE;
  428. ++DI) {
  429. uint32_t Offset;
  430. DI->getOffset(Offset);
  431. outs() << format("0x%08" PRIx32, Offset) << " ";
  432. uint16_t Length;
  433. DI->getLength(Length);
  434. outs() << format("%6u", Length) << " ";
  435. uint16_t Kind;
  436. DI->getKind(Kind);
  437. if (verbose) {
  438. switch (Kind) {
  439. case MachO::DICE_KIND_DATA:
  440. outs() << "DATA";
  441. break;
  442. case MachO::DICE_KIND_JUMP_TABLE8:
  443. outs() << "JUMP_TABLE8";
  444. break;
  445. case MachO::DICE_KIND_JUMP_TABLE16:
  446. outs() << "JUMP_TABLE16";
  447. break;
  448. case MachO::DICE_KIND_JUMP_TABLE32:
  449. outs() << "JUMP_TABLE32";
  450. break;
  451. case MachO::DICE_KIND_ABS_JUMP_TABLE32:
  452. outs() << "ABS_JUMP_TABLE32";
  453. break;
  454. default:
  455. outs() << format("0x%04" PRIx32, Kind);
  456. break;
  457. }
  458. } else
  459. outs() << format("0x%04" PRIx32, Kind);
  460. outs() << "\n";
  461. }
  462. }
  463. static void PrintLinkOptHints(MachOObjectFile *O) {
  464. MachO::linkedit_data_command LohLC = O->getLinkOptHintsLoadCommand();
  465. const char *loh = O->getData().substr(LohLC.dataoff, 1).data();
  466. uint32_t nloh = LohLC.datasize;
  467. outs() << "Linker optimiztion hints (" << nloh << " total bytes)\n";
  468. for (uint32_t i = 0; i < nloh;) {
  469. unsigned n;
  470. uint64_t identifier = decodeULEB128((const uint8_t *)(loh + i), &n);
  471. i += n;
  472. outs() << " identifier " << identifier << " ";
  473. if (i >= nloh)
  474. return;
  475. switch (identifier) {
  476. case 1:
  477. outs() << "AdrpAdrp\n";
  478. break;
  479. case 2:
  480. outs() << "AdrpLdr\n";
  481. break;
  482. case 3:
  483. outs() << "AdrpAddLdr\n";
  484. break;
  485. case 4:
  486. outs() << "AdrpLdrGotLdr\n";
  487. break;
  488. case 5:
  489. outs() << "AdrpAddStr\n";
  490. break;
  491. case 6:
  492. outs() << "AdrpLdrGotStr\n";
  493. break;
  494. case 7:
  495. outs() << "AdrpAdd\n";
  496. break;
  497. case 8:
  498. outs() << "AdrpLdrGot\n";
  499. break;
  500. default:
  501. outs() << "Unknown identifier value\n";
  502. break;
  503. }
  504. uint64_t narguments = decodeULEB128((const uint8_t *)(loh + i), &n);
  505. i += n;
  506. outs() << " narguments " << narguments << "\n";
  507. if (i >= nloh)
  508. return;
  509. for (uint32_t j = 0; j < narguments; j++) {
  510. uint64_t value = decodeULEB128((const uint8_t *)(loh + i), &n);
  511. i += n;
  512. outs() << "\tvalue " << format("0x%" PRIx64, value) << "\n";
  513. if (i >= nloh)
  514. return;
  515. }
  516. }
  517. }
  518. static void PrintDylibs(MachOObjectFile *O, bool JustId) {
  519. unsigned Index = 0;
  520. for (const auto &Load : O->load_commands()) {
  521. if ((JustId && Load.C.cmd == MachO::LC_ID_DYLIB) ||
  522. (!JustId && (Load.C.cmd == MachO::LC_ID_DYLIB ||
  523. Load.C.cmd == MachO::LC_LOAD_DYLIB ||
  524. Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
  525. Load.C.cmd == MachO::LC_REEXPORT_DYLIB ||
  526. Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
  527. Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB))) {
  528. MachO::dylib_command dl = O->getDylibIDLoadCommand(Load);
  529. if (dl.dylib.name < dl.cmdsize) {
  530. const char *p = (const char *)(Load.Ptr) + dl.dylib.name;
  531. if (JustId)
  532. outs() << p << "\n";
  533. else {
  534. outs() << "\t" << p;
  535. outs() << " (compatibility version "
  536. << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
  537. << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
  538. << (dl.dylib.compatibility_version & 0xff) << ",";
  539. outs() << " current version "
  540. << ((dl.dylib.current_version >> 16) & 0xffff) << "."
  541. << ((dl.dylib.current_version >> 8) & 0xff) << "."
  542. << (dl.dylib.current_version & 0xff) << ")\n";
  543. }
  544. } else {
  545. outs() << "\tBad offset (" << dl.dylib.name << ") for name of ";
  546. if (Load.C.cmd == MachO::LC_ID_DYLIB)
  547. outs() << "LC_ID_DYLIB ";
  548. else if (Load.C.cmd == MachO::LC_LOAD_DYLIB)
  549. outs() << "LC_LOAD_DYLIB ";
  550. else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB)
  551. outs() << "LC_LOAD_WEAK_DYLIB ";
  552. else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB)
  553. outs() << "LC_LAZY_LOAD_DYLIB ";
  554. else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB)
  555. outs() << "LC_REEXPORT_DYLIB ";
  556. else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
  557. outs() << "LC_LOAD_UPWARD_DYLIB ";
  558. else
  559. outs() << "LC_??? ";
  560. outs() << "command " << Index++ << "\n";
  561. }
  562. }
  563. }
  564. }
  565. typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
  566. static void CreateSymbolAddressMap(MachOObjectFile *O,
  567. SymbolAddressMap *AddrMap) {
  568. // Create a map of symbol addresses to symbol names.
  569. for (const SymbolRef &Symbol : O->symbols()) {
  570. Expected<SymbolRef::Type> STOrErr = Symbol.getType();
  571. if (!STOrErr) {
  572. std::string Buf;
  573. raw_string_ostream OS(Buf);
  574. logAllUnhandledErrors(STOrErr.takeError(), OS, "");
  575. OS.flush();
  576. report_fatal_error(Buf);
  577. }
  578. SymbolRef::Type ST = *STOrErr;
  579. if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
  580. ST == SymbolRef::ST_Other) {
  581. uint64_t Address = Symbol.getValue();
  582. Expected<StringRef> SymNameOrErr = Symbol.getName();
  583. if (!SymNameOrErr) {
  584. std::string Buf;
  585. raw_string_ostream OS(Buf);
  586. logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
  587. OS.flush();
  588. report_fatal_error(Buf);
  589. }
  590. StringRef SymName = *SymNameOrErr;
  591. if (!SymName.startswith(".objc"))
  592. (*AddrMap)[Address] = SymName;
  593. }
  594. }
  595. }
  596. // GuessSymbolName is passed the address of what might be a symbol and a
  597. // pointer to the SymbolAddressMap. It returns the name of a symbol
  598. // with that address or nullptr if no symbol is found with that address.
  599. static const char *GuessSymbolName(uint64_t value, SymbolAddressMap *AddrMap) {
  600. const char *SymbolName = nullptr;
  601. // A DenseMap can't lookup up some values.
  602. if (value != 0xffffffffffffffffULL && value != 0xfffffffffffffffeULL) {
  603. StringRef name = AddrMap->lookup(value);
  604. if (!name.empty())
  605. SymbolName = name.data();
  606. }
  607. return SymbolName;
  608. }
  609. static void DumpCstringChar(const char c) {
  610. char p[2];
  611. p[0] = c;
  612. p[1] = '\0';
  613. outs().write_escaped(p);
  614. }
  615. static void DumpCstringSection(MachOObjectFile *O, const char *sect,
  616. uint32_t sect_size, uint64_t sect_addr,
  617. bool print_addresses) {
  618. for (uint32_t i = 0; i < sect_size; i++) {
  619. if (print_addresses) {
  620. if (O->is64Bit())
  621. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  622. else
  623. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  624. }
  625. for (; i < sect_size && sect[i] != '\0'; i++)
  626. DumpCstringChar(sect[i]);
  627. if (i < sect_size && sect[i] == '\0')
  628. outs() << "\n";
  629. }
  630. }
  631. static void DumpLiteral4(uint32_t l, float f) {
  632. outs() << format("0x%08" PRIx32, l);
  633. if ((l & 0x7f800000) != 0x7f800000)
  634. outs() << format(" (%.16e)\n", f);
  635. else {
  636. if (l == 0x7f800000)
  637. outs() << " (+Infinity)\n";
  638. else if (l == 0xff800000)
  639. outs() << " (-Infinity)\n";
  640. else if ((l & 0x00400000) == 0x00400000)
  641. outs() << " (non-signaling Not-a-Number)\n";
  642. else
  643. outs() << " (signaling Not-a-Number)\n";
  644. }
  645. }
  646. static void DumpLiteral4Section(MachOObjectFile *O, const char *sect,
  647. uint32_t sect_size, uint64_t sect_addr,
  648. bool print_addresses) {
  649. for (uint32_t i = 0; i < sect_size; i += sizeof(float)) {
  650. if (print_addresses) {
  651. if (O->is64Bit())
  652. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  653. else
  654. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  655. }
  656. float f;
  657. memcpy(&f, sect + i, sizeof(float));
  658. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  659. sys::swapByteOrder(f);
  660. uint32_t l;
  661. memcpy(&l, sect + i, sizeof(uint32_t));
  662. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  663. sys::swapByteOrder(l);
  664. DumpLiteral4(l, f);
  665. }
  666. }
  667. static void DumpLiteral8(MachOObjectFile *O, uint32_t l0, uint32_t l1,
  668. double d) {
  669. outs() << format("0x%08" PRIx32, l0) << " " << format("0x%08" PRIx32, l1);
  670. uint32_t Hi, Lo;
  671. Hi = (O->isLittleEndian()) ? l1 : l0;
  672. Lo = (O->isLittleEndian()) ? l0 : l1;
  673. // Hi is the high word, so this is equivalent to if(isfinite(d))
  674. if ((Hi & 0x7ff00000) != 0x7ff00000)
  675. outs() << format(" (%.16e)\n", d);
  676. else {
  677. if (Hi == 0x7ff00000 && Lo == 0)
  678. outs() << " (+Infinity)\n";
  679. else if (Hi == 0xfff00000 && Lo == 0)
  680. outs() << " (-Infinity)\n";
  681. else if ((Hi & 0x00080000) == 0x00080000)
  682. outs() << " (non-signaling Not-a-Number)\n";
  683. else
  684. outs() << " (signaling Not-a-Number)\n";
  685. }
  686. }
  687. static void DumpLiteral8Section(MachOObjectFile *O, const char *sect,
  688. uint32_t sect_size, uint64_t sect_addr,
  689. bool print_addresses) {
  690. for (uint32_t i = 0; i < sect_size; i += sizeof(double)) {
  691. if (print_addresses) {
  692. if (O->is64Bit())
  693. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  694. else
  695. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  696. }
  697. double d;
  698. memcpy(&d, sect + i, sizeof(double));
  699. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  700. sys::swapByteOrder(d);
  701. uint32_t l0, l1;
  702. memcpy(&l0, sect + i, sizeof(uint32_t));
  703. memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
  704. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  705. sys::swapByteOrder(l0);
  706. sys::swapByteOrder(l1);
  707. }
  708. DumpLiteral8(O, l0, l1, d);
  709. }
  710. }
  711. static void DumpLiteral16(uint32_t l0, uint32_t l1, uint32_t l2, uint32_t l3) {
  712. outs() << format("0x%08" PRIx32, l0) << " ";
  713. outs() << format("0x%08" PRIx32, l1) << " ";
  714. outs() << format("0x%08" PRIx32, l2) << " ";
  715. outs() << format("0x%08" PRIx32, l3) << "\n";
  716. }
  717. static void DumpLiteral16Section(MachOObjectFile *O, const char *sect,
  718. uint32_t sect_size, uint64_t sect_addr,
  719. bool print_addresses) {
  720. for (uint32_t i = 0; i < sect_size; i += 16) {
  721. if (print_addresses) {
  722. if (O->is64Bit())
  723. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  724. else
  725. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  726. }
  727. uint32_t l0, l1, l2, l3;
  728. memcpy(&l0, sect + i, sizeof(uint32_t));
  729. memcpy(&l1, sect + i + sizeof(uint32_t), sizeof(uint32_t));
  730. memcpy(&l2, sect + i + 2 * sizeof(uint32_t), sizeof(uint32_t));
  731. memcpy(&l3, sect + i + 3 * sizeof(uint32_t), sizeof(uint32_t));
  732. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  733. sys::swapByteOrder(l0);
  734. sys::swapByteOrder(l1);
  735. sys::swapByteOrder(l2);
  736. sys::swapByteOrder(l3);
  737. }
  738. DumpLiteral16(l0, l1, l2, l3);
  739. }
  740. }
  741. static void DumpLiteralPointerSection(MachOObjectFile *O,
  742. const SectionRef &Section,
  743. const char *sect, uint32_t sect_size,
  744. uint64_t sect_addr,
  745. bool print_addresses) {
  746. // Collect the literal sections in this Mach-O file.
  747. std::vector<SectionRef> LiteralSections;
  748. for (const SectionRef &Section : O->sections()) {
  749. DataRefImpl Ref = Section.getRawDataRefImpl();
  750. uint32_t section_type;
  751. if (O->is64Bit()) {
  752. const MachO::section_64 Sec = O->getSection64(Ref);
  753. section_type = Sec.flags & MachO::SECTION_TYPE;
  754. } else {
  755. const MachO::section Sec = O->getSection(Ref);
  756. section_type = Sec.flags & MachO::SECTION_TYPE;
  757. }
  758. if (section_type == MachO::S_CSTRING_LITERALS ||
  759. section_type == MachO::S_4BYTE_LITERALS ||
  760. section_type == MachO::S_8BYTE_LITERALS ||
  761. section_type == MachO::S_16BYTE_LITERALS)
  762. LiteralSections.push_back(Section);
  763. }
  764. // Set the size of the literal pointer.
  765. uint32_t lp_size = O->is64Bit() ? 8 : 4;
  766. // Collect the external relocation symbols for the literal pointers.
  767. std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
  768. for (const RelocationRef &Reloc : Section.relocations()) {
  769. DataRefImpl Rel;
  770. MachO::any_relocation_info RE;
  771. bool isExtern = false;
  772. Rel = Reloc.getRawDataRefImpl();
  773. RE = O->getRelocation(Rel);
  774. isExtern = O->getPlainRelocationExternal(RE);
  775. if (isExtern) {
  776. uint64_t RelocOffset = Reloc.getOffset();
  777. symbol_iterator RelocSym = Reloc.getSymbol();
  778. Relocs.push_back(std::make_pair(RelocOffset, *RelocSym));
  779. }
  780. }
  781. array_pod_sort(Relocs.begin(), Relocs.end());
  782. // Dump each literal pointer.
  783. for (uint32_t i = 0; i < sect_size; i += lp_size) {
  784. if (print_addresses) {
  785. if (O->is64Bit())
  786. outs() << format("%016" PRIx64, sect_addr + i) << " ";
  787. else
  788. outs() << format("%08" PRIx64, sect_addr + i) << " ";
  789. }
  790. uint64_t lp;
  791. if (O->is64Bit()) {
  792. memcpy(&lp, sect + i, sizeof(uint64_t));
  793. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  794. sys::swapByteOrder(lp);
  795. } else {
  796. uint32_t li;
  797. memcpy(&li, sect + i, sizeof(uint32_t));
  798. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  799. sys::swapByteOrder(li);
  800. lp = li;
  801. }
  802. // First look for an external relocation entry for this literal pointer.
  803. auto Reloc = std::find_if(
  804. Relocs.begin(), Relocs.end(),
  805. [&](const std::pair<uint64_t, SymbolRef> &P) { return P.first == i; });
  806. if (Reloc != Relocs.end()) {
  807. symbol_iterator RelocSym = Reloc->second;
  808. Expected<StringRef> SymName = RelocSym->getName();
  809. if (!SymName) {
  810. std::string Buf;
  811. raw_string_ostream OS(Buf);
  812. logAllUnhandledErrors(SymName.takeError(), OS, "");
  813. OS.flush();
  814. report_fatal_error(Buf);
  815. }
  816. outs() << "external relocation entry for symbol:" << *SymName << "\n";
  817. continue;
  818. }
  819. // For local references see what the section the literal pointer points to.
  820. auto Sect = std::find_if(LiteralSections.begin(), LiteralSections.end(),
  821. [&](const SectionRef &R) {
  822. return lp >= R.getAddress() &&
  823. lp < R.getAddress() + R.getSize();
  824. });
  825. if (Sect == LiteralSections.end()) {
  826. outs() << format("0x%" PRIx64, lp) << " (not in a literal section)\n";
  827. continue;
  828. }
  829. uint64_t SectAddress = Sect->getAddress();
  830. uint64_t SectSize = Sect->getSize();
  831. StringRef SectName;
  832. Sect->getName(SectName);
  833. DataRefImpl Ref = Sect->getRawDataRefImpl();
  834. StringRef SegmentName = O->getSectionFinalSegmentName(Ref);
  835. outs() << SegmentName << ":" << SectName << ":";
  836. uint32_t section_type;
  837. if (O->is64Bit()) {
  838. const MachO::section_64 Sec = O->getSection64(Ref);
  839. section_type = Sec.flags & MachO::SECTION_TYPE;
  840. } else {
  841. const MachO::section Sec = O->getSection(Ref);
  842. section_type = Sec.flags & MachO::SECTION_TYPE;
  843. }
  844. StringRef BytesStr;
  845. Sect->getContents(BytesStr);
  846. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  847. switch (section_type) {
  848. case MachO::S_CSTRING_LITERALS:
  849. for (uint64_t i = lp - SectAddress; i < SectSize && Contents[i] != '\0';
  850. i++) {
  851. DumpCstringChar(Contents[i]);
  852. }
  853. outs() << "\n";
  854. break;
  855. case MachO::S_4BYTE_LITERALS:
  856. float f;
  857. memcpy(&f, Contents + (lp - SectAddress), sizeof(float));
  858. uint32_t l;
  859. memcpy(&l, Contents + (lp - SectAddress), sizeof(uint32_t));
  860. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  861. sys::swapByteOrder(f);
  862. sys::swapByteOrder(l);
  863. }
  864. DumpLiteral4(l, f);
  865. break;
  866. case MachO::S_8BYTE_LITERALS: {
  867. double d;
  868. memcpy(&d, Contents + (lp - SectAddress), sizeof(double));
  869. uint32_t l0, l1;
  870. memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
  871. memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
  872. sizeof(uint32_t));
  873. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  874. sys::swapByteOrder(f);
  875. sys::swapByteOrder(l0);
  876. sys::swapByteOrder(l1);
  877. }
  878. DumpLiteral8(O, l0, l1, d);
  879. break;
  880. }
  881. case MachO::S_16BYTE_LITERALS: {
  882. uint32_t l0, l1, l2, l3;
  883. memcpy(&l0, Contents + (lp - SectAddress), sizeof(uint32_t));
  884. memcpy(&l1, Contents + (lp - SectAddress) + sizeof(uint32_t),
  885. sizeof(uint32_t));
  886. memcpy(&l2, Contents + (lp - SectAddress) + 2 * sizeof(uint32_t),
  887. sizeof(uint32_t));
  888. memcpy(&l3, Contents + (lp - SectAddress) + 3 * sizeof(uint32_t),
  889. sizeof(uint32_t));
  890. if (O->isLittleEndian() != sys::IsLittleEndianHost) {
  891. sys::swapByteOrder(l0);
  892. sys::swapByteOrder(l1);
  893. sys::swapByteOrder(l2);
  894. sys::swapByteOrder(l3);
  895. }
  896. DumpLiteral16(l0, l1, l2, l3);
  897. break;
  898. }
  899. }
  900. }
  901. }
  902. static void DumpInitTermPointerSection(MachOObjectFile *O, const char *sect,
  903. uint32_t sect_size, uint64_t sect_addr,
  904. SymbolAddressMap *AddrMap,
  905. bool verbose) {
  906. uint32_t stride;
  907. stride = (O->is64Bit()) ? sizeof(uint64_t) : sizeof(uint32_t);
  908. for (uint32_t i = 0; i < sect_size; i += stride) {
  909. const char *SymbolName = nullptr;
  910. if (O->is64Bit()) {
  911. outs() << format("0x%016" PRIx64, sect_addr + i * stride) << " ";
  912. uint64_t pointer_value;
  913. memcpy(&pointer_value, sect + i, stride);
  914. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  915. sys::swapByteOrder(pointer_value);
  916. outs() << format("0x%016" PRIx64, pointer_value);
  917. if (verbose)
  918. SymbolName = GuessSymbolName(pointer_value, AddrMap);
  919. } else {
  920. outs() << format("0x%08" PRIx64, sect_addr + i * stride) << " ";
  921. uint32_t pointer_value;
  922. memcpy(&pointer_value, sect + i, stride);
  923. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  924. sys::swapByteOrder(pointer_value);
  925. outs() << format("0x%08" PRIx32, pointer_value);
  926. if (verbose)
  927. SymbolName = GuessSymbolName(pointer_value, AddrMap);
  928. }
  929. if (SymbolName)
  930. outs() << " " << SymbolName;
  931. outs() << "\n";
  932. }
  933. }
  934. static void DumpRawSectionContents(MachOObjectFile *O, const char *sect,
  935. uint32_t size, uint64_t addr) {
  936. uint32_t cputype = O->getHeader().cputype;
  937. if (cputype == MachO::CPU_TYPE_I386 || cputype == MachO::CPU_TYPE_X86_64) {
  938. uint32_t j;
  939. for (uint32_t i = 0; i < size; i += j, addr += j) {
  940. if (O->is64Bit())
  941. outs() << format("%016" PRIx64, addr) << "\t";
  942. else
  943. outs() << format("%08" PRIx64, addr) << "\t";
  944. for (j = 0; j < 16 && i + j < size; j++) {
  945. uint8_t byte_word = *(sect + i + j);
  946. outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
  947. }
  948. outs() << "\n";
  949. }
  950. } else {
  951. uint32_t j;
  952. for (uint32_t i = 0; i < size; i += j, addr += j) {
  953. if (O->is64Bit())
  954. outs() << format("%016" PRIx64, addr) << "\t";
  955. else
  956. outs() << format("%08" PRIx64, addr) << "\t";
  957. for (j = 0; j < 4 * sizeof(int32_t) && i + j < size;
  958. j += sizeof(int32_t)) {
  959. if (i + j + sizeof(int32_t) <= size) {
  960. uint32_t long_word;
  961. memcpy(&long_word, sect + i + j, sizeof(int32_t));
  962. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  963. sys::swapByteOrder(long_word);
  964. outs() << format("%08" PRIx32, long_word) << " ";
  965. } else {
  966. for (uint32_t k = 0; i + j + k < size; k++) {
  967. uint8_t byte_word = *(sect + i + j + k);
  968. outs() << format("%02" PRIx32, (uint32_t)byte_word) << " ";
  969. }
  970. }
  971. }
  972. outs() << "\n";
  973. }
  974. }
  975. }
  976. static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
  977. StringRef DisSegName, StringRef DisSectName);
  978. static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
  979. uint32_t size, uint32_t addr);
  980. #ifdef HAVE_LIBXAR
  981. static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
  982. uint32_t size, bool verbose,
  983. bool PrintXarHeader, bool PrintXarFileHeaders,
  984. std::string XarMemberName);
  985. #endif // defined(HAVE_LIBXAR)
  986. static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
  987. bool verbose) {
  988. SymbolAddressMap AddrMap;
  989. if (verbose)
  990. CreateSymbolAddressMap(O, &AddrMap);
  991. for (unsigned i = 0; i < FilterSections.size(); ++i) {
  992. StringRef DumpSection = FilterSections[i];
  993. std::pair<StringRef, StringRef> DumpSegSectName;
  994. DumpSegSectName = DumpSection.split(',');
  995. StringRef DumpSegName, DumpSectName;
  996. if (DumpSegSectName.second.size()) {
  997. DumpSegName = DumpSegSectName.first;
  998. DumpSectName = DumpSegSectName.second;
  999. } else {
  1000. DumpSegName = "";
  1001. DumpSectName = DumpSegSectName.first;
  1002. }
  1003. for (const SectionRef &Section : O->sections()) {
  1004. StringRef SectName;
  1005. Section.getName(SectName);
  1006. DataRefImpl Ref = Section.getRawDataRefImpl();
  1007. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  1008. if ((DumpSegName.empty() || SegName == DumpSegName) &&
  1009. (SectName == DumpSectName)) {
  1010. uint32_t section_flags;
  1011. if (O->is64Bit()) {
  1012. const MachO::section_64 Sec = O->getSection64(Ref);
  1013. section_flags = Sec.flags;
  1014. } else {
  1015. const MachO::section Sec = O->getSection(Ref);
  1016. section_flags = Sec.flags;
  1017. }
  1018. uint32_t section_type = section_flags & MachO::SECTION_TYPE;
  1019. StringRef BytesStr;
  1020. Section.getContents(BytesStr);
  1021. const char *sect = reinterpret_cast<const char *>(BytesStr.data());
  1022. uint32_t sect_size = BytesStr.size();
  1023. uint64_t sect_addr = Section.getAddress();
  1024. outs() << "Contents of (" << SegName << "," << SectName
  1025. << ") section\n";
  1026. if (verbose) {
  1027. if ((section_flags & MachO::S_ATTR_PURE_INSTRUCTIONS) ||
  1028. (section_flags & MachO::S_ATTR_SOME_INSTRUCTIONS)) {
  1029. DisassembleMachO(Filename, O, SegName, SectName);
  1030. continue;
  1031. }
  1032. if (SegName == "__TEXT" && SectName == "__info_plist") {
  1033. outs() << sect;
  1034. continue;
  1035. }
  1036. if (SegName == "__OBJC" && SectName == "__protocol") {
  1037. DumpProtocolSection(O, sect, sect_size, sect_addr);
  1038. continue;
  1039. }
  1040. #ifdef HAVE_LIBXAR
  1041. if (SegName == "__LLVM" && SectName == "__bundle") {
  1042. DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands,
  1043. ArchiveHeaders, "");
  1044. continue;
  1045. }
  1046. #endif // defined(HAVE_LIBXAR)
  1047. switch (section_type) {
  1048. case MachO::S_REGULAR:
  1049. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1050. break;
  1051. case MachO::S_ZEROFILL:
  1052. outs() << "zerofill section and has no contents in the file\n";
  1053. break;
  1054. case MachO::S_CSTRING_LITERALS:
  1055. DumpCstringSection(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1056. break;
  1057. case MachO::S_4BYTE_LITERALS:
  1058. DumpLiteral4Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1059. break;
  1060. case MachO::S_8BYTE_LITERALS:
  1061. DumpLiteral8Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1062. break;
  1063. case MachO::S_16BYTE_LITERALS:
  1064. DumpLiteral16Section(O, sect, sect_size, sect_addr, !NoLeadingAddr);
  1065. break;
  1066. case MachO::S_LITERAL_POINTERS:
  1067. DumpLiteralPointerSection(O, Section, sect, sect_size, sect_addr,
  1068. !NoLeadingAddr);
  1069. break;
  1070. case MachO::S_MOD_INIT_FUNC_POINTERS:
  1071. case MachO::S_MOD_TERM_FUNC_POINTERS:
  1072. DumpInitTermPointerSection(O, sect, sect_size, sect_addr, &AddrMap,
  1073. verbose);
  1074. break;
  1075. default:
  1076. outs() << "Unknown section type ("
  1077. << format("0x%08" PRIx32, section_type) << ")\n";
  1078. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1079. break;
  1080. }
  1081. } else {
  1082. if (section_type == MachO::S_ZEROFILL)
  1083. outs() << "zerofill section and has no contents in the file\n";
  1084. else
  1085. DumpRawSectionContents(O, sect, sect_size, sect_addr);
  1086. }
  1087. }
  1088. }
  1089. }
  1090. }
  1091. static void DumpInfoPlistSectionContents(StringRef Filename,
  1092. MachOObjectFile *O) {
  1093. for (const SectionRef &Section : O->sections()) {
  1094. StringRef SectName;
  1095. Section.getName(SectName);
  1096. DataRefImpl Ref = Section.getRawDataRefImpl();
  1097. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  1098. if (SegName == "__TEXT" && SectName == "__info_plist") {
  1099. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  1100. StringRef BytesStr;
  1101. Section.getContents(BytesStr);
  1102. const char *sect = reinterpret_cast<const char *>(BytesStr.data());
  1103. outs() << sect;
  1104. return;
  1105. }
  1106. }
  1107. }
  1108. // checkMachOAndArchFlags() checks to see if the ObjectFile is a Mach-O file
  1109. // and if it is and there is a list of architecture flags is specified then
  1110. // check to make sure this Mach-O file is one of those architectures or all
  1111. // architectures were specified. If not then an error is generated and this
  1112. // routine returns false. Else it returns true.
  1113. static bool checkMachOAndArchFlags(ObjectFile *O, StringRef Filename) {
  1114. if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) {
  1115. MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O);
  1116. bool ArchFound = false;
  1117. MachO::mach_header H;
  1118. MachO::mach_header_64 H_64;
  1119. Triple T;
  1120. if (MachO->is64Bit()) {
  1121. H_64 = MachO->MachOObjectFile::getHeader64();
  1122. T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype);
  1123. } else {
  1124. H = MachO->MachOObjectFile::getHeader();
  1125. T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype);
  1126. }
  1127. unsigned i;
  1128. for (i = 0; i < ArchFlags.size(); ++i) {
  1129. if (ArchFlags[i] == T.getArchName())
  1130. ArchFound = true;
  1131. break;
  1132. }
  1133. if (!ArchFound) {
  1134. errs() << "llvm-objdump: file: " + Filename + " does not contain "
  1135. << "architecture: " + ArchFlags[i] + "\n";
  1136. return false;
  1137. }
  1138. }
  1139. return true;
  1140. }
  1141. static void printObjcMetaData(MachOObjectFile *O, bool verbose);
  1142. // ProcessMachO() is passed a single opened Mach-O file, which may be an
  1143. // archive member and or in a slice of a universal file. It prints the
  1144. // the file name and header info and then processes it according to the
  1145. // command line options.
  1146. static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
  1147. StringRef ArchiveMemberName = StringRef(),
  1148. StringRef ArchitectureName = StringRef()) {
  1149. // If we are doing some processing here on the Mach-O file print the header
  1150. // info. And don't print it otherwise like in the case of printing the
  1151. // UniversalHeaders or ArchiveHeaders.
  1152. if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind || SymbolTable ||
  1153. LazyBind || WeakBind || IndirectSymbols || DataInCode || LinkOptHints ||
  1154. DylibsUsed || DylibId || ObjcMetaData || (FilterSections.size() != 0)) {
  1155. outs() << Filename;
  1156. if (!ArchiveMemberName.empty())
  1157. outs() << '(' << ArchiveMemberName << ')';
  1158. if (!ArchitectureName.empty())
  1159. outs() << " (architecture " << ArchitectureName << ")";
  1160. outs() << ":\n";
  1161. }
  1162. if (Disassemble)
  1163. DisassembleMachO(Filename, MachOOF, "__TEXT", "__text");
  1164. if (IndirectSymbols)
  1165. PrintIndirectSymbols(MachOOF, !NonVerbose);
  1166. if (DataInCode)
  1167. PrintDataInCodeTable(MachOOF, !NonVerbose);
  1168. if (LinkOptHints)
  1169. PrintLinkOptHints(MachOOF);
  1170. if (Relocations)
  1171. PrintRelocations(MachOOF);
  1172. if (SectionHeaders)
  1173. PrintSectionHeaders(MachOOF);
  1174. if (SectionContents)
  1175. PrintSectionContents(MachOOF);
  1176. if (FilterSections.size() != 0)
  1177. DumpSectionContents(Filename, MachOOF, !NonVerbose);
  1178. if (InfoPlist)
  1179. DumpInfoPlistSectionContents(Filename, MachOOF);
  1180. if (DylibsUsed)
  1181. PrintDylibs(MachOOF, false);
  1182. if (DylibId)
  1183. PrintDylibs(MachOOF, true);
  1184. if (SymbolTable) {
  1185. StringRef ArchiveName = ArchiveMemberName == StringRef() ? "" : Filename;
  1186. PrintSymbolTable(MachOOF, ArchiveName, ArchitectureName);
  1187. }
  1188. if (UnwindInfo)
  1189. printMachOUnwindInfo(MachOOF);
  1190. if (PrivateHeaders) {
  1191. printMachOFileHeader(MachOOF);
  1192. printMachOLoadCommands(MachOOF);
  1193. }
  1194. if (FirstPrivateHeader)
  1195. printMachOFileHeader(MachOOF);
  1196. if (ObjcMetaData)
  1197. printObjcMetaData(MachOOF, !NonVerbose);
  1198. if (ExportsTrie)
  1199. printExportsTrie(MachOOF);
  1200. if (Rebase)
  1201. printRebaseTable(MachOOF);
  1202. if (Bind)
  1203. printBindTable(MachOOF);
  1204. if (LazyBind)
  1205. printLazyBindTable(MachOOF);
  1206. if (WeakBind)
  1207. printWeakBindTable(MachOOF);
  1208. if (DwarfDumpType != DIDT_Null) {
  1209. std::unique_ptr<DIContext> DICtx(new DWARFContextInMemory(*MachOOF));
  1210. // Dump the complete DWARF structure.
  1211. DICtx->dump(outs(), DwarfDumpType, true /* DumpEH */);
  1212. }
  1213. }
  1214. // printUnknownCPUType() helps print_fat_headers for unknown CPU's.
  1215. static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
  1216. outs() << " cputype (" << cputype << ")\n";
  1217. outs() << " cpusubtype (" << cpusubtype << ")\n";
  1218. }
  1219. // printCPUType() helps print_fat_headers by printing the cputype and
  1220. // pusubtype (symbolically for the one's it knows about).
  1221. static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
  1222. switch (cputype) {
  1223. case MachO::CPU_TYPE_I386:
  1224. switch (cpusubtype) {
  1225. case MachO::CPU_SUBTYPE_I386_ALL:
  1226. outs() << " cputype CPU_TYPE_I386\n";
  1227. outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
  1228. break;
  1229. default:
  1230. printUnknownCPUType(cputype, cpusubtype);
  1231. break;
  1232. }
  1233. break;
  1234. case MachO::CPU_TYPE_X86_64:
  1235. switch (cpusubtype) {
  1236. case MachO::CPU_SUBTYPE_X86_64_ALL:
  1237. outs() << " cputype CPU_TYPE_X86_64\n";
  1238. outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
  1239. break;
  1240. case MachO::CPU_SUBTYPE_X86_64_H:
  1241. outs() << " cputype CPU_TYPE_X86_64\n";
  1242. outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
  1243. break;
  1244. default:
  1245. printUnknownCPUType(cputype, cpusubtype);
  1246. break;
  1247. }
  1248. break;
  1249. case MachO::CPU_TYPE_ARM:
  1250. switch (cpusubtype) {
  1251. case MachO::CPU_SUBTYPE_ARM_ALL:
  1252. outs() << " cputype CPU_TYPE_ARM\n";
  1253. outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
  1254. break;
  1255. case MachO::CPU_SUBTYPE_ARM_V4T:
  1256. outs() << " cputype CPU_TYPE_ARM\n";
  1257. outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
  1258. break;
  1259. case MachO::CPU_SUBTYPE_ARM_V5TEJ:
  1260. outs() << " cputype CPU_TYPE_ARM\n";
  1261. outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
  1262. break;
  1263. case MachO::CPU_SUBTYPE_ARM_XSCALE:
  1264. outs() << " cputype CPU_TYPE_ARM\n";
  1265. outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
  1266. break;
  1267. case MachO::CPU_SUBTYPE_ARM_V6:
  1268. outs() << " cputype CPU_TYPE_ARM\n";
  1269. outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
  1270. break;
  1271. case MachO::CPU_SUBTYPE_ARM_V6M:
  1272. outs() << " cputype CPU_TYPE_ARM\n";
  1273. outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
  1274. break;
  1275. case MachO::CPU_SUBTYPE_ARM_V7:
  1276. outs() << " cputype CPU_TYPE_ARM\n";
  1277. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
  1278. break;
  1279. case MachO::CPU_SUBTYPE_ARM_V7EM:
  1280. outs() << " cputype CPU_TYPE_ARM\n";
  1281. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
  1282. break;
  1283. case MachO::CPU_SUBTYPE_ARM_V7K:
  1284. outs() << " cputype CPU_TYPE_ARM\n";
  1285. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
  1286. break;
  1287. case MachO::CPU_SUBTYPE_ARM_V7M:
  1288. outs() << " cputype CPU_TYPE_ARM\n";
  1289. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
  1290. break;
  1291. case MachO::CPU_SUBTYPE_ARM_V7S:
  1292. outs() << " cputype CPU_TYPE_ARM\n";
  1293. outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
  1294. break;
  1295. default:
  1296. printUnknownCPUType(cputype, cpusubtype);
  1297. break;
  1298. }
  1299. break;
  1300. case MachO::CPU_TYPE_ARM64:
  1301. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  1302. case MachO::CPU_SUBTYPE_ARM64_ALL:
  1303. outs() << " cputype CPU_TYPE_ARM64\n";
  1304. outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
  1305. break;
  1306. default:
  1307. printUnknownCPUType(cputype, cpusubtype);
  1308. break;
  1309. }
  1310. break;
  1311. default:
  1312. printUnknownCPUType(cputype, cpusubtype);
  1313. break;
  1314. }
  1315. }
  1316. static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
  1317. bool verbose) {
  1318. outs() << "Fat headers\n";
  1319. if (verbose) {
  1320. if (UB->getMagic() == MachO::FAT_MAGIC)
  1321. outs() << "fat_magic FAT_MAGIC\n";
  1322. else // UB->getMagic() == MachO::FAT_MAGIC_64
  1323. outs() << "fat_magic FAT_MAGIC_64\n";
  1324. } else
  1325. outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
  1326. uint32_t nfat_arch = UB->getNumberOfObjects();
  1327. StringRef Buf = UB->getData();
  1328. uint64_t size = Buf.size();
  1329. uint64_t big_size = sizeof(struct MachO::fat_header) +
  1330. nfat_arch * sizeof(struct MachO::fat_arch);
  1331. outs() << "nfat_arch " << UB->getNumberOfObjects();
  1332. if (nfat_arch == 0)
  1333. outs() << " (malformed, contains zero architecture types)\n";
  1334. else if (big_size > size)
  1335. outs() << " (malformed, architectures past end of file)\n";
  1336. else
  1337. outs() << "\n";
  1338. for (uint32_t i = 0; i < nfat_arch; ++i) {
  1339. MachOUniversalBinary::ObjectForArch OFA(UB, i);
  1340. uint32_t cputype = OFA.getCPUType();
  1341. uint32_t cpusubtype = OFA.getCPUSubType();
  1342. outs() << "architecture ";
  1343. for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
  1344. MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
  1345. uint32_t other_cputype = other_OFA.getCPUType();
  1346. uint32_t other_cpusubtype = other_OFA.getCPUSubType();
  1347. if (cputype != 0 && cpusubtype != 0 && cputype == other_cputype &&
  1348. (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
  1349. (other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK)) {
  1350. outs() << "(illegal duplicate architecture) ";
  1351. break;
  1352. }
  1353. }
  1354. if (verbose) {
  1355. outs() << OFA.getArchTypeName() << "\n";
  1356. printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  1357. } else {
  1358. outs() << i << "\n";
  1359. outs() << " cputype " << cputype << "\n";
  1360. outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
  1361. << "\n";
  1362. }
  1363. if (verbose &&
  1364. (cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
  1365. outs() << " capabilities CPU_SUBTYPE_LIB64\n";
  1366. else
  1367. outs() << " capabilities "
  1368. << format("0x%" PRIx32,
  1369. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
  1370. outs() << " offset " << OFA.getOffset();
  1371. if (OFA.getOffset() > size)
  1372. outs() << " (past end of file)";
  1373. if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
  1374. outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
  1375. outs() << "\n";
  1376. outs() << " size " << OFA.getSize();
  1377. big_size = OFA.getOffset() + OFA.getSize();
  1378. if (big_size > size)
  1379. outs() << " (past end of file)";
  1380. outs() << "\n";
  1381. outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
  1382. << ")\n";
  1383. }
  1384. }
  1385. static void printArchiveChild(StringRef Filename, const Archive::Child &C,
  1386. bool verbose, bool print_offset,
  1387. StringRef ArchitectureName = StringRef()) {
  1388. if (print_offset)
  1389. outs() << C.getChildOffset() << "\t";
  1390. sys::fs::perms Mode = C.getAccessMode();
  1391. if (verbose) {
  1392. // FIXME: this first dash, "-", is for (Mode & S_IFMT) == S_IFREG.
  1393. // But there is nothing in sys::fs::perms for S_IFMT or S_IFREG.
  1394. outs() << "-";
  1395. outs() << ((Mode & sys::fs::owner_read) ? "r" : "-");
  1396. outs() << ((Mode & sys::fs::owner_write) ? "w" : "-");
  1397. outs() << ((Mode & sys::fs::owner_exe) ? "x" : "-");
  1398. outs() << ((Mode & sys::fs::group_read) ? "r" : "-");
  1399. outs() << ((Mode & sys::fs::group_write) ? "w" : "-");
  1400. outs() << ((Mode & sys::fs::group_exe) ? "x" : "-");
  1401. outs() << ((Mode & sys::fs::others_read) ? "r" : "-");
  1402. outs() << ((Mode & sys::fs::others_write) ? "w" : "-");
  1403. outs() << ((Mode & sys::fs::others_exe) ? "x" : "-");
  1404. } else {
  1405. outs() << format("0%o ", Mode);
  1406. }
  1407. unsigned UID = C.getUID();
  1408. outs() << format("%3d/", UID);
  1409. unsigned GID = C.getGID();
  1410. outs() << format("%-3d ", GID);
  1411. Expected<uint64_t> Size = C.getRawSize();
  1412. if (!Size)
  1413. report_error(Filename, C, Size.takeError(), ArchitectureName);
  1414. outs() << format("%5" PRId64, Size.get()) << " ";
  1415. StringRef RawLastModified = C.getRawLastModified();
  1416. if (verbose) {
  1417. unsigned Seconds;
  1418. if (RawLastModified.getAsInteger(10, Seconds))
  1419. outs() << "(date: \"%s\" contains non-decimal chars) " << RawLastModified;
  1420. else {
  1421. // Since cime(3) returns a 26 character string of the form:
  1422. // "Sun Sep 16 01:03:52 1973\n\0"
  1423. // just print 24 characters.
  1424. time_t t = Seconds;
  1425. outs() << format("%.24s ", ctime(&t));
  1426. }
  1427. } else {
  1428. outs() << RawLastModified << " ";
  1429. }
  1430. if (verbose) {
  1431. Expected<StringRef> NameOrErr = C.getName();
  1432. if (!NameOrErr) {
  1433. consumeError(NameOrErr.takeError());
  1434. Expected<StringRef> NameOrErr = C.getRawName();
  1435. if (!NameOrErr)
  1436. report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
  1437. StringRef RawName = NameOrErr.get();
  1438. outs() << RawName << "\n";
  1439. } else {
  1440. StringRef Name = NameOrErr.get();
  1441. outs() << Name << "\n";
  1442. }
  1443. } else {
  1444. Expected<StringRef> NameOrErr = C.getRawName();
  1445. if (!NameOrErr)
  1446. report_error(Filename, C, NameOrErr.takeError(), ArchitectureName);
  1447. StringRef RawName = NameOrErr.get();
  1448. outs() << RawName << "\n";
  1449. }
  1450. }
  1451. static void printArchiveHeaders(StringRef Filename, Archive *A, bool verbose,
  1452. bool print_offset,
  1453. StringRef ArchitectureName = StringRef()) {
  1454. Error Err;
  1455. for (const auto &C : A->children(Err, false))
  1456. printArchiveChild(Filename, C, verbose, print_offset, ArchitectureName);
  1457. if (Err)
  1458. report_error(Filename, std::move(Err));
  1459. }
  1460. // ParseInputMachO() parses the named Mach-O file in Filename and handles the
  1461. // -arch flags selecting just those slices as specified by them and also parses
  1462. // archive files. Then for each individual Mach-O file ProcessMachO() is
  1463. // called to process the file based on the command line options.
  1464. void llvm::ParseInputMachO(StringRef Filename) {
  1465. // Check for -arch all and verifiy the -arch flags are valid.
  1466. for (unsigned i = 0; i < ArchFlags.size(); ++i) {
  1467. if (ArchFlags[i] == "all") {
  1468. ArchAll = true;
  1469. } else {
  1470. if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
  1471. errs() << "llvm-objdump: Unknown architecture named '" + ArchFlags[i] +
  1472. "'for the -arch option\n";
  1473. return;
  1474. }
  1475. }
  1476. }
  1477. // Attempt to open the binary.
  1478. Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
  1479. if (!BinaryOrErr)
  1480. report_error(Filename, BinaryOrErr.takeError());
  1481. Binary &Bin = *BinaryOrErr.get().getBinary();
  1482. if (Archive *A = dyn_cast<Archive>(&Bin)) {
  1483. outs() << "Archive : " << Filename << "\n";
  1484. if (ArchiveHeaders)
  1485. printArchiveHeaders(Filename, A, !NonVerbose, ArchiveMemberOffsets);
  1486. Error Err;
  1487. for (auto &C : A->children(Err)) {
  1488. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1489. if (!ChildOrErr) {
  1490. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1491. report_error(Filename, C, std::move(E));
  1492. continue;
  1493. }
  1494. if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
  1495. if (!checkMachOAndArchFlags(O, Filename))
  1496. return;
  1497. ProcessMachO(Filename, O, O->getFileName());
  1498. }
  1499. }
  1500. if (Err)
  1501. report_error(Filename, std::move(Err));
  1502. return;
  1503. }
  1504. if (UniversalHeaders) {
  1505. if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
  1506. printMachOUniversalHeaders(UB, !NonVerbose);
  1507. }
  1508. if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
  1509. // If we have a list of architecture flags specified dump only those.
  1510. if (!ArchAll && ArchFlags.size() != 0) {
  1511. // Look for a slice in the universal binary that matches each ArchFlag.
  1512. bool ArchFound;
  1513. for (unsigned i = 0; i < ArchFlags.size(); ++i) {
  1514. ArchFound = false;
  1515. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1516. E = UB->end_objects();
  1517. I != E; ++I) {
  1518. if (ArchFlags[i] == I->getArchTypeName()) {
  1519. ArchFound = true;
  1520. Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
  1521. I->getAsObjectFile();
  1522. std::string ArchitectureName = "";
  1523. if (ArchFlags.size() > 1)
  1524. ArchitectureName = I->getArchTypeName();
  1525. if (ObjOrErr) {
  1526. ObjectFile &O = *ObjOrErr.get();
  1527. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
  1528. ProcessMachO(Filename, MachOOF, "", ArchitectureName);
  1529. } else if (auto E = isNotObjectErrorInvalidFileType(
  1530. ObjOrErr.takeError())) {
  1531. report_error(Filename, StringRef(), std::move(E),
  1532. ArchitectureName);
  1533. continue;
  1534. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1535. I->getAsArchive()) {
  1536. std::unique_ptr<Archive> &A = *AOrErr;
  1537. outs() << "Archive : " << Filename;
  1538. if (!ArchitectureName.empty())
  1539. outs() << " (architecture " << ArchitectureName << ")";
  1540. outs() << "\n";
  1541. if (ArchiveHeaders)
  1542. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1543. ArchiveMemberOffsets, ArchitectureName);
  1544. Error Err;
  1545. for (auto &C : A->children(Err)) {
  1546. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1547. if (!ChildOrErr) {
  1548. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1549. report_error(Filename, C, std::move(E), ArchitectureName);
  1550. continue;
  1551. }
  1552. if (MachOObjectFile *O =
  1553. dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
  1554. ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
  1555. }
  1556. if (Err)
  1557. report_error(Filename, std::move(Err));
  1558. } else {
  1559. consumeError(AOrErr.takeError());
  1560. error("Mach-O universal file: " + Filename + " for " +
  1561. "architecture " + StringRef(I->getArchTypeName()) +
  1562. " is not a Mach-O file or an archive file");
  1563. }
  1564. }
  1565. }
  1566. if (!ArchFound) {
  1567. errs() << "llvm-objdump: file: " + Filename + " does not contain "
  1568. << "architecture: " + ArchFlags[i] + "\n";
  1569. return;
  1570. }
  1571. }
  1572. return;
  1573. }
  1574. // No architecture flags were specified so if this contains a slice that
  1575. // matches the host architecture dump only that.
  1576. if (!ArchAll) {
  1577. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1578. E = UB->end_objects();
  1579. I != E; ++I) {
  1580. if (MachOObjectFile::getHostArch().getArchName() ==
  1581. I->getArchTypeName()) {
  1582. Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
  1583. std::string ArchiveName;
  1584. ArchiveName.clear();
  1585. if (ObjOrErr) {
  1586. ObjectFile &O = *ObjOrErr.get();
  1587. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
  1588. ProcessMachO(Filename, MachOOF);
  1589. } else if (auto E = isNotObjectErrorInvalidFileType(
  1590. ObjOrErr.takeError())) {
  1591. report_error(Filename, std::move(E));
  1592. continue;
  1593. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1594. I->getAsArchive()) {
  1595. std::unique_ptr<Archive> &A = *AOrErr;
  1596. outs() << "Archive : " << Filename << "\n";
  1597. if (ArchiveHeaders)
  1598. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1599. ArchiveMemberOffsets);
  1600. Error Err;
  1601. for (auto &C : A->children(Err)) {
  1602. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1603. if (!ChildOrErr) {
  1604. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1605. report_error(Filename, C, std::move(E));
  1606. continue;
  1607. }
  1608. if (MachOObjectFile *O =
  1609. dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
  1610. ProcessMachO(Filename, O, O->getFileName());
  1611. }
  1612. if (Err)
  1613. report_error(Filename, std::move(Err));
  1614. } else {
  1615. consumeError(AOrErr.takeError());
  1616. error("Mach-O universal file: " + Filename + " for architecture " +
  1617. StringRef(I->getArchTypeName()) +
  1618. " is not a Mach-O file or an archive file");
  1619. }
  1620. return;
  1621. }
  1622. }
  1623. }
  1624. // Either all architectures have been specified or none have been specified
  1625. // and this does not contain the host architecture so dump all the slices.
  1626. bool moreThanOneArch = UB->getNumberOfObjects() > 1;
  1627. for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
  1628. E = UB->end_objects();
  1629. I != E; ++I) {
  1630. Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
  1631. std::string ArchitectureName = "";
  1632. if (moreThanOneArch)
  1633. ArchitectureName = I->getArchTypeName();
  1634. if (ObjOrErr) {
  1635. ObjectFile &Obj = *ObjOrErr.get();
  1636. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
  1637. ProcessMachO(Filename, MachOOF, "", ArchitectureName);
  1638. } else if (auto E = isNotObjectErrorInvalidFileType(
  1639. ObjOrErr.takeError())) {
  1640. report_error(StringRef(), Filename, std::move(E), ArchitectureName);
  1641. continue;
  1642. } else if (Expected<std::unique_ptr<Archive>> AOrErr =
  1643. I->getAsArchive()) {
  1644. std::unique_ptr<Archive> &A = *AOrErr;
  1645. outs() << "Archive : " << Filename;
  1646. if (!ArchitectureName.empty())
  1647. outs() << " (architecture " << ArchitectureName << ")";
  1648. outs() << "\n";
  1649. if (ArchiveHeaders)
  1650. printArchiveHeaders(Filename, A.get(), !NonVerbose,
  1651. ArchiveMemberOffsets, ArchitectureName);
  1652. Error Err;
  1653. for (auto &C : A->children(Err)) {
  1654. Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
  1655. if (!ChildOrErr) {
  1656. if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
  1657. report_error(Filename, C, std::move(E), ArchitectureName);
  1658. continue;
  1659. }
  1660. if (MachOObjectFile *O =
  1661. dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
  1662. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
  1663. ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
  1664. ArchitectureName);
  1665. }
  1666. }
  1667. if (Err)
  1668. report_error(Filename, std::move(Err));
  1669. } else {
  1670. consumeError(AOrErr.takeError());
  1671. error("Mach-O universal file: " + Filename + " for architecture " +
  1672. StringRef(I->getArchTypeName()) +
  1673. " is not a Mach-O file or an archive file");
  1674. }
  1675. }
  1676. return;
  1677. }
  1678. if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
  1679. if (!checkMachOAndArchFlags(O, Filename))
  1680. return;
  1681. if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
  1682. ProcessMachO(Filename, MachOOF);
  1683. } else
  1684. errs() << "llvm-objdump: '" << Filename << "': "
  1685. << "Object is not a Mach-O file type.\n";
  1686. return;
  1687. }
  1688. llvm_unreachable("Input object can't be invalid at this point");
  1689. }
  1690. typedef std::pair<uint64_t, const char *> BindInfoEntry;
  1691. typedef std::vector<BindInfoEntry> BindTable;
  1692. typedef BindTable::iterator bind_table_iterator;
  1693. // The block of info used by the Symbolizer call backs.
  1694. struct DisassembleInfo {
  1695. bool verbose;
  1696. MachOObjectFile *O;
  1697. SectionRef S;
  1698. SymbolAddressMap *AddrMap;
  1699. std::vector<SectionRef> *Sections;
  1700. const char *class_name;
  1701. const char *selector_name;
  1702. char *method;
  1703. char *demangled_name;
  1704. uint64_t adrp_addr;
  1705. uint32_t adrp_inst;
  1706. BindTable *bindtable;
  1707. uint32_t depth;
  1708. };
  1709. // SymbolizerGetOpInfo() is the operand information call back function.
  1710. // This is called to get the symbolic information for operand(s) of an
  1711. // instruction when it is being done. This routine does this from
  1712. // the relocation information, symbol table, etc. That block of information
  1713. // is a pointer to the struct DisassembleInfo that was passed when the
  1714. // disassembler context was created and passed to back to here when
  1715. // called back by the disassembler for instruction operands that could have
  1716. // relocation information. The address of the instruction containing operand is
  1717. // at the Pc parameter. The immediate value the operand has is passed in
  1718. // op_info->Value and is at Offset past the start of the instruction and has a
  1719. // byte Size of 1, 2 or 4. The symbolc information is returned in TagBuf is the
  1720. // LLVMOpInfo1 struct defined in the header "llvm-c/Disassembler.h" as symbol
  1721. // names and addends of the symbolic expression to add for the operand. The
  1722. // value of TagType is currently 1 (for the LLVMOpInfo1 struct). If symbolic
  1723. // information is returned then this function returns 1 else it returns 0.
  1724. static int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
  1725. uint64_t Size, int TagType, void *TagBuf) {
  1726. struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
  1727. struct LLVMOpInfo1 *op_info = (struct LLVMOpInfo1 *)TagBuf;
  1728. uint64_t value = op_info->Value;
  1729. // Make sure all fields returned are zero if we don't set them.
  1730. memset((void *)op_info, '\0', sizeof(struct LLVMOpInfo1));
  1731. op_info->Value = value;
  1732. // If the TagType is not the value 1 which it code knows about or if no
  1733. // verbose symbolic information is wanted then just return 0, indicating no
  1734. // information is being returned.
  1735. if (TagType != 1 || !info->verbose)
  1736. return 0;
  1737. unsigned int Arch = info->O->getArch();
  1738. if (Arch == Triple::x86) {
  1739. if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
  1740. return 0;
  1741. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1742. // TODO:
  1743. // Search the external relocation entries of a fully linked image
  1744. // (if any) for an entry that matches this segment offset.
  1745. // uint32_t seg_offset = (Pc + Offset);
  1746. return 0;
  1747. }
  1748. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1749. // for an entry for this section offset.
  1750. uint32_t sect_addr = info->S.getAddress();
  1751. uint32_t sect_offset = (Pc + Offset) - sect_addr;
  1752. bool reloc_found = false;
  1753. DataRefImpl Rel;
  1754. MachO::any_relocation_info RE;
  1755. bool isExtern = false;
  1756. SymbolRef Symbol;
  1757. bool r_scattered = false;
  1758. uint32_t r_value, pair_r_value, r_type;
  1759. for (const RelocationRef &Reloc : info->S.relocations()) {
  1760. uint64_t RelocOffset = Reloc.getOffset();
  1761. if (RelocOffset == sect_offset) {
  1762. Rel = Reloc.getRawDataRefImpl();
  1763. RE = info->O->getRelocation(Rel);
  1764. r_type = info->O->getAnyRelocationType(RE);
  1765. r_scattered = info->O->isRelocationScattered(RE);
  1766. if (r_scattered) {
  1767. r_value = info->O->getScatteredRelocationValue(RE);
  1768. if (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
  1769. r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) {
  1770. DataRefImpl RelNext = Rel;
  1771. info->O->moveRelocationNext(RelNext);
  1772. MachO::any_relocation_info RENext;
  1773. RENext = info->O->getRelocation(RelNext);
  1774. if (info->O->isRelocationScattered(RENext))
  1775. pair_r_value = info->O->getScatteredRelocationValue(RENext);
  1776. else
  1777. return 0;
  1778. }
  1779. } else {
  1780. isExtern = info->O->getPlainRelocationExternal(RE);
  1781. if (isExtern) {
  1782. symbol_iterator RelocSym = Reloc.getSymbol();
  1783. Symbol = *RelocSym;
  1784. }
  1785. }
  1786. reloc_found = true;
  1787. break;
  1788. }
  1789. }
  1790. if (reloc_found && isExtern) {
  1791. Expected<StringRef> SymName = Symbol.getName();
  1792. if (!SymName) {
  1793. std::string Buf;
  1794. raw_string_ostream OS(Buf);
  1795. logAllUnhandledErrors(SymName.takeError(), OS, "");
  1796. OS.flush();
  1797. report_fatal_error(Buf);
  1798. }
  1799. const char *name = SymName->data();
  1800. op_info->AddSymbol.Present = 1;
  1801. op_info->AddSymbol.Name = name;
  1802. // For i386 extern relocation entries the value in the instruction is
  1803. // the offset from the symbol, and value is already set in op_info->Value.
  1804. return 1;
  1805. }
  1806. if (reloc_found && (r_type == MachO::GENERIC_RELOC_SECTDIFF ||
  1807. r_type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF)) {
  1808. const char *add = GuessSymbolName(r_value, info->AddrMap);
  1809. const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
  1810. uint32_t offset = value - (r_value - pair_r_value);
  1811. op_info->AddSymbol.Present = 1;
  1812. if (add != nullptr)
  1813. op_info->AddSymbol.Name = add;
  1814. else
  1815. op_info->AddSymbol.Value = r_value;
  1816. op_info->SubtractSymbol.Present = 1;
  1817. if (sub != nullptr)
  1818. op_info->SubtractSymbol.Name = sub;
  1819. else
  1820. op_info->SubtractSymbol.Value = pair_r_value;
  1821. op_info->Value = offset;
  1822. return 1;
  1823. }
  1824. return 0;
  1825. }
  1826. if (Arch == Triple::x86_64) {
  1827. if (Size != 1 && Size != 2 && Size != 4 && Size != 0)
  1828. return 0;
  1829. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1830. // TODO:
  1831. // Search the external relocation entries of a fully linked image
  1832. // (if any) for an entry that matches this segment offset.
  1833. // uint64_t seg_offset = (Pc + Offset);
  1834. return 0;
  1835. }
  1836. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1837. // for an entry for this section offset.
  1838. uint64_t sect_addr = info->S.getAddress();
  1839. uint64_t sect_offset = (Pc + Offset) - sect_addr;
  1840. bool reloc_found = false;
  1841. DataRefImpl Rel;
  1842. MachO::any_relocation_info RE;
  1843. bool isExtern = false;
  1844. SymbolRef Symbol;
  1845. for (const RelocationRef &Reloc : info->S.relocations()) {
  1846. uint64_t RelocOffset = Reloc.getOffset();
  1847. if (RelocOffset == sect_offset) {
  1848. Rel = Reloc.getRawDataRefImpl();
  1849. RE = info->O->getRelocation(Rel);
  1850. // NOTE: Scattered relocations don't exist on x86_64.
  1851. isExtern = info->O->getPlainRelocationExternal(RE);
  1852. if (isExtern) {
  1853. symbol_iterator RelocSym = Reloc.getSymbol();
  1854. Symbol = *RelocSym;
  1855. }
  1856. reloc_found = true;
  1857. break;
  1858. }
  1859. }
  1860. if (reloc_found && isExtern) {
  1861. // The Value passed in will be adjusted by the Pc if the instruction
  1862. // adds the Pc. But for x86_64 external relocation entries the Value
  1863. // is the offset from the external symbol.
  1864. if (info->O->getAnyRelocationPCRel(RE))
  1865. op_info->Value -= Pc + Offset + Size;
  1866. Expected<StringRef> SymName = Symbol.getName();
  1867. if (!SymName) {
  1868. std::string Buf;
  1869. raw_string_ostream OS(Buf);
  1870. logAllUnhandledErrors(SymName.takeError(), OS, "");
  1871. OS.flush();
  1872. report_fatal_error(Buf);
  1873. }
  1874. const char *name = SymName->data();
  1875. unsigned Type = info->O->getAnyRelocationType(RE);
  1876. if (Type == MachO::X86_64_RELOC_SUBTRACTOR) {
  1877. DataRefImpl RelNext = Rel;
  1878. info->O->moveRelocationNext(RelNext);
  1879. MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
  1880. unsigned TypeNext = info->O->getAnyRelocationType(RENext);
  1881. bool isExternNext = info->O->getPlainRelocationExternal(RENext);
  1882. unsigned SymbolNum = info->O->getPlainRelocationSymbolNum(RENext);
  1883. if (TypeNext == MachO::X86_64_RELOC_UNSIGNED && isExternNext) {
  1884. op_info->SubtractSymbol.Present = 1;
  1885. op_info->SubtractSymbol.Name = name;
  1886. symbol_iterator RelocSymNext = info->O->getSymbolByIndex(SymbolNum);
  1887. Symbol = *RelocSymNext;
  1888. Expected<StringRef> SymNameNext = Symbol.getName();
  1889. if (!SymNameNext) {
  1890. std::string Buf;
  1891. raw_string_ostream OS(Buf);
  1892. logAllUnhandledErrors(SymNameNext.takeError(), OS, "");
  1893. OS.flush();
  1894. report_fatal_error(Buf);
  1895. }
  1896. name = SymNameNext->data();
  1897. }
  1898. }
  1899. // TODO: add the VariantKinds to op_info->VariantKind for relocation types
  1900. // like: X86_64_RELOC_TLV, X86_64_RELOC_GOT_LOAD and X86_64_RELOC_GOT.
  1901. op_info->AddSymbol.Present = 1;
  1902. op_info->AddSymbol.Name = name;
  1903. return 1;
  1904. }
  1905. return 0;
  1906. }
  1907. if (Arch == Triple::arm) {
  1908. if (Offset != 0 || (Size != 4 && Size != 2))
  1909. return 0;
  1910. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  1911. // TODO:
  1912. // Search the external relocation entries of a fully linked image
  1913. // (if any) for an entry that matches this segment offset.
  1914. // uint32_t seg_offset = (Pc + Offset);
  1915. return 0;
  1916. }
  1917. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  1918. // for an entry for this section offset.
  1919. uint32_t sect_addr = info->S.getAddress();
  1920. uint32_t sect_offset = (Pc + Offset) - sect_addr;
  1921. DataRefImpl Rel;
  1922. MachO::any_relocation_info RE;
  1923. bool isExtern = false;
  1924. SymbolRef Symbol;
  1925. bool r_scattered = false;
  1926. uint32_t r_value, pair_r_value, r_type, r_length, other_half;
  1927. auto Reloc =
  1928. std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
  1929. [&](const RelocationRef &Reloc) {
  1930. uint64_t RelocOffset = Reloc.getOffset();
  1931. return RelocOffset == sect_offset;
  1932. });
  1933. if (Reloc == info->S.relocations().end())
  1934. return 0;
  1935. Rel = Reloc->getRawDataRefImpl();
  1936. RE = info->O->getRelocation(Rel);
  1937. r_length = info->O->getAnyRelocationLength(RE);
  1938. r_scattered = info->O->isRelocationScattered(RE);
  1939. if (r_scattered) {
  1940. r_value = info->O->getScatteredRelocationValue(RE);
  1941. r_type = info->O->getScatteredRelocationType(RE);
  1942. } else {
  1943. r_type = info->O->getAnyRelocationType(RE);
  1944. isExtern = info->O->getPlainRelocationExternal(RE);
  1945. if (isExtern) {
  1946. symbol_iterator RelocSym = Reloc->getSymbol();
  1947. Symbol = *RelocSym;
  1948. }
  1949. }
  1950. if (r_type == MachO::ARM_RELOC_HALF ||
  1951. r_type == MachO::ARM_RELOC_SECTDIFF ||
  1952. r_type == MachO::ARM_RELOC_LOCAL_SECTDIFF ||
  1953. r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  1954. DataRefImpl RelNext = Rel;
  1955. info->O->moveRelocationNext(RelNext);
  1956. MachO::any_relocation_info RENext;
  1957. RENext = info->O->getRelocation(RelNext);
  1958. other_half = info->O->getAnyRelocationAddress(RENext) & 0xffff;
  1959. if (info->O->isRelocationScattered(RENext))
  1960. pair_r_value = info->O->getScatteredRelocationValue(RENext);
  1961. }
  1962. if (isExtern) {
  1963. Expected<StringRef> SymName = Symbol.getName();
  1964. if (!SymName) {
  1965. std::string Buf;
  1966. raw_string_ostream OS(Buf);
  1967. logAllUnhandledErrors(SymName.takeError(), OS, "");
  1968. OS.flush();
  1969. report_fatal_error(Buf);
  1970. }
  1971. const char *name = SymName->data();
  1972. op_info->AddSymbol.Present = 1;
  1973. op_info->AddSymbol.Name = name;
  1974. switch (r_type) {
  1975. case MachO::ARM_RELOC_HALF:
  1976. if ((r_length & 0x1) == 1) {
  1977. op_info->Value = value << 16 | other_half;
  1978. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  1979. } else {
  1980. op_info->Value = other_half << 16 | value;
  1981. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  1982. }
  1983. break;
  1984. default:
  1985. break;
  1986. }
  1987. return 1;
  1988. }
  1989. // If we have a branch that is not an external relocation entry then
  1990. // return 0 so the code in tryAddingSymbolicOperand() can use the
  1991. // SymbolLookUp call back with the branch target address to look up the
  1992. // symbol and possiblity add an annotation for a symbol stub.
  1993. if (isExtern == 0 && (r_type == MachO::ARM_RELOC_BR24 ||
  1994. r_type == MachO::ARM_THUMB_RELOC_BR22))
  1995. return 0;
  1996. uint32_t offset = 0;
  1997. if (r_type == MachO::ARM_RELOC_HALF ||
  1998. r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  1999. if ((r_length & 0x1) == 1)
  2000. value = value << 16 | other_half;
  2001. else
  2002. value = other_half << 16 | value;
  2003. }
  2004. if (r_scattered && (r_type != MachO::ARM_RELOC_HALF &&
  2005. r_type != MachO::ARM_RELOC_HALF_SECTDIFF)) {
  2006. offset = value - r_value;
  2007. value = r_value;
  2008. }
  2009. if (r_type == MachO::ARM_RELOC_HALF_SECTDIFF) {
  2010. if ((r_length & 0x1) == 1)
  2011. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  2012. else
  2013. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  2014. const char *add = GuessSymbolName(r_value, info->AddrMap);
  2015. const char *sub = GuessSymbolName(pair_r_value, info->AddrMap);
  2016. int32_t offset = value - (r_value - pair_r_value);
  2017. op_info->AddSymbol.Present = 1;
  2018. if (add != nullptr)
  2019. op_info->AddSymbol.Name = add;
  2020. else
  2021. op_info->AddSymbol.Value = r_value;
  2022. op_info->SubtractSymbol.Present = 1;
  2023. if (sub != nullptr)
  2024. op_info->SubtractSymbol.Name = sub;
  2025. else
  2026. op_info->SubtractSymbol.Value = pair_r_value;
  2027. op_info->Value = offset;
  2028. return 1;
  2029. }
  2030. op_info->AddSymbol.Present = 1;
  2031. op_info->Value = offset;
  2032. if (r_type == MachO::ARM_RELOC_HALF) {
  2033. if ((r_length & 0x1) == 1)
  2034. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_HI16;
  2035. else
  2036. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM_LO16;
  2037. }
  2038. const char *add = GuessSymbolName(value, info->AddrMap);
  2039. if (add != nullptr) {
  2040. op_info->AddSymbol.Name = add;
  2041. return 1;
  2042. }
  2043. op_info->AddSymbol.Value = value;
  2044. return 1;
  2045. }
  2046. if (Arch == Triple::aarch64) {
  2047. if (Offset != 0 || Size != 4)
  2048. return 0;
  2049. if (info->O->getHeader().filetype != MachO::MH_OBJECT) {
  2050. // TODO:
  2051. // Search the external relocation entries of a fully linked image
  2052. // (if any) for an entry that matches this segment offset.
  2053. // uint64_t seg_offset = (Pc + Offset);
  2054. return 0;
  2055. }
  2056. // In MH_OBJECT filetypes search the section's relocation entries (if any)
  2057. // for an entry for this section offset.
  2058. uint64_t sect_addr = info->S.getAddress();
  2059. uint64_t sect_offset = (Pc + Offset) - sect_addr;
  2060. auto Reloc =
  2061. std::find_if(info->S.relocations().begin(), info->S.relocations().end(),
  2062. [&](const RelocationRef &Reloc) {
  2063. uint64_t RelocOffset = Reloc.getOffset();
  2064. return RelocOffset == sect_offset;
  2065. });
  2066. if (Reloc == info->S.relocations().end())
  2067. return 0;
  2068. DataRefImpl Rel = Reloc->getRawDataRefImpl();
  2069. MachO::any_relocation_info RE = info->O->getRelocation(Rel);
  2070. uint32_t r_type = info->O->getAnyRelocationType(RE);
  2071. if (r_type == MachO::ARM64_RELOC_ADDEND) {
  2072. DataRefImpl RelNext = Rel;
  2073. info->O->moveRelocationNext(RelNext);
  2074. MachO::any_relocation_info RENext = info->O->getRelocation(RelNext);
  2075. if (value == 0) {
  2076. value = info->O->getPlainRelocationSymbolNum(RENext);
  2077. op_info->Value = value;
  2078. }
  2079. }
  2080. // NOTE: Scattered relocations don't exist on arm64.
  2081. if (!info->O->getPlainRelocationExternal(RE))
  2082. return 0;
  2083. Expected<StringRef> SymName = Reloc->getSymbol()->getName();
  2084. if (!SymName) {
  2085. std::string Buf;
  2086. raw_string_ostream OS(Buf);
  2087. logAllUnhandledErrors(SymName.takeError(), OS, "");
  2088. OS.flush();
  2089. report_fatal_error(Buf);
  2090. }
  2091. const char *name = SymName->data();
  2092. op_info->AddSymbol.Present = 1;
  2093. op_info->AddSymbol.Name = name;
  2094. switch (r_type) {
  2095. case MachO::ARM64_RELOC_PAGE21:
  2096. /* @page */
  2097. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGE;
  2098. break;
  2099. case MachO::ARM64_RELOC_PAGEOFF12:
  2100. /* @pageoff */
  2101. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_PAGEOFF;
  2102. break;
  2103. case MachO::ARM64_RELOC_GOT_LOAD_PAGE21:
  2104. /* @gotpage */
  2105. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGE;
  2106. break;
  2107. case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12:
  2108. /* @gotpageoff */
  2109. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_GOTPAGEOFF;
  2110. break;
  2111. case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21:
  2112. /* @tvlppage is not implemented in llvm-mc */
  2113. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVP;
  2114. break;
  2115. case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
  2116. /* @tvlppageoff is not implemented in llvm-mc */
  2117. op_info->VariantKind = LLVMDisassembler_VariantKind_ARM64_TLVOFF;
  2118. break;
  2119. default:
  2120. case MachO::ARM64_RELOC_BRANCH26:
  2121. op_info->VariantKind = LLVMDisassembler_VariantKind_None;
  2122. break;
  2123. }
  2124. return 1;
  2125. }
  2126. return 0;
  2127. }
  2128. // GuessCstringPointer is passed the address of what might be a pointer to a
  2129. // literal string in a cstring section. If that address is in a cstring section
  2130. // it returns a pointer to that string. Else it returns nullptr.
  2131. static const char *GuessCstringPointer(uint64_t ReferenceValue,
  2132. struct DisassembleInfo *info) {
  2133. for (const auto &Load : info->O->load_commands()) {
  2134. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2135. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2136. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2137. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2138. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2139. if (section_type == MachO::S_CSTRING_LITERALS &&
  2140. ReferenceValue >= Sec.addr &&
  2141. ReferenceValue < Sec.addr + Sec.size) {
  2142. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2143. uint64_t object_offset = Sec.offset + sect_offset;
  2144. StringRef MachOContents = info->O->getData();
  2145. uint64_t object_size = MachOContents.size();
  2146. const char *object_addr = (const char *)MachOContents.data();
  2147. if (object_offset < object_size) {
  2148. const char *name = object_addr + object_offset;
  2149. return name;
  2150. } else {
  2151. return nullptr;
  2152. }
  2153. }
  2154. }
  2155. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  2156. MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
  2157. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2158. MachO::section Sec = info->O->getSection(Load, J);
  2159. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2160. if (section_type == MachO::S_CSTRING_LITERALS &&
  2161. ReferenceValue >= Sec.addr &&
  2162. ReferenceValue < Sec.addr + Sec.size) {
  2163. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2164. uint64_t object_offset = Sec.offset + sect_offset;
  2165. StringRef MachOContents = info->O->getData();
  2166. uint64_t object_size = MachOContents.size();
  2167. const char *object_addr = (const char *)MachOContents.data();
  2168. if (object_offset < object_size) {
  2169. const char *name = object_addr + object_offset;
  2170. return name;
  2171. } else {
  2172. return nullptr;
  2173. }
  2174. }
  2175. }
  2176. }
  2177. }
  2178. return nullptr;
  2179. }
  2180. // GuessIndirectSymbol returns the name of the indirect symbol for the
  2181. // ReferenceValue passed in or nullptr. This is used when ReferenceValue maybe
  2182. // an address of a symbol stub or a lazy or non-lazy pointer to associate the
  2183. // symbol name being referenced by the stub or pointer.
  2184. static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
  2185. struct DisassembleInfo *info) {
  2186. MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
  2187. MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
  2188. for (const auto &Load : info->O->load_commands()) {
  2189. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2190. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2191. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2192. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2193. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2194. if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  2195. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  2196. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  2197. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  2198. section_type == MachO::S_SYMBOL_STUBS) &&
  2199. ReferenceValue >= Sec.addr &&
  2200. ReferenceValue < Sec.addr + Sec.size) {
  2201. uint32_t stride;
  2202. if (section_type == MachO::S_SYMBOL_STUBS)
  2203. stride = Sec.reserved2;
  2204. else
  2205. stride = 8;
  2206. if (stride == 0)
  2207. return nullptr;
  2208. uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
  2209. if (index < Dysymtab.nindirectsyms) {
  2210. uint32_t indirect_symbol =
  2211. info->O->getIndirectSymbolTableEntry(Dysymtab, index);
  2212. if (indirect_symbol < Symtab.nsyms) {
  2213. symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
  2214. SymbolRef Symbol = *Sym;
  2215. Expected<StringRef> SymName = Symbol.getName();
  2216. if (!SymName) {
  2217. std::string Buf;
  2218. raw_string_ostream OS(Buf);
  2219. logAllUnhandledErrors(SymName.takeError(), OS, "");
  2220. OS.flush();
  2221. report_fatal_error(Buf);
  2222. }
  2223. const char *name = SymName->data();
  2224. return name;
  2225. }
  2226. }
  2227. }
  2228. }
  2229. } else if (Load.C.cmd == MachO::LC_SEGMENT) {
  2230. MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
  2231. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2232. MachO::section Sec = info->O->getSection(Load, J);
  2233. uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
  2234. if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  2235. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  2236. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  2237. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
  2238. section_type == MachO::S_SYMBOL_STUBS) &&
  2239. ReferenceValue >= Sec.addr &&
  2240. ReferenceValue < Sec.addr + Sec.size) {
  2241. uint32_t stride;
  2242. if (section_type == MachO::S_SYMBOL_STUBS)
  2243. stride = Sec.reserved2;
  2244. else
  2245. stride = 4;
  2246. if (stride == 0)
  2247. return nullptr;
  2248. uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
  2249. if (index < Dysymtab.nindirectsyms) {
  2250. uint32_t indirect_symbol =
  2251. info->O->getIndirectSymbolTableEntry(Dysymtab, index);
  2252. if (indirect_symbol < Symtab.nsyms) {
  2253. symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
  2254. SymbolRef Symbol = *Sym;
  2255. Expected<StringRef> SymName = Symbol.getName();
  2256. if (!SymName) {
  2257. std::string Buf;
  2258. raw_string_ostream OS(Buf);
  2259. logAllUnhandledErrors(SymName.takeError(), OS, "");
  2260. OS.flush();
  2261. report_fatal_error(Buf);
  2262. }
  2263. const char *name = SymName->data();
  2264. return name;
  2265. }
  2266. }
  2267. }
  2268. }
  2269. }
  2270. }
  2271. return nullptr;
  2272. }
  2273. // method_reference() is called passing it the ReferenceName that might be
  2274. // a reference it to an Objective-C method call. If so then it allocates and
  2275. // assembles a method call string with the values last seen and saved in
  2276. // the DisassembleInfo's class_name and selector_name fields. This is saved
  2277. // into the method field of the info and any previous string is free'ed.
  2278. // Then the class_name field in the info is set to nullptr. The method call
  2279. // string is set into ReferenceName and ReferenceType is set to
  2280. // LLVMDisassembler_ReferenceType_Out_Objc_Message. If this not a method call
  2281. // then both ReferenceType and ReferenceName are left unchanged.
  2282. static void method_reference(struct DisassembleInfo *info,
  2283. uint64_t *ReferenceType,
  2284. const char **ReferenceName) {
  2285. unsigned int Arch = info->O->getArch();
  2286. if (*ReferenceName != nullptr) {
  2287. if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
  2288. if (info->selector_name != nullptr) {
  2289. if (info->method != nullptr)
  2290. free(info->method);
  2291. if (info->class_name != nullptr) {
  2292. info->method = (char *)malloc(5 + strlen(info->class_name) +
  2293. strlen(info->selector_name));
  2294. if (info->method != nullptr) {
  2295. strcpy(info->method, "+[");
  2296. strcat(info->method, info->class_name);
  2297. strcat(info->method, " ");
  2298. strcat(info->method, info->selector_name);
  2299. strcat(info->method, "]");
  2300. *ReferenceName = info->method;
  2301. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2302. }
  2303. } else {
  2304. info->method = (char *)malloc(9 + strlen(info->selector_name));
  2305. if (info->method != nullptr) {
  2306. if (Arch == Triple::x86_64)
  2307. strcpy(info->method, "-[%rdi ");
  2308. else if (Arch == Triple::aarch64)
  2309. strcpy(info->method, "-[x0 ");
  2310. else
  2311. strcpy(info->method, "-[r? ");
  2312. strcat(info->method, info->selector_name);
  2313. strcat(info->method, "]");
  2314. *ReferenceName = info->method;
  2315. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2316. }
  2317. }
  2318. info->class_name = nullptr;
  2319. }
  2320. } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
  2321. if (info->selector_name != nullptr) {
  2322. if (info->method != nullptr)
  2323. free(info->method);
  2324. info->method = (char *)malloc(17 + strlen(info->selector_name));
  2325. if (info->method != nullptr) {
  2326. if (Arch == Triple::x86_64)
  2327. strcpy(info->method, "-[[%rdi super] ");
  2328. else if (Arch == Triple::aarch64)
  2329. strcpy(info->method, "-[[x0 super] ");
  2330. else
  2331. strcpy(info->method, "-[[r? super] ");
  2332. strcat(info->method, info->selector_name);
  2333. strcat(info->method, "]");
  2334. *ReferenceName = info->method;
  2335. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
  2336. }
  2337. info->class_name = nullptr;
  2338. }
  2339. }
  2340. }
  2341. }
  2342. // GuessPointerPointer() is passed the address of what might be a pointer to
  2343. // a reference to an Objective-C class, selector, message ref or cfstring.
  2344. // If so the value of the pointer is returned and one of the booleans are set
  2345. // to true. If not zero is returned and all the booleans are set to false.
  2346. static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
  2347. struct DisassembleInfo *info,
  2348. bool &classref, bool &selref, bool &msgref,
  2349. bool &cfstring) {
  2350. classref = false;
  2351. selref = false;
  2352. msgref = false;
  2353. cfstring = false;
  2354. for (const auto &Load : info->O->load_commands()) {
  2355. if (Load.C.cmd == MachO::LC_SEGMENT_64) {
  2356. MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
  2357. for (unsigned J = 0; J < Seg.nsects; ++J) {
  2358. MachO::section_64 Sec = info->O->getSection64(Load, J);
  2359. if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
  2360. strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
  2361. strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
  2362. strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
  2363. strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
  2364. ReferenceValue >= Sec.addr &&
  2365. ReferenceValue < Sec.addr + Sec.size) {
  2366. uint64_t sect_offset = ReferenceValue - Sec.addr;
  2367. uint64_t object_offset = Sec.offset + sect_offset;
  2368. StringRef MachOContents = info->O->getData();
  2369. uint64_t object_size = MachOContents.size();
  2370. const char *object_addr = (const char *)MachOContents.data();
  2371. if (object_offset < object_size) {
  2372. uint64_t pointer_value;
  2373. memcpy(&pointer_value, object_addr + object_offset,
  2374. sizeof(uint64_t));
  2375. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  2376. sys::swapByteOrder(pointer_value);
  2377. if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
  2378. selref = true;
  2379. else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
  2380. strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
  2381. classref = true;
  2382. else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
  2383. ReferenceValue + 8 < Sec.addr + Sec.size) {
  2384. msgref = true;
  2385. memcpy(&pointer_value, object_addr + object_offset + 8,
  2386. sizeof(uint64_t));
  2387. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  2388. sys::swapByteOrder(pointer_value);
  2389. } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
  2390. cfstring = true;
  2391. return pointer_value;
  2392. } else {
  2393. return 0;
  2394. }
  2395. }
  2396. }
  2397. }
  2398. // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
  2399. }
  2400. return 0;
  2401. }
  2402. // get_pointer_64 returns a pointer to the bytes in the object file at the
  2403. // Address from a section in the Mach-O file. And indirectly returns the
  2404. // offset into the section, number of bytes left in the section past the offset
  2405. // and which section is was being referenced. If the Address is not in a
  2406. // section nullptr is returned.
  2407. static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
  2408. uint32_t &left, SectionRef &S,
  2409. DisassembleInfo *info,
  2410. bool objc_only = false) {
  2411. offset = 0;
  2412. left = 0;
  2413. S = SectionRef();
  2414. for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
  2415. uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
  2416. uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
  2417. if (SectSize == 0)
  2418. continue;
  2419. if (objc_only) {
  2420. StringRef SectName;
  2421. ((*(info->Sections))[SectIdx]).getName(SectName);
  2422. DataRefImpl Ref = ((*(info->Sections))[SectIdx]).getRawDataRefImpl();
  2423. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  2424. if (SegName != "__OBJC" && SectName != "__cstring")
  2425. continue;
  2426. }
  2427. if (Address >= SectAddress && Address < SectAddress + SectSize) {
  2428. S = (*(info->Sections))[SectIdx];
  2429. offset = Address - SectAddress;
  2430. left = SectSize - offset;
  2431. StringRef SectContents;
  2432. ((*(info->Sections))[SectIdx]).getContents(SectContents);
  2433. return SectContents.data() + offset;
  2434. }
  2435. }
  2436. return nullptr;
  2437. }
  2438. static const char *get_pointer_32(uint32_t Address, uint32_t &offset,
  2439. uint32_t &left, SectionRef &S,
  2440. DisassembleInfo *info,
  2441. bool objc_only = false) {
  2442. return get_pointer_64(Address, offset, left, S, info, objc_only);
  2443. }
  2444. // get_symbol_64() returns the name of a symbol (or nullptr) and the address of
  2445. // the symbol indirectly through n_value. Based on the relocation information
  2446. // for the specified section offset in the specified section reference.
  2447. // If no relocation information is found and a non-zero ReferenceValue for the
  2448. // symbol is passed, look up that address in the info's AddrMap.
  2449. static const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
  2450. DisassembleInfo *info, uint64_t &n_value,
  2451. uint64_t ReferenceValue = 0) {
  2452. n_value = 0;
  2453. if (!info->verbose)
  2454. return nullptr;
  2455. // See if there is an external relocation entry at the sect_offset.
  2456. bool reloc_found = false;
  2457. DataRefImpl Rel;
  2458. MachO::any_relocation_info RE;
  2459. bool isExtern = false;
  2460. SymbolRef Symbol;
  2461. for (const RelocationRef &Reloc : S.relocations()) {
  2462. uint64_t RelocOffset = Reloc.getOffset();
  2463. if (RelocOffset == sect_offset) {
  2464. Rel = Reloc.getRawDataRefImpl();
  2465. RE = info->O->getRelocation(Rel);
  2466. if (info->O->isRelocationScattered(RE))
  2467. continue;
  2468. isExtern = info->O->getPlainRelocationExternal(RE);
  2469. if (isExtern) {
  2470. symbol_iterator RelocSym = Reloc.getSymbol();
  2471. Symbol = *RelocSym;
  2472. }
  2473. reloc_found = true;
  2474. break;
  2475. }
  2476. }
  2477. // If there is an external relocation entry for a symbol in this section
  2478. // at this section_offset then use that symbol's value for the n_value
  2479. // and return its name.
  2480. const char *SymbolName = nullptr;
  2481. if (reloc_found && isExtern) {
  2482. n_value = Symbol.getValue();
  2483. Expected<StringRef> NameOrError = Symbol.getName();
  2484. if (!NameOrError) {
  2485. std::string Buf;
  2486. raw_string_ostream OS(Buf);
  2487. logAllUnhandledErrors(NameOrError.takeError(), OS, "");
  2488. OS.flush();
  2489. report_fatal_error(Buf);
  2490. }
  2491. StringRef Name = *NameOrError;
  2492. if (!Name.empty()) {
  2493. SymbolName = Name.data();
  2494. return SymbolName;
  2495. }
  2496. }
  2497. // TODO: For fully linked images, look through the external relocation
  2498. // entries off the dynamic symtab command. For these the r_offset is from the
  2499. // start of the first writeable segment in the Mach-O file. So the offset
  2500. // to this section from that segment is passed to this routine by the caller,
  2501. // as the database_offset. Which is the difference of the section's starting
  2502. // address and the first writable segment.
  2503. //
  2504. // NOTE: need add passing the database_offset to this routine.
  2505. // We did not find an external relocation entry so look up the ReferenceValue
  2506. // as an address of a symbol and if found return that symbol's name.
  2507. SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
  2508. return SymbolName;
  2509. }
  2510. static const char *get_symbol_32(uint32_t sect_offset, SectionRef S,
  2511. DisassembleInfo *info,
  2512. uint32_t ReferenceValue) {
  2513. uint64_t n_value64;
  2514. return get_symbol_64(sect_offset, S, info, n_value64, ReferenceValue);
  2515. }
  2516. // These are structs in the Objective-C meta data and read to produce the
  2517. // comments for disassembly. While these are part of the ABI they are no
  2518. // public defintions. So the are here not in include/llvm/Support/MachO.h .
  2519. // The cfstring object in a 64-bit Mach-O file.
  2520. struct cfstring64_t {
  2521. uint64_t isa; // class64_t * (64-bit pointer)
  2522. uint64_t flags; // flag bits
  2523. uint64_t characters; // char * (64-bit pointer)
  2524. uint64_t length; // number of non-NULL characters in above
  2525. };
  2526. // The class object in a 64-bit Mach-O file.
  2527. struct class64_t {
  2528. uint64_t isa; // class64_t * (64-bit pointer)
  2529. uint64_t superclass; // class64_t * (64-bit pointer)
  2530. uint64_t cache; // Cache (64-bit pointer)
  2531. uint64_t vtable; // IMP * (64-bit pointer)
  2532. uint64_t data; // class_ro64_t * (64-bit pointer)
  2533. };
  2534. struct class32_t {
  2535. uint32_t isa; /* class32_t * (32-bit pointer) */
  2536. uint32_t superclass; /* class32_t * (32-bit pointer) */
  2537. uint32_t cache; /* Cache (32-bit pointer) */
  2538. uint32_t vtable; /* IMP * (32-bit pointer) */
  2539. uint32_t data; /* class_ro32_t * (32-bit pointer) */
  2540. };
  2541. struct class_ro64_t {
  2542. uint32_t flags;
  2543. uint32_t instanceStart;
  2544. uint32_t instanceSize;
  2545. uint32_t reserved;
  2546. uint64_t ivarLayout; // const uint8_t * (64-bit pointer)
  2547. uint64_t name; // const char * (64-bit pointer)
  2548. uint64_t baseMethods; // const method_list_t * (64-bit pointer)
  2549. uint64_t baseProtocols; // const protocol_list_t * (64-bit pointer)
  2550. uint64_t ivars; // const ivar_list_t * (64-bit pointer)
  2551. uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
  2552. uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
  2553. };
  2554. struct class_ro32_t {
  2555. uint32_t flags;
  2556. uint32_t instanceStart;
  2557. uint32_t instanceSize;
  2558. uint32_t ivarLayout; /* const uint8_t * (32-bit pointer) */
  2559. uint32_t name; /* const char * (32-bit pointer) */
  2560. uint32_t baseMethods; /* const method_list_t * (32-bit pointer) */
  2561. uint32_t baseProtocols; /* const protocol_list_t * (32-bit pointer) */
  2562. uint32_t ivars; /* const ivar_list_t * (32-bit pointer) */
  2563. uint32_t weakIvarLayout; /* const uint8_t * (32-bit pointer) */
  2564. uint32_t baseProperties; /* const struct objc_property_list *
  2565. (32-bit pointer) */
  2566. };
  2567. /* Values for class_ro{64,32}_t->flags */
  2568. #define RO_META (1 << 0)
  2569. #define RO_ROOT (1 << 1)
  2570. #define RO_HAS_CXX_STRUCTORS (1 << 2)
  2571. struct method_list64_t {
  2572. uint32_t entsize;
  2573. uint32_t count;
  2574. /* struct method64_t first; These structures follow inline */
  2575. };
  2576. struct method_list32_t {
  2577. uint32_t entsize;
  2578. uint32_t count;
  2579. /* struct method32_t first; These structures follow inline */
  2580. };
  2581. struct method64_t {
  2582. uint64_t name; /* SEL (64-bit pointer) */
  2583. uint64_t types; /* const char * (64-bit pointer) */
  2584. uint64_t imp; /* IMP (64-bit pointer) */
  2585. };
  2586. struct method32_t {
  2587. uint32_t name; /* SEL (32-bit pointer) */
  2588. uint32_t types; /* const char * (32-bit pointer) */
  2589. uint32_t imp; /* IMP (32-bit pointer) */
  2590. };
  2591. struct protocol_list64_t {
  2592. uint64_t count; /* uintptr_t (a 64-bit value) */
  2593. /* struct protocol64_t * list[0]; These pointers follow inline */
  2594. };
  2595. struct protocol_list32_t {
  2596. uint32_t count; /* uintptr_t (a 32-bit value) */
  2597. /* struct protocol32_t * list[0]; These pointers follow inline */
  2598. };
  2599. struct protocol64_t {
  2600. uint64_t isa; /* id * (64-bit pointer) */
  2601. uint64_t name; /* const char * (64-bit pointer) */
  2602. uint64_t protocols; /* struct protocol_list64_t *
  2603. (64-bit pointer) */
  2604. uint64_t instanceMethods; /* method_list_t * (64-bit pointer) */
  2605. uint64_t classMethods; /* method_list_t * (64-bit pointer) */
  2606. uint64_t optionalInstanceMethods; /* method_list_t * (64-bit pointer) */
  2607. uint64_t optionalClassMethods; /* method_list_t * (64-bit pointer) */
  2608. uint64_t instanceProperties; /* struct objc_property_list *
  2609. (64-bit pointer) */
  2610. };
  2611. struct protocol32_t {
  2612. uint32_t isa; /* id * (32-bit pointer) */
  2613. uint32_t name; /* const char * (32-bit pointer) */
  2614. uint32_t protocols; /* struct protocol_list_t *
  2615. (32-bit pointer) */
  2616. uint32_t instanceMethods; /* method_list_t * (32-bit pointer) */
  2617. uint32_t classMethods; /* method_list_t * (32-bit pointer) */
  2618. uint32_t optionalInstanceMethods; /* method_list_t * (32-bit pointer) */
  2619. uint32_t optionalClassMethods; /* method_list_t * (32-bit pointer) */
  2620. uint32_t instanceProperties; /* struct objc_property_list *
  2621. (32-bit pointer) */
  2622. };
  2623. struct ivar_list64_t {
  2624. uint32_t entsize;
  2625. uint32_t count;
  2626. /* struct ivar64_t first; These structures follow inline */
  2627. };
  2628. struct ivar_list32_t {
  2629. uint32_t entsize;
  2630. uint32_t count;
  2631. /* struct ivar32_t first; These structures follow inline */
  2632. };
  2633. struct ivar64_t {
  2634. uint64_t offset; /* uintptr_t * (64-bit pointer) */
  2635. uint64_t name; /* const char * (64-bit pointer) */
  2636. uint64_t type; /* const char * (64-bit pointer) */
  2637. uint32_t alignment;
  2638. uint32_t size;
  2639. };
  2640. struct ivar32_t {
  2641. uint32_t offset; /* uintptr_t * (32-bit pointer) */
  2642. uint32_t name; /* const char * (32-bit pointer) */
  2643. uint32_t type; /* const char * (32-bit pointer) */
  2644. uint32_t alignment;
  2645. uint32_t size;
  2646. };
  2647. struct objc_property_list64 {
  2648. uint32_t entsize;
  2649. uint32_t count;
  2650. /* struct objc_property64 first; These structures follow inline */
  2651. };
  2652. struct objc_property_list32 {
  2653. uint32_t entsize;
  2654. uint32_t count;
  2655. /* struct objc_property32 first; These structures follow inline */
  2656. };
  2657. struct objc_property64 {
  2658. uint64_t name; /* const char * (64-bit pointer) */
  2659. uint64_t attributes; /* const char * (64-bit pointer) */
  2660. };
  2661. struct objc_property32 {
  2662. uint32_t name; /* const char * (32-bit pointer) */
  2663. uint32_t attributes; /* const char * (32-bit pointer) */
  2664. };
  2665. struct category64_t {
  2666. uint64_t name; /* const char * (64-bit pointer) */
  2667. uint64_t cls; /* struct class_t * (64-bit pointer) */
  2668. uint64_t instanceMethods; /* struct method_list_t * (64-bit pointer) */
  2669. uint64_t classMethods; /* struct method_list_t * (64-bit pointer) */
  2670. uint64_t protocols; /* struct protocol_list_t * (64-bit pointer) */
  2671. uint64_t instanceProperties; /* struct objc_property_list *
  2672. (64-bit pointer) */
  2673. };
  2674. struct category32_t {
  2675. uint32_t name; /* const char * (32-bit pointer) */
  2676. uint32_t cls; /* struct class_t * (32-bit pointer) */
  2677. uint32_t instanceMethods; /* struct method_list_t * (32-bit pointer) */
  2678. uint32_t classMethods; /* struct method_list_t * (32-bit pointer) */
  2679. uint32_t protocols; /* struct protocol_list_t * (32-bit pointer) */
  2680. uint32_t instanceProperties; /* struct objc_property_list *
  2681. (32-bit pointer) */
  2682. };
  2683. struct objc_image_info64 {
  2684. uint32_t version;
  2685. uint32_t flags;
  2686. };
  2687. struct objc_image_info32 {
  2688. uint32_t version;
  2689. uint32_t flags;
  2690. };
  2691. struct imageInfo_t {
  2692. uint32_t version;
  2693. uint32_t flags;
  2694. };
  2695. /* masks for objc_image_info.flags */
  2696. #define OBJC_IMAGE_IS_REPLACEMENT (1 << 0)
  2697. #define OBJC_IMAGE_SUPPORTS_GC (1 << 1)
  2698. struct message_ref64 {
  2699. uint64_t imp; /* IMP (64-bit pointer) */
  2700. uint64_t sel; /* SEL (64-bit pointer) */
  2701. };
  2702. struct message_ref32 {
  2703. uint32_t imp; /* IMP (32-bit pointer) */
  2704. uint32_t sel; /* SEL (32-bit pointer) */
  2705. };
  2706. // Objective-C 1 (32-bit only) meta data structs.
  2707. struct objc_module_t {
  2708. uint32_t version;
  2709. uint32_t size;
  2710. uint32_t name; /* char * (32-bit pointer) */
  2711. uint32_t symtab; /* struct objc_symtab * (32-bit pointer) */
  2712. };
  2713. struct objc_symtab_t {
  2714. uint32_t sel_ref_cnt;
  2715. uint32_t refs; /* SEL * (32-bit pointer) */
  2716. uint16_t cls_def_cnt;
  2717. uint16_t cat_def_cnt;
  2718. // uint32_t defs[1]; /* void * (32-bit pointer) variable size */
  2719. };
  2720. struct objc_class_t {
  2721. uint32_t isa; /* struct objc_class * (32-bit pointer) */
  2722. uint32_t super_class; /* struct objc_class * (32-bit pointer) */
  2723. uint32_t name; /* const char * (32-bit pointer) */
  2724. int32_t version;
  2725. int32_t info;
  2726. int32_t instance_size;
  2727. uint32_t ivars; /* struct objc_ivar_list * (32-bit pointer) */
  2728. uint32_t methodLists; /* struct objc_method_list ** (32-bit pointer) */
  2729. uint32_t cache; /* struct objc_cache * (32-bit pointer) */
  2730. uint32_t protocols; /* struct objc_protocol_list * (32-bit pointer) */
  2731. };
  2732. #define CLS_GETINFO(cls, infomask) ((cls)->info & (infomask))
  2733. // class is not a metaclass
  2734. #define CLS_CLASS 0x1
  2735. // class is a metaclass
  2736. #define CLS_META 0x2
  2737. struct objc_category_t {
  2738. uint32_t category_name; /* char * (32-bit pointer) */
  2739. uint32_t class_name; /* char * (32-bit pointer) */
  2740. uint32_t instance_methods; /* struct objc_method_list * (32-bit pointer) */
  2741. uint32_t class_methods; /* struct objc_method_list * (32-bit pointer) */
  2742. uint32_t protocols; /* struct objc_protocol_list * (32-bit ptr) */
  2743. };
  2744. struct objc_ivar_t {
  2745. uint32_t ivar_name; /* char * (32-bit pointer) */
  2746. uint32_t ivar_type; /* char * (32-bit pointer) */
  2747. int32_t ivar_offset;
  2748. };
  2749. struct objc_ivar_list_t {
  2750. int32_t ivar_count;
  2751. // struct objc_ivar_t ivar_list[1]; /* variable length structure */
  2752. };
  2753. struct objc_method_list_t {
  2754. uint32_t obsolete; /* struct objc_method_list * (32-bit pointer) */
  2755. int32_t method_count;
  2756. // struct objc_method_t method_list[1]; /* variable length structure */
  2757. };
  2758. struct objc_method_t {
  2759. uint32_t method_name; /* SEL, aka struct objc_selector * (32-bit pointer) */
  2760. uint32_t method_types; /* char * (32-bit pointer) */
  2761. uint32_t method_imp; /* IMP, aka function pointer, (*IMP)(id, SEL, ...)
  2762. (32-bit pointer) */
  2763. };
  2764. struct objc_protocol_list_t {
  2765. uint32_t next; /* struct objc_protocol_list * (32-bit pointer) */
  2766. int32_t count;
  2767. // uint32_t list[1]; /* Protocol *, aka struct objc_protocol_t *
  2768. // (32-bit pointer) */
  2769. };
  2770. struct objc_protocol_t {
  2771. uint32_t isa; /* struct objc_class * (32-bit pointer) */
  2772. uint32_t protocol_name; /* char * (32-bit pointer) */
  2773. uint32_t protocol_list; /* struct objc_protocol_list * (32-bit pointer) */
  2774. uint32_t instance_methods; /* struct objc_method_description_list *
  2775. (32-bit pointer) */
  2776. uint32_t class_methods; /* struct objc_method_description_list *
  2777. (32-bit pointer) */
  2778. };
  2779. struct objc_method_description_list_t {
  2780. int32_t count;
  2781. // struct objc_method_description_t list[1];
  2782. };
  2783. struct objc_method_description_t {
  2784. uint32_t name; /* SEL, aka struct objc_selector * (32-bit pointer) */
  2785. uint32_t types; /* char * (32-bit pointer) */
  2786. };
  2787. inline void swapStruct(struct cfstring64_t &cfs) {
  2788. sys::swapByteOrder(cfs.isa);
  2789. sys::swapByteOrder(cfs.flags);
  2790. sys::swapByteOrder(cfs.characters);
  2791. sys::swapByteOrder(cfs.length);
  2792. }
  2793. inline void swapStruct(struct class64_t &c) {
  2794. sys::swapByteOrder(c.isa);
  2795. sys::swapByteOrder(c.superclass);
  2796. sys::swapByteOrder(c.cache);
  2797. sys::swapByteOrder(c.vtable);
  2798. sys::swapByteOrder(c.data);
  2799. }
  2800. inline void swapStruct(struct class32_t &c) {
  2801. sys::swapByteOrder(c.isa);
  2802. sys::swapByteOrder(c.superclass);
  2803. sys::swapByteOrder(c.cache);
  2804. sys::swapByteOrder(c.vtable);
  2805. sys::swapByteOrder(c.data);
  2806. }
  2807. inline void swapStruct(struct class_ro64_t &cro) {
  2808. sys::swapByteOrder(cro.flags);
  2809. sys::swapByteOrder(cro.instanceStart);
  2810. sys::swapByteOrder(cro.instanceSize);
  2811. sys::swapByteOrder(cro.reserved);
  2812. sys::swapByteOrder(cro.ivarLayout);
  2813. sys::swapByteOrder(cro.name);
  2814. sys::swapByteOrder(cro.baseMethods);
  2815. sys::swapByteOrder(cro.baseProtocols);
  2816. sys::swapByteOrder(cro.ivars);
  2817. sys::swapByteOrder(cro.weakIvarLayout);
  2818. sys::swapByteOrder(cro.baseProperties);
  2819. }
  2820. inline void swapStruct(struct class_ro32_t &cro) {
  2821. sys::swapByteOrder(cro.flags);
  2822. sys::swapByteOrder(cro.instanceStart);
  2823. sys::swapByteOrder(cro.instanceSize);
  2824. sys::swapByteOrder(cro.ivarLayout);
  2825. sys::swapByteOrder(cro.name);
  2826. sys::swapByteOrder(cro.baseMethods);
  2827. sys::swapByteOrder(cro.baseProtocols);
  2828. sys::swapByteOrder(cro.ivars);
  2829. sys::swapByteOrder(cro.weakIvarLayout);
  2830. sys::swapByteOrder(cro.baseProperties);
  2831. }
  2832. inline void swapStruct(struct method_list64_t &ml) {
  2833. sys::swapByteOrder(ml.entsize);
  2834. sys::swapByteOrder(ml.count);
  2835. }
  2836. inline void swapStruct(struct method_list32_t &ml) {
  2837. sys::swapByteOrder(ml.entsize);
  2838. sys::swapByteOrder(ml.count);
  2839. }
  2840. inline void swapStruct(struct method64_t &m) {
  2841. sys::swapByteOrder(m.name);
  2842. sys::swapByteOrder(m.types);
  2843. sys::swapByteOrder(m.imp);
  2844. }
  2845. inline void swapStruct(struct method32_t &m) {
  2846. sys::swapByteOrder(m.name);
  2847. sys::swapByteOrder(m.types);
  2848. sys::swapByteOrder(m.imp);
  2849. }
  2850. inline void swapStruct(struct protocol_list64_t &pl) {
  2851. sys::swapByteOrder(pl.count);
  2852. }
  2853. inline void swapStruct(struct protocol_list32_t &pl) {
  2854. sys::swapByteOrder(pl.count);
  2855. }
  2856. inline void swapStruct(struct protocol64_t &p) {
  2857. sys::swapByteOrder(p.isa);
  2858. sys::swapByteOrder(p.name);
  2859. sys::swapByteOrder(p.protocols);
  2860. sys::swapByteOrder(p.instanceMethods);
  2861. sys::swapByteOrder(p.classMethods);
  2862. sys::swapByteOrder(p.optionalInstanceMethods);
  2863. sys::swapByteOrder(p.optionalClassMethods);
  2864. sys::swapByteOrder(p.instanceProperties);
  2865. }
  2866. inline void swapStruct(struct protocol32_t &p) {
  2867. sys::swapByteOrder(p.isa);
  2868. sys::swapByteOrder(p.name);
  2869. sys::swapByteOrder(p.protocols);
  2870. sys::swapByteOrder(p.instanceMethods);
  2871. sys::swapByteOrder(p.classMethods);
  2872. sys::swapByteOrder(p.optionalInstanceMethods);
  2873. sys::swapByteOrder(p.optionalClassMethods);
  2874. sys::swapByteOrder(p.instanceProperties);
  2875. }
  2876. inline void swapStruct(struct ivar_list64_t &il) {
  2877. sys::swapByteOrder(il.entsize);
  2878. sys::swapByteOrder(il.count);
  2879. }
  2880. inline void swapStruct(struct ivar_list32_t &il) {
  2881. sys::swapByteOrder(il.entsize);
  2882. sys::swapByteOrder(il.count);
  2883. }
  2884. inline void swapStruct(struct ivar64_t &i) {
  2885. sys::swapByteOrder(i.offset);
  2886. sys::swapByteOrder(i.name);
  2887. sys::swapByteOrder(i.type);
  2888. sys::swapByteOrder(i.alignment);
  2889. sys::swapByteOrder(i.size);
  2890. }
  2891. inline void swapStruct(struct ivar32_t &i) {
  2892. sys::swapByteOrder(i.offset);
  2893. sys::swapByteOrder(i.name);
  2894. sys::swapByteOrder(i.type);
  2895. sys::swapByteOrder(i.alignment);
  2896. sys::swapByteOrder(i.size);
  2897. }
  2898. inline void swapStruct(struct objc_property_list64 &pl) {
  2899. sys::swapByteOrder(pl.entsize);
  2900. sys::swapByteOrder(pl.count);
  2901. }
  2902. inline void swapStruct(struct objc_property_list32 &pl) {
  2903. sys::swapByteOrder(pl.entsize);
  2904. sys::swapByteOrder(pl.count);
  2905. }
  2906. inline void swapStruct(struct objc_property64 &op) {
  2907. sys::swapByteOrder(op.name);
  2908. sys::swapByteOrder(op.attributes);
  2909. }
  2910. inline void swapStruct(struct objc_property32 &op) {
  2911. sys::swapByteOrder(op.name);
  2912. sys::swapByteOrder(op.attributes);
  2913. }
  2914. inline void swapStruct(struct category64_t &c) {
  2915. sys::swapByteOrder(c.name);
  2916. sys::swapByteOrder(c.cls);
  2917. sys::swapByteOrder(c.instanceMethods);
  2918. sys::swapByteOrder(c.classMethods);
  2919. sys::swapByteOrder(c.protocols);
  2920. sys::swapByteOrder(c.instanceProperties);
  2921. }
  2922. inline void swapStruct(struct category32_t &c) {
  2923. sys::swapByteOrder(c.name);
  2924. sys::swapByteOrder(c.cls);
  2925. sys::swapByteOrder(c.instanceMethods);
  2926. sys::swapByteOrder(c.classMethods);
  2927. sys::swapByteOrder(c.protocols);
  2928. sys::swapByteOrder(c.instanceProperties);
  2929. }
  2930. inline void swapStruct(struct objc_image_info64 &o) {
  2931. sys::swapByteOrder(o.version);
  2932. sys::swapByteOrder(o.flags);
  2933. }
  2934. inline void swapStruct(struct objc_image_info32 &o) {
  2935. sys::swapByteOrder(o.version);
  2936. sys::swapByteOrder(o.flags);
  2937. }
  2938. inline void swapStruct(struct imageInfo_t &o) {
  2939. sys::swapByteOrder(o.version);
  2940. sys::swapByteOrder(o.flags);
  2941. }
  2942. inline void swapStruct(struct message_ref64 &mr) {
  2943. sys::swapByteOrder(mr.imp);
  2944. sys::swapByteOrder(mr.sel);
  2945. }
  2946. inline void swapStruct(struct message_ref32 &mr) {
  2947. sys::swapByteOrder(mr.imp);
  2948. sys::swapByteOrder(mr.sel);
  2949. }
  2950. inline void swapStruct(struct objc_module_t &module) {
  2951. sys::swapByteOrder(module.version);
  2952. sys::swapByteOrder(module.size);
  2953. sys::swapByteOrder(module.name);
  2954. sys::swapByteOrder(module.symtab);
  2955. }
  2956. inline void swapStruct(struct objc_symtab_t &symtab) {
  2957. sys::swapByteOrder(symtab.sel_ref_cnt);
  2958. sys::swapByteOrder(symtab.refs);
  2959. sys::swapByteOrder(symtab.cls_def_cnt);
  2960. sys::swapByteOrder(symtab.cat_def_cnt);
  2961. }
  2962. inline void swapStruct(struct objc_class_t &objc_class) {
  2963. sys::swapByteOrder(objc_class.isa);
  2964. sys::swapByteOrder(objc_class.super_class);
  2965. sys::swapByteOrder(objc_class.name);
  2966. sys::swapByteOrder(objc_class.version);
  2967. sys::swapByteOrder(objc_class.info);
  2968. sys::swapByteOrder(objc_class.instance_size);
  2969. sys::swapByteOrder(objc_class.ivars);
  2970. sys::swapByteOrder(objc_class.methodLists);
  2971. sys::swapByteOrder(objc_class.cache);
  2972. sys::swapByteOrder(objc_class.protocols);
  2973. }
  2974. inline void swapStruct(struct objc_category_t &objc_category) {
  2975. sys::swapByteOrder(objc_category.category_name);
  2976. sys::swapByteOrder(objc_category.class_name);
  2977. sys::swapByteOrder(objc_category.instance_methods);
  2978. sys::swapByteOrder(objc_category.class_methods);
  2979. sys::swapByteOrder(objc_category.protocols);
  2980. }
  2981. inline void swapStruct(struct objc_ivar_list_t &objc_ivar_list) {
  2982. sys::swapByteOrder(objc_ivar_list.ivar_count);
  2983. }
  2984. inline void swapStruct(struct objc_ivar_t &objc_ivar) {
  2985. sys::swapByteOrder(objc_ivar.ivar_name);
  2986. sys::swapByteOrder(objc_ivar.ivar_type);
  2987. sys::swapByteOrder(objc_ivar.ivar_offset);
  2988. }
  2989. inline void swapStruct(struct objc_method_list_t &method_list) {
  2990. sys::swapByteOrder(method_list.obsolete);
  2991. sys::swapByteOrder(method_list.method_count);
  2992. }
  2993. inline void swapStruct(struct objc_method_t &method) {
  2994. sys::swapByteOrder(method.method_name);
  2995. sys::swapByteOrder(method.method_types);
  2996. sys::swapByteOrder(method.method_imp);
  2997. }
  2998. inline void swapStruct(struct objc_protocol_list_t &protocol_list) {
  2999. sys::swapByteOrder(protocol_list.next);
  3000. sys::swapByteOrder(protocol_list.count);
  3001. }
  3002. inline void swapStruct(struct objc_protocol_t &protocol) {
  3003. sys::swapByteOrder(protocol.isa);
  3004. sys::swapByteOrder(protocol.protocol_name);
  3005. sys::swapByteOrder(protocol.protocol_list);
  3006. sys::swapByteOrder(protocol.instance_methods);
  3007. sys::swapByteOrder(protocol.class_methods);
  3008. }
  3009. inline void swapStruct(struct objc_method_description_list_t &mdl) {
  3010. sys::swapByteOrder(mdl.count);
  3011. }
  3012. inline void swapStruct(struct objc_method_description_t &md) {
  3013. sys::swapByteOrder(md.name);
  3014. sys::swapByteOrder(md.types);
  3015. }
  3016. static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
  3017. struct DisassembleInfo *info);
  3018. // get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
  3019. // to an Objective-C class and returns the class name. It is also passed the
  3020. // address of the pointer, so when the pointer is zero as it can be in an .o
  3021. // file, that is used to look for an external relocation entry with a symbol
  3022. // name.
  3023. static const char *get_objc2_64bit_class_name(uint64_t pointer_value,
  3024. uint64_t ReferenceValue,
  3025. struct DisassembleInfo *info) {
  3026. const char *r;
  3027. uint32_t offset, left;
  3028. SectionRef S;
  3029. // The pointer_value can be 0 in an object file and have a relocation
  3030. // entry for the class symbol at the ReferenceValue (the address of the
  3031. // pointer).
  3032. if (pointer_value == 0) {
  3033. r = get_pointer_64(ReferenceValue, offset, left, S, info);
  3034. if (r == nullptr || left < sizeof(uint64_t))
  3035. return nullptr;
  3036. uint64_t n_value;
  3037. const char *symbol_name = get_symbol_64(offset, S, info, n_value);
  3038. if (symbol_name == nullptr)
  3039. return nullptr;
  3040. const char *class_name = strrchr(symbol_name, '$');
  3041. if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
  3042. return class_name + 2;
  3043. else
  3044. return nullptr;
  3045. }
  3046. // The case were the pointer_value is non-zero and points to a class defined
  3047. // in this Mach-O file.
  3048. r = get_pointer_64(pointer_value, offset, left, S, info);
  3049. if (r == nullptr || left < sizeof(struct class64_t))
  3050. return nullptr;
  3051. struct class64_t c;
  3052. memcpy(&c, r, sizeof(struct class64_t));
  3053. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3054. swapStruct(c);
  3055. if (c.data == 0)
  3056. return nullptr;
  3057. r = get_pointer_64(c.data, offset, left, S, info);
  3058. if (r == nullptr || left < sizeof(struct class_ro64_t))
  3059. return nullptr;
  3060. struct class_ro64_t cro;
  3061. memcpy(&cro, r, sizeof(struct class_ro64_t));
  3062. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3063. swapStruct(cro);
  3064. if (cro.name == 0)
  3065. return nullptr;
  3066. const char *name = get_pointer_64(cro.name, offset, left, S, info);
  3067. return name;
  3068. }
  3069. // get_objc2_64bit_cfstring_name is used for disassembly and is passed a
  3070. // pointer to a cfstring and returns its name or nullptr.
  3071. static const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
  3072. struct DisassembleInfo *info) {
  3073. const char *r, *name;
  3074. uint32_t offset, left;
  3075. SectionRef S;
  3076. struct cfstring64_t cfs;
  3077. uint64_t cfs_characters;
  3078. r = get_pointer_64(ReferenceValue, offset, left, S, info);
  3079. if (r == nullptr || left < sizeof(struct cfstring64_t))
  3080. return nullptr;
  3081. memcpy(&cfs, r, sizeof(struct cfstring64_t));
  3082. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3083. swapStruct(cfs);
  3084. if (cfs.characters == 0) {
  3085. uint64_t n_value;
  3086. const char *symbol_name = get_symbol_64(
  3087. offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
  3088. if (symbol_name == nullptr)
  3089. return nullptr;
  3090. cfs_characters = n_value;
  3091. } else
  3092. cfs_characters = cfs.characters;
  3093. name = get_pointer_64(cfs_characters, offset, left, S, info);
  3094. return name;
  3095. }
  3096. // get_objc2_64bit_selref() is used for disassembly and is passed a the address
  3097. // of a pointer to an Objective-C selector reference when the pointer value is
  3098. // zero as in a .o file and is likely to have a external relocation entry with
  3099. // who's symbol's n_value is the real pointer to the selector name. If that is
  3100. // the case the real pointer to the selector name is returned else 0 is
  3101. // returned
  3102. static uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
  3103. struct DisassembleInfo *info) {
  3104. uint32_t offset, left;
  3105. SectionRef S;
  3106. const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
  3107. if (r == nullptr || left < sizeof(uint64_t))
  3108. return 0;
  3109. uint64_t n_value;
  3110. const char *symbol_name = get_symbol_64(offset, S, info, n_value);
  3111. if (symbol_name == nullptr)
  3112. return 0;
  3113. return n_value;
  3114. }
  3115. static const SectionRef get_section(MachOObjectFile *O, const char *segname,
  3116. const char *sectname) {
  3117. for (const SectionRef &Section : O->sections()) {
  3118. StringRef SectName;
  3119. Section.getName(SectName);
  3120. DataRefImpl Ref = Section.getRawDataRefImpl();
  3121. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3122. if (SegName == segname && SectName == sectname)
  3123. return Section;
  3124. }
  3125. return SectionRef();
  3126. }
  3127. static void
  3128. walk_pointer_list_64(const char *listname, const SectionRef S,
  3129. MachOObjectFile *O, struct DisassembleInfo *info,
  3130. void (*func)(uint64_t, struct DisassembleInfo *info)) {
  3131. if (S == SectionRef())
  3132. return;
  3133. StringRef SectName;
  3134. S.getName(SectName);
  3135. DataRefImpl Ref = S.getRawDataRefImpl();
  3136. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3137. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  3138. StringRef BytesStr;
  3139. S.getContents(BytesStr);
  3140. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  3141. for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint64_t)) {
  3142. uint32_t left = S.getSize() - i;
  3143. uint32_t size = left < sizeof(uint64_t) ? left : sizeof(uint64_t);
  3144. uint64_t p = 0;
  3145. memcpy(&p, Contents + i, size);
  3146. if (i + sizeof(uint64_t) > S.getSize())
  3147. outs() << listname << " list pointer extends past end of (" << SegName
  3148. << "," << SectName << ") section\n";
  3149. outs() << format("%016" PRIx64, S.getAddress() + i) << " ";
  3150. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  3151. sys::swapByteOrder(p);
  3152. uint64_t n_value = 0;
  3153. const char *name = get_symbol_64(i, S, info, n_value, p);
  3154. if (name == nullptr)
  3155. name = get_dyld_bind_info_symbolname(S.getAddress() + i, info);
  3156. if (n_value != 0) {
  3157. outs() << format("0x%" PRIx64, n_value);
  3158. if (p != 0)
  3159. outs() << " + " << format("0x%" PRIx64, p);
  3160. } else
  3161. outs() << format("0x%" PRIx64, p);
  3162. if (name != nullptr)
  3163. outs() << " " << name;
  3164. outs() << "\n";
  3165. p += n_value;
  3166. if (func)
  3167. func(p, info);
  3168. }
  3169. }
  3170. static void
  3171. walk_pointer_list_32(const char *listname, const SectionRef S,
  3172. MachOObjectFile *O, struct DisassembleInfo *info,
  3173. void (*func)(uint32_t, struct DisassembleInfo *info)) {
  3174. if (S == SectionRef())
  3175. return;
  3176. StringRef SectName;
  3177. S.getName(SectName);
  3178. DataRefImpl Ref = S.getRawDataRefImpl();
  3179. StringRef SegName = O->getSectionFinalSegmentName(Ref);
  3180. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  3181. StringRef BytesStr;
  3182. S.getContents(BytesStr);
  3183. const char *Contents = reinterpret_cast<const char *>(BytesStr.data());
  3184. for (uint32_t i = 0; i < S.getSize(); i += sizeof(uint32_t)) {
  3185. uint32_t left = S.getSize() - i;
  3186. uint32_t size = left < sizeof(uint32_t) ? left : sizeof(uint32_t);
  3187. uint32_t p = 0;
  3188. memcpy(&p, Contents + i, size);
  3189. if (i + sizeof(uint32_t) > S.getSize())
  3190. outs() << listname << " list pointer extends past end of (" << SegName
  3191. << "," << SectName << ") section\n";
  3192. uint32_t Address = S.getAddress() + i;
  3193. outs() << format("%08" PRIx32, Address) << " ";
  3194. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  3195. sys::swapByteOrder(p);
  3196. outs() << format("0x%" PRIx32, p);
  3197. const char *name = get_symbol_32(i, S, info, p);
  3198. if (name != nullptr)
  3199. outs() << " " << name;
  3200. outs() << "\n";
  3201. if (func)
  3202. func(p, info);
  3203. }
  3204. }
  3205. static void print_layout_map(const char *layout_map, uint32_t left) {
  3206. if (layout_map == nullptr)
  3207. return;
  3208. outs() << " layout map: ";
  3209. do {
  3210. outs() << format("0x%02" PRIx32, (*layout_map) & 0xff) << " ";
  3211. left--;
  3212. layout_map++;
  3213. } while (*layout_map != '\0' && left != 0);
  3214. outs() << "\n";
  3215. }
  3216. static void print_layout_map64(uint64_t p, struct DisassembleInfo *info) {
  3217. uint32_t offset, left;
  3218. SectionRef S;
  3219. const char *layout_map;
  3220. if (p == 0)
  3221. return;
  3222. layout_map = get_pointer_64(p, offset, left, S, info);
  3223. print_layout_map(layout_map, left);
  3224. }
  3225. static void print_layout_map32(uint32_t p, struct DisassembleInfo *info) {
  3226. uint32_t offset, left;
  3227. SectionRef S;
  3228. const char *layout_map;
  3229. if (p == 0)
  3230. return;
  3231. layout_map = get_pointer_32(p, offset, left, S, info);
  3232. print_layout_map(layout_map, left);
  3233. }
  3234. static void print_method_list64_t(uint64_t p, struct DisassembleInfo *info,
  3235. const char *indent) {
  3236. struct method_list64_t ml;
  3237. struct method64_t m;
  3238. const char *r;
  3239. uint32_t offset, xoffset, left, i;
  3240. SectionRef S, xS;
  3241. const char *name, *sym_name;
  3242. uint64_t n_value;
  3243. r = get_pointer_64(p, offset, left, S, info);
  3244. if (r == nullptr)
  3245. return;
  3246. memset(&ml, '\0', sizeof(struct method_list64_t));
  3247. if (left < sizeof(struct method_list64_t)) {
  3248. memcpy(&ml, r, left);
  3249. outs() << " (method_list_t entends past the end of the section)\n";
  3250. } else
  3251. memcpy(&ml, r, sizeof(struct method_list64_t));
  3252. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3253. swapStruct(ml);
  3254. outs() << indent << "\t\t entsize " << ml.entsize << "\n";
  3255. outs() << indent << "\t\t count " << ml.count << "\n";
  3256. p += sizeof(struct method_list64_t);
  3257. offset += sizeof(struct method_list64_t);
  3258. for (i = 0; i < ml.count; i++) {
  3259. r = get_pointer_64(p, offset, left, S, info);
  3260. if (r == nullptr)
  3261. return;
  3262. memset(&m, '\0', sizeof(struct method64_t));
  3263. if (left < sizeof(struct method64_t)) {
  3264. memcpy(&m, r, left);
  3265. outs() << indent << " (method_t extends past the end of the section)\n";
  3266. } else
  3267. memcpy(&m, r, sizeof(struct method64_t));
  3268. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3269. swapStruct(m);
  3270. outs() << indent << "\t\t name ";
  3271. sym_name = get_symbol_64(offset + offsetof(struct method64_t, name), S,
  3272. info, n_value, m.name);
  3273. if (n_value != 0) {
  3274. if (info->verbose && sym_name != nullptr)
  3275. outs() << sym_name;
  3276. else
  3277. outs() << format("0x%" PRIx64, n_value);
  3278. if (m.name != 0)
  3279. outs() << " + " << format("0x%" PRIx64, m.name);
  3280. } else
  3281. outs() << format("0x%" PRIx64, m.name);
  3282. name = get_pointer_64(m.name + n_value, xoffset, left, xS, info);
  3283. if (name != nullptr)
  3284. outs() << format(" %.*s", left, name);
  3285. outs() << "\n";
  3286. outs() << indent << "\t\t types ";
  3287. sym_name = get_symbol_64(offset + offsetof(struct method64_t, types), S,
  3288. info, n_value, m.types);
  3289. if (n_value != 0) {
  3290. if (info->verbose && sym_name != nullptr)
  3291. outs() << sym_name;
  3292. else
  3293. outs() << format("0x%" PRIx64, n_value);
  3294. if (m.types != 0)
  3295. outs() << " + " << format("0x%" PRIx64, m.types);
  3296. } else
  3297. outs() << format("0x%" PRIx64, m.types);
  3298. name = get_pointer_64(m.types + n_value, xoffset, left, xS, info);
  3299. if (name != nullptr)
  3300. outs() << format(" %.*s", left, name);
  3301. outs() << "\n";
  3302. outs() << indent << "\t\t imp ";
  3303. name = get_symbol_64(offset + offsetof(struct method64_t, imp), S, info,
  3304. n_value, m.imp);
  3305. if (info->verbose && name == nullptr) {
  3306. if (n_value != 0) {
  3307. outs() << format("0x%" PRIx64, n_value) << " ";
  3308. if (m.imp != 0)
  3309. outs() << "+ " << format("0x%" PRIx64, m.imp) << " ";
  3310. } else
  3311. outs() << format("0x%" PRIx64, m.imp) << " ";
  3312. }
  3313. if (name != nullptr)
  3314. outs() << name;
  3315. outs() << "\n";
  3316. p += sizeof(struct method64_t);
  3317. offset += sizeof(struct method64_t);
  3318. }
  3319. }
  3320. static void print_method_list32_t(uint64_t p, struct DisassembleInfo *info,
  3321. const char *indent) {
  3322. struct method_list32_t ml;
  3323. struct method32_t m;
  3324. const char *r, *name;
  3325. uint32_t offset, xoffset, left, i;
  3326. SectionRef S, xS;
  3327. r = get_pointer_32(p, offset, left, S, info);
  3328. if (r == nullptr)
  3329. return;
  3330. memset(&ml, '\0', sizeof(struct method_list32_t));
  3331. if (left < sizeof(struct method_list32_t)) {
  3332. memcpy(&ml, r, left);
  3333. outs() << " (method_list_t entends past the end of the section)\n";
  3334. } else
  3335. memcpy(&ml, r, sizeof(struct method_list32_t));
  3336. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3337. swapStruct(ml);
  3338. outs() << indent << "\t\t entsize " << ml.entsize << "\n";
  3339. outs() << indent << "\t\t count " << ml.count << "\n";
  3340. p += sizeof(struct method_list32_t);
  3341. offset += sizeof(struct method_list32_t);
  3342. for (i = 0; i < ml.count; i++) {
  3343. r = get_pointer_32(p, offset, left, S, info);
  3344. if (r == nullptr)
  3345. return;
  3346. memset(&m, '\0', sizeof(struct method32_t));
  3347. if (left < sizeof(struct method32_t)) {
  3348. memcpy(&ml, r, left);
  3349. outs() << indent << " (method_t entends past the end of the section)\n";
  3350. } else
  3351. memcpy(&m, r, sizeof(struct method32_t));
  3352. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3353. swapStruct(m);
  3354. outs() << indent << "\t\t name " << format("0x%" PRIx32, m.name);
  3355. name = get_pointer_32(m.name, xoffset, left, xS, info);
  3356. if (name != nullptr)
  3357. outs() << format(" %.*s", left, name);
  3358. outs() << "\n";
  3359. outs() << indent << "\t\t types " << format("0x%" PRIx32, m.types);
  3360. name = get_pointer_32(m.types, xoffset, left, xS, info);
  3361. if (name != nullptr)
  3362. outs() << format(" %.*s", left, name);
  3363. outs() << "\n";
  3364. outs() << indent << "\t\t imp " << format("0x%" PRIx32, m.imp);
  3365. name = get_symbol_32(offset + offsetof(struct method32_t, imp), S, info,
  3366. m.imp);
  3367. if (name != nullptr)
  3368. outs() << " " << name;
  3369. outs() << "\n";
  3370. p += sizeof(struct method32_t);
  3371. offset += sizeof(struct method32_t);
  3372. }
  3373. }
  3374. static bool print_method_list(uint32_t p, struct DisassembleInfo *info) {
  3375. uint32_t offset, left, xleft;
  3376. SectionRef S;
  3377. struct objc_method_list_t method_list;
  3378. struct objc_method_t method;
  3379. const char *r, *methods, *name, *SymbolName;
  3380. int32_t i;
  3381. r = get_pointer_32(p, offset, left, S, info, true);
  3382. if (r == nullptr)
  3383. return true;
  3384. outs() << "\n";
  3385. if (left > sizeof(struct objc_method_list_t)) {
  3386. memcpy(&method_list, r, sizeof(struct objc_method_list_t));
  3387. } else {
  3388. outs() << "\t\t objc_method_list extends past end of the section\n";
  3389. memset(&method_list, '\0', sizeof(struct objc_method_list_t));
  3390. memcpy(&method_list, r, left);
  3391. }
  3392. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3393. swapStruct(method_list);
  3394. outs() << "\t\t obsolete "
  3395. << format("0x%08" PRIx32, method_list.obsolete) << "\n";
  3396. outs() << "\t\t method_count " << method_list.method_count << "\n";
  3397. methods = r + sizeof(struct objc_method_list_t);
  3398. for (i = 0; i < method_list.method_count; i++) {
  3399. if ((i + 1) * sizeof(struct objc_method_t) > left) {
  3400. outs() << "\t\t remaining method's extend past the of the section\n";
  3401. break;
  3402. }
  3403. memcpy(&method, methods + i * sizeof(struct objc_method_t),
  3404. sizeof(struct objc_method_t));
  3405. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3406. swapStruct(method);
  3407. outs() << "\t\t method_name "
  3408. << format("0x%08" PRIx32, method.method_name);
  3409. if (info->verbose) {
  3410. name = get_pointer_32(method.method_name, offset, xleft, S, info, true);
  3411. if (name != nullptr)
  3412. outs() << format(" %.*s", xleft, name);
  3413. else
  3414. outs() << " (not in an __OBJC section)";
  3415. }
  3416. outs() << "\n";
  3417. outs() << "\t\t method_types "
  3418. << format("0x%08" PRIx32, method.method_types);
  3419. if (info->verbose) {
  3420. name = get_pointer_32(method.method_types, offset, xleft, S, info, true);
  3421. if (name != nullptr)
  3422. outs() << format(" %.*s", xleft, name);
  3423. else
  3424. outs() << " (not in an __OBJC section)";
  3425. }
  3426. outs() << "\n";
  3427. outs() << "\t\t method_imp "
  3428. << format("0x%08" PRIx32, method.method_imp) << " ";
  3429. if (info->verbose) {
  3430. SymbolName = GuessSymbolName(method.method_imp, info->AddrMap);
  3431. if (SymbolName != nullptr)
  3432. outs() << SymbolName;
  3433. }
  3434. outs() << "\n";
  3435. }
  3436. return false;
  3437. }
  3438. static void print_protocol_list64_t(uint64_t p, struct DisassembleInfo *info) {
  3439. struct protocol_list64_t pl;
  3440. uint64_t q, n_value;
  3441. struct protocol64_t pc;
  3442. const char *r;
  3443. uint32_t offset, xoffset, left, i;
  3444. SectionRef S, xS;
  3445. const char *name, *sym_name;
  3446. r = get_pointer_64(p, offset, left, S, info);
  3447. if (r == nullptr)
  3448. return;
  3449. memset(&pl, '\0', sizeof(struct protocol_list64_t));
  3450. if (left < sizeof(struct protocol_list64_t)) {
  3451. memcpy(&pl, r, left);
  3452. outs() << " (protocol_list_t entends past the end of the section)\n";
  3453. } else
  3454. memcpy(&pl, r, sizeof(struct protocol_list64_t));
  3455. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3456. swapStruct(pl);
  3457. outs() << " count " << pl.count << "\n";
  3458. p += sizeof(struct protocol_list64_t);
  3459. offset += sizeof(struct protocol_list64_t);
  3460. for (i = 0; i < pl.count; i++) {
  3461. r = get_pointer_64(p, offset, left, S, info);
  3462. if (r == nullptr)
  3463. return;
  3464. q = 0;
  3465. if (left < sizeof(uint64_t)) {
  3466. memcpy(&q, r, left);
  3467. outs() << " (protocol_t * entends past the end of the section)\n";
  3468. } else
  3469. memcpy(&q, r, sizeof(uint64_t));
  3470. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3471. sys::swapByteOrder(q);
  3472. outs() << "\t\t list[" << i << "] ";
  3473. sym_name = get_symbol_64(offset, S, info, n_value, q);
  3474. if (n_value != 0) {
  3475. if (info->verbose && sym_name != nullptr)
  3476. outs() << sym_name;
  3477. else
  3478. outs() << format("0x%" PRIx64, n_value);
  3479. if (q != 0)
  3480. outs() << " + " << format("0x%" PRIx64, q);
  3481. } else
  3482. outs() << format("0x%" PRIx64, q);
  3483. outs() << " (struct protocol_t *)\n";
  3484. r = get_pointer_64(q + n_value, offset, left, S, info);
  3485. if (r == nullptr)
  3486. return;
  3487. memset(&pc, '\0', sizeof(struct protocol64_t));
  3488. if (left < sizeof(struct protocol64_t)) {
  3489. memcpy(&pc, r, left);
  3490. outs() << " (protocol_t entends past the end of the section)\n";
  3491. } else
  3492. memcpy(&pc, r, sizeof(struct protocol64_t));
  3493. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3494. swapStruct(pc);
  3495. outs() << "\t\t\t isa " << format("0x%" PRIx64, pc.isa) << "\n";
  3496. outs() << "\t\t\t name ";
  3497. sym_name = get_symbol_64(offset + offsetof(struct protocol64_t, name), S,
  3498. info, n_value, pc.name);
  3499. if (n_value != 0) {
  3500. if (info->verbose && sym_name != nullptr)
  3501. outs() << sym_name;
  3502. else
  3503. outs() << format("0x%" PRIx64, n_value);
  3504. if (pc.name != 0)
  3505. outs() << " + " << format("0x%" PRIx64, pc.name);
  3506. } else
  3507. outs() << format("0x%" PRIx64, pc.name);
  3508. name = get_pointer_64(pc.name + n_value, xoffset, left, xS, info);
  3509. if (name != nullptr)
  3510. outs() << format(" %.*s", left, name);
  3511. outs() << "\n";
  3512. outs() << "\t\t\tprotocols " << format("0x%" PRIx64, pc.protocols) << "\n";
  3513. outs() << "\t\t instanceMethods ";
  3514. sym_name =
  3515. get_symbol_64(offset + offsetof(struct protocol64_t, instanceMethods),
  3516. S, info, n_value, pc.instanceMethods);
  3517. if (n_value != 0) {
  3518. if (info->verbose && sym_name != nullptr)
  3519. outs() << sym_name;
  3520. else
  3521. outs() << format("0x%" PRIx64, n_value);
  3522. if (pc.instanceMethods != 0)
  3523. outs() << " + " << format("0x%" PRIx64, pc.instanceMethods);
  3524. } else
  3525. outs() << format("0x%" PRIx64, pc.instanceMethods);
  3526. outs() << " (struct method_list_t *)\n";
  3527. if (pc.instanceMethods + n_value != 0)
  3528. print_method_list64_t(pc.instanceMethods + n_value, info, "\t");
  3529. outs() << "\t\t classMethods ";
  3530. sym_name =
  3531. get_symbol_64(offset + offsetof(struct protocol64_t, classMethods), S,
  3532. info, n_value, pc.classMethods);
  3533. if (n_value != 0) {
  3534. if (info->verbose && sym_name != nullptr)
  3535. outs() << sym_name;
  3536. else
  3537. outs() << format("0x%" PRIx64, n_value);
  3538. if (pc.classMethods != 0)
  3539. outs() << " + " << format("0x%" PRIx64, pc.classMethods);
  3540. } else
  3541. outs() << format("0x%" PRIx64, pc.classMethods);
  3542. outs() << " (struct method_list_t *)\n";
  3543. if (pc.classMethods + n_value != 0)
  3544. print_method_list64_t(pc.classMethods + n_value, info, "\t");
  3545. outs() << "\t optionalInstanceMethods "
  3546. << format("0x%" PRIx64, pc.optionalInstanceMethods) << "\n";
  3547. outs() << "\t optionalClassMethods "
  3548. << format("0x%" PRIx64, pc.optionalClassMethods) << "\n";
  3549. outs() << "\t instanceProperties "
  3550. << format("0x%" PRIx64, pc.instanceProperties) << "\n";
  3551. p += sizeof(uint64_t);
  3552. offset += sizeof(uint64_t);
  3553. }
  3554. }
  3555. static void print_protocol_list32_t(uint32_t p, struct DisassembleInfo *info) {
  3556. struct protocol_list32_t pl;
  3557. uint32_t q;
  3558. struct protocol32_t pc;
  3559. const char *r;
  3560. uint32_t offset, xoffset, left, i;
  3561. SectionRef S, xS;
  3562. const char *name;
  3563. r = get_pointer_32(p, offset, left, S, info);
  3564. if (r == nullptr)
  3565. return;
  3566. memset(&pl, '\0', sizeof(struct protocol_list32_t));
  3567. if (left < sizeof(struct protocol_list32_t)) {
  3568. memcpy(&pl, r, left);
  3569. outs() << " (protocol_list_t entends past the end of the section)\n";
  3570. } else
  3571. memcpy(&pl, r, sizeof(struct protocol_list32_t));
  3572. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3573. swapStruct(pl);
  3574. outs() << " count " << pl.count << "\n";
  3575. p += sizeof(struct protocol_list32_t);
  3576. offset += sizeof(struct protocol_list32_t);
  3577. for (i = 0; i < pl.count; i++) {
  3578. r = get_pointer_32(p, offset, left, S, info);
  3579. if (r == nullptr)
  3580. return;
  3581. q = 0;
  3582. if (left < sizeof(uint32_t)) {
  3583. memcpy(&q, r, left);
  3584. outs() << " (protocol_t * entends past the end of the section)\n";
  3585. } else
  3586. memcpy(&q, r, sizeof(uint32_t));
  3587. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3588. sys::swapByteOrder(q);
  3589. outs() << "\t\t list[" << i << "] " << format("0x%" PRIx32, q)
  3590. << " (struct protocol_t *)\n";
  3591. r = get_pointer_32(q, offset, left, S, info);
  3592. if (r == nullptr)
  3593. return;
  3594. memset(&pc, '\0', sizeof(struct protocol32_t));
  3595. if (left < sizeof(struct protocol32_t)) {
  3596. memcpy(&pc, r, left);
  3597. outs() << " (protocol_t entends past the end of the section)\n";
  3598. } else
  3599. memcpy(&pc, r, sizeof(struct protocol32_t));
  3600. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3601. swapStruct(pc);
  3602. outs() << "\t\t\t isa " << format("0x%" PRIx32, pc.isa) << "\n";
  3603. outs() << "\t\t\t name " << format("0x%" PRIx32, pc.name);
  3604. name = get_pointer_32(pc.name, xoffset, left, xS, info);
  3605. if (name != nullptr)
  3606. outs() << format(" %.*s", left, name);
  3607. outs() << "\n";
  3608. outs() << "\t\t\tprotocols " << format("0x%" PRIx32, pc.protocols) << "\n";
  3609. outs() << "\t\t instanceMethods "
  3610. << format("0x%" PRIx32, pc.instanceMethods)
  3611. << " (struct method_list_t *)\n";
  3612. if (pc.instanceMethods != 0)
  3613. print_method_list32_t(pc.instanceMethods, info, "\t");
  3614. outs() << "\t\t classMethods " << format("0x%" PRIx32, pc.classMethods)
  3615. << " (struct method_list_t *)\n";
  3616. if (pc.classMethods != 0)
  3617. print_method_list32_t(pc.classMethods, info, "\t");
  3618. outs() << "\t optionalInstanceMethods "
  3619. << format("0x%" PRIx32, pc.optionalInstanceMethods) << "\n";
  3620. outs() << "\t optionalClassMethods "
  3621. << format("0x%" PRIx32, pc.optionalClassMethods) << "\n";
  3622. outs() << "\t instanceProperties "
  3623. << format("0x%" PRIx32, pc.instanceProperties) << "\n";
  3624. p += sizeof(uint32_t);
  3625. offset += sizeof(uint32_t);
  3626. }
  3627. }
  3628. static void print_indent(uint32_t indent) {
  3629. for (uint32_t i = 0; i < indent;) {
  3630. if (indent - i >= 8) {
  3631. outs() << "\t";
  3632. i += 8;
  3633. } else {
  3634. for (uint32_t j = i; j < indent; j++)
  3635. outs() << " ";
  3636. return;
  3637. }
  3638. }
  3639. }
  3640. static bool print_method_description_list(uint32_t p, uint32_t indent,
  3641. struct DisassembleInfo *info) {
  3642. uint32_t offset, left, xleft;
  3643. SectionRef S;
  3644. struct objc_method_description_list_t mdl;
  3645. struct objc_method_description_t md;
  3646. const char *r, *list, *name;
  3647. int32_t i;
  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_method_description_list_t)) {
  3653. memcpy(&mdl, r, sizeof(struct objc_method_description_list_t));
  3654. } else {
  3655. print_indent(indent);
  3656. outs() << " objc_method_description_list extends past end of the section\n";
  3657. memset(&mdl, '\0', sizeof(struct objc_method_description_list_t));
  3658. memcpy(&mdl, r, left);
  3659. }
  3660. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3661. swapStruct(mdl);
  3662. print_indent(indent);
  3663. outs() << " count " << mdl.count << "\n";
  3664. list = r + sizeof(struct objc_method_description_list_t);
  3665. for (i = 0; i < mdl.count; i++) {
  3666. if ((i + 1) * sizeof(struct objc_method_description_t) > left) {
  3667. print_indent(indent);
  3668. outs() << " remaining list entries extend past the of the section\n";
  3669. break;
  3670. }
  3671. print_indent(indent);
  3672. outs() << " list[" << i << "]\n";
  3673. memcpy(&md, list + i * sizeof(struct objc_method_description_t),
  3674. sizeof(struct objc_method_description_t));
  3675. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3676. swapStruct(md);
  3677. print_indent(indent);
  3678. outs() << " name " << format("0x%08" PRIx32, md.name);
  3679. if (info->verbose) {
  3680. name = get_pointer_32(md.name, offset, xleft, S, info, true);
  3681. if (name != nullptr)
  3682. outs() << format(" %.*s", xleft, name);
  3683. else
  3684. outs() << " (not in an __OBJC section)";
  3685. }
  3686. outs() << "\n";
  3687. print_indent(indent);
  3688. outs() << " types " << format("0x%08" PRIx32, md.types);
  3689. if (info->verbose) {
  3690. name = get_pointer_32(md.types, offset, xleft, S, info, true);
  3691. if (name != nullptr)
  3692. outs() << format(" %.*s", xleft, name);
  3693. else
  3694. outs() << " (not in an __OBJC section)";
  3695. }
  3696. outs() << "\n";
  3697. }
  3698. return false;
  3699. }
  3700. static bool print_protocol_list(uint32_t p, uint32_t indent,
  3701. struct DisassembleInfo *info);
  3702. static bool print_protocol(uint32_t p, uint32_t indent,
  3703. struct DisassembleInfo *info) {
  3704. uint32_t offset, left;
  3705. SectionRef S;
  3706. struct objc_protocol_t protocol;
  3707. const char *r, *name;
  3708. r = get_pointer_32(p, offset, left, S, info, true);
  3709. if (r == nullptr)
  3710. return true;
  3711. outs() << "\n";
  3712. if (left >= sizeof(struct objc_protocol_t)) {
  3713. memcpy(&protocol, r, sizeof(struct objc_protocol_t));
  3714. } else {
  3715. print_indent(indent);
  3716. outs() << " Protocol extends past end of the section\n";
  3717. memset(&protocol, '\0', sizeof(struct objc_protocol_t));
  3718. memcpy(&protocol, r, left);
  3719. }
  3720. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3721. swapStruct(protocol);
  3722. print_indent(indent);
  3723. outs() << " isa " << format("0x%08" PRIx32, protocol.isa)
  3724. << "\n";
  3725. print_indent(indent);
  3726. outs() << " protocol_name "
  3727. << format("0x%08" PRIx32, protocol.protocol_name);
  3728. if (info->verbose) {
  3729. name = get_pointer_32(protocol.protocol_name, offset, left, S, info, true);
  3730. if (name != nullptr)
  3731. outs() << format(" %.*s", left, name);
  3732. else
  3733. outs() << " (not in an __OBJC section)";
  3734. }
  3735. outs() << "\n";
  3736. print_indent(indent);
  3737. outs() << " protocol_list "
  3738. << format("0x%08" PRIx32, protocol.protocol_list);
  3739. if (print_protocol_list(protocol.protocol_list, indent + 4, info))
  3740. outs() << " (not in an __OBJC section)\n";
  3741. print_indent(indent);
  3742. outs() << " instance_methods "
  3743. << format("0x%08" PRIx32, protocol.instance_methods);
  3744. if (print_method_description_list(protocol.instance_methods, indent, info))
  3745. outs() << " (not in an __OBJC section)\n";
  3746. print_indent(indent);
  3747. outs() << " class_methods "
  3748. << format("0x%08" PRIx32, protocol.class_methods);
  3749. if (print_method_description_list(protocol.class_methods, indent, info))
  3750. outs() << " (not in an __OBJC section)\n";
  3751. return false;
  3752. }
  3753. static bool print_protocol_list(uint32_t p, uint32_t indent,
  3754. struct DisassembleInfo *info) {
  3755. uint32_t offset, left, l;
  3756. SectionRef S;
  3757. struct objc_protocol_list_t protocol_list;
  3758. const char *r, *list;
  3759. int32_t i;
  3760. r = get_pointer_32(p, offset, left, S, info, true);
  3761. if (r == nullptr)
  3762. return true;
  3763. outs() << "\n";
  3764. if (left > sizeof(struct objc_protocol_list_t)) {
  3765. memcpy(&protocol_list, r, sizeof(struct objc_protocol_list_t));
  3766. } else {
  3767. outs() << "\t\t objc_protocol_list_t extends past end of the section\n";
  3768. memset(&protocol_list, '\0', sizeof(struct objc_protocol_list_t));
  3769. memcpy(&protocol_list, r, left);
  3770. }
  3771. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3772. swapStruct(protocol_list);
  3773. print_indent(indent);
  3774. outs() << " next " << format("0x%08" PRIx32, protocol_list.next)
  3775. << "\n";
  3776. print_indent(indent);
  3777. outs() << " count " << protocol_list.count << "\n";
  3778. list = r + sizeof(struct objc_protocol_list_t);
  3779. for (i = 0; i < protocol_list.count; i++) {
  3780. if ((i + 1) * sizeof(uint32_t) > left) {
  3781. outs() << "\t\t remaining list entries extend past the of the section\n";
  3782. break;
  3783. }
  3784. memcpy(&l, list + i * sizeof(uint32_t), sizeof(uint32_t));
  3785. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3786. sys::swapByteOrder(l);
  3787. print_indent(indent);
  3788. outs() << " list[" << i << "] " << format("0x%08" PRIx32, l);
  3789. if (print_protocol(l, indent, info))
  3790. outs() << "(not in an __OBJC section)\n";
  3791. }
  3792. return false;
  3793. }
  3794. static void print_ivar_list64_t(uint64_t p, struct DisassembleInfo *info) {
  3795. struct ivar_list64_t il;
  3796. struct ivar64_t i;
  3797. const char *r;
  3798. uint32_t offset, xoffset, left, j;
  3799. SectionRef S, xS;
  3800. const char *name, *sym_name, *ivar_offset_p;
  3801. uint64_t ivar_offset, n_value;
  3802. r = get_pointer_64(p, offset, left, S, info);
  3803. if (r == nullptr)
  3804. return;
  3805. memset(&il, '\0', sizeof(struct ivar_list64_t));
  3806. if (left < sizeof(struct ivar_list64_t)) {
  3807. memcpy(&il, r, left);
  3808. outs() << " (ivar_list_t entends past the end of the section)\n";
  3809. } else
  3810. memcpy(&il, r, sizeof(struct ivar_list64_t));
  3811. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3812. swapStruct(il);
  3813. outs() << " entsize " << il.entsize << "\n";
  3814. outs() << " count " << il.count << "\n";
  3815. p += sizeof(struct ivar_list64_t);
  3816. offset += sizeof(struct ivar_list64_t);
  3817. for (j = 0; j < il.count; j++) {
  3818. r = get_pointer_64(p, offset, left, S, info);
  3819. if (r == nullptr)
  3820. return;
  3821. memset(&i, '\0', sizeof(struct ivar64_t));
  3822. if (left < sizeof(struct ivar64_t)) {
  3823. memcpy(&i, r, left);
  3824. outs() << " (ivar_t entends past the end of the section)\n";
  3825. } else
  3826. memcpy(&i, r, sizeof(struct ivar64_t));
  3827. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3828. swapStruct(i);
  3829. outs() << "\t\t\t offset ";
  3830. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, offset), S,
  3831. info, n_value, i.offset);
  3832. if (n_value != 0) {
  3833. if (info->verbose && sym_name != nullptr)
  3834. outs() << sym_name;
  3835. else
  3836. outs() << format("0x%" PRIx64, n_value);
  3837. if (i.offset != 0)
  3838. outs() << " + " << format("0x%" PRIx64, i.offset);
  3839. } else
  3840. outs() << format("0x%" PRIx64, i.offset);
  3841. ivar_offset_p = get_pointer_64(i.offset + n_value, xoffset, left, xS, info);
  3842. if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
  3843. memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
  3844. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3845. sys::swapByteOrder(ivar_offset);
  3846. outs() << " " << ivar_offset << "\n";
  3847. } else
  3848. outs() << "\n";
  3849. outs() << "\t\t\t name ";
  3850. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, name), S, info,
  3851. n_value, i.name);
  3852. if (n_value != 0) {
  3853. if (info->verbose && sym_name != nullptr)
  3854. outs() << sym_name;
  3855. else
  3856. outs() << format("0x%" PRIx64, n_value);
  3857. if (i.name != 0)
  3858. outs() << " + " << format("0x%" PRIx64, i.name);
  3859. } else
  3860. outs() << format("0x%" PRIx64, i.name);
  3861. name = get_pointer_64(i.name + n_value, xoffset, left, xS, info);
  3862. if (name != nullptr)
  3863. outs() << format(" %.*s", left, name);
  3864. outs() << "\n";
  3865. outs() << "\t\t\t type ";
  3866. sym_name = get_symbol_64(offset + offsetof(struct ivar64_t, type), S, info,
  3867. n_value, i.name);
  3868. name = get_pointer_64(i.type + n_value, xoffset, left, xS, info);
  3869. if (n_value != 0) {
  3870. if (info->verbose && sym_name != nullptr)
  3871. outs() << sym_name;
  3872. else
  3873. outs() << format("0x%" PRIx64, n_value);
  3874. if (i.type != 0)
  3875. outs() << " + " << format("0x%" PRIx64, i.type);
  3876. } else
  3877. outs() << format("0x%" PRIx64, i.type);
  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 ivar64_t);
  3884. offset += sizeof(struct ivar64_t);
  3885. }
  3886. }
  3887. static void print_ivar_list32_t(uint32_t p, struct DisassembleInfo *info) {
  3888. struct ivar_list32_t il;
  3889. struct ivar32_t i;
  3890. const char *r;
  3891. uint32_t offset, xoffset, left, j;
  3892. SectionRef S, xS;
  3893. const char *name, *ivar_offset_p;
  3894. uint32_t ivar_offset;
  3895. r = get_pointer_32(p, offset, left, S, info);
  3896. if (r == nullptr)
  3897. return;
  3898. memset(&il, '\0', sizeof(struct ivar_list32_t));
  3899. if (left < sizeof(struct ivar_list32_t)) {
  3900. memcpy(&il, r, left);
  3901. outs() << " (ivar_list_t entends past the end of the section)\n";
  3902. } else
  3903. memcpy(&il, r, sizeof(struct ivar_list32_t));
  3904. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3905. swapStruct(il);
  3906. outs() << " entsize " << il.entsize << "\n";
  3907. outs() << " count " << il.count << "\n";
  3908. p += sizeof(struct ivar_list32_t);
  3909. offset += sizeof(struct ivar_list32_t);
  3910. for (j = 0; j < il.count; j++) {
  3911. r = get_pointer_32(p, offset, left, S, info);
  3912. if (r == nullptr)
  3913. return;
  3914. memset(&i, '\0', sizeof(struct ivar32_t));
  3915. if (left < sizeof(struct ivar32_t)) {
  3916. memcpy(&i, r, left);
  3917. outs() << " (ivar_t entends past the end of the section)\n";
  3918. } else
  3919. memcpy(&i, r, sizeof(struct ivar32_t));
  3920. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3921. swapStruct(i);
  3922. outs() << "\t\t\t offset " << format("0x%" PRIx32, i.offset);
  3923. ivar_offset_p = get_pointer_32(i.offset, xoffset, left, xS, info);
  3924. if (ivar_offset_p != nullptr && left >= sizeof(*ivar_offset_p)) {
  3925. memcpy(&ivar_offset, ivar_offset_p, sizeof(ivar_offset));
  3926. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3927. sys::swapByteOrder(ivar_offset);
  3928. outs() << " " << ivar_offset << "\n";
  3929. } else
  3930. outs() << "\n";
  3931. outs() << "\t\t\t name " << format("0x%" PRIx32, i.name);
  3932. name = get_pointer_32(i.name, xoffset, left, xS, info);
  3933. if (name != nullptr)
  3934. outs() << format(" %.*s", left, name);
  3935. outs() << "\n";
  3936. outs() << "\t\t\t type " << format("0x%" PRIx32, i.type);
  3937. name = get_pointer_32(i.type, xoffset, left, xS, info);
  3938. if (name != nullptr)
  3939. outs() << format(" %.*s", left, name);
  3940. outs() << "\n";
  3941. outs() << "\t\t\talignment " << i.alignment << "\n";
  3942. outs() << "\t\t\t size " << i.size << "\n";
  3943. p += sizeof(struct ivar32_t);
  3944. offset += sizeof(struct ivar32_t);
  3945. }
  3946. }
  3947. static void print_objc_property_list64(uint64_t p,
  3948. struct DisassembleInfo *info) {
  3949. struct objc_property_list64 opl;
  3950. struct objc_property64 op;
  3951. const char *r;
  3952. uint32_t offset, xoffset, left, j;
  3953. SectionRef S, xS;
  3954. const char *name, *sym_name;
  3955. uint64_t n_value;
  3956. r = get_pointer_64(p, offset, left, S, info);
  3957. if (r == nullptr)
  3958. return;
  3959. memset(&opl, '\0', sizeof(struct objc_property_list64));
  3960. if (left < sizeof(struct objc_property_list64)) {
  3961. memcpy(&opl, r, left);
  3962. outs() << " (objc_property_list entends past the end of the section)\n";
  3963. } else
  3964. memcpy(&opl, r, sizeof(struct objc_property_list64));
  3965. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3966. swapStruct(opl);
  3967. outs() << " entsize " << opl.entsize << "\n";
  3968. outs() << " count " << opl.count << "\n";
  3969. p += sizeof(struct objc_property_list64);
  3970. offset += sizeof(struct objc_property_list64);
  3971. for (j = 0; j < opl.count; j++) {
  3972. r = get_pointer_64(p, offset, left, S, info);
  3973. if (r == nullptr)
  3974. return;
  3975. memset(&op, '\0', sizeof(struct objc_property64));
  3976. if (left < sizeof(struct objc_property64)) {
  3977. memcpy(&op, r, left);
  3978. outs() << " (objc_property entends past the end of the section)\n";
  3979. } else
  3980. memcpy(&op, r, sizeof(struct objc_property64));
  3981. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  3982. swapStruct(op);
  3983. outs() << "\t\t\t name ";
  3984. sym_name = get_symbol_64(offset + offsetof(struct objc_property64, name), S,
  3985. info, n_value, op.name);
  3986. if (n_value != 0) {
  3987. if (info->verbose && sym_name != nullptr)
  3988. outs() << sym_name;
  3989. else
  3990. outs() << format("0x%" PRIx64, n_value);
  3991. if (op.name != 0)
  3992. outs() << " + " << format("0x%" PRIx64, op.name);
  3993. } else
  3994. outs() << format("0x%" PRIx64, op.name);
  3995. name = get_pointer_64(op.name + n_value, xoffset, left, xS, info);
  3996. if (name != nullptr)
  3997. outs() << format(" %.*s", left, name);
  3998. outs() << "\n";
  3999. outs() << "\t\t\tattributes ";
  4000. sym_name =
  4001. get_symbol_64(offset + offsetof(struct objc_property64, attributes), S,
  4002. info, n_value, op.attributes);
  4003. if (n_value != 0) {
  4004. if (info->verbose && sym_name != nullptr)
  4005. outs() << sym_name;
  4006. else
  4007. outs() << format("0x%" PRIx64, n_value);
  4008. if (op.attributes != 0)
  4009. outs() << " + " << format("0x%" PRIx64, op.attributes);
  4010. } else
  4011. outs() << format("0x%" PRIx64, op.attributes);
  4012. name = get_pointer_64(op.attributes + n_value, xoffset, left, xS, info);
  4013. if (name != nullptr)
  4014. outs() << format(" %.*s", left, name);
  4015. outs() << "\n";
  4016. p += sizeof(struct objc_property64);
  4017. offset += sizeof(struct objc_property64);
  4018. }
  4019. }
  4020. static void print_objc_property_list32(uint32_t p,
  4021. struct DisassembleInfo *info) {
  4022. struct objc_property_list32 opl;
  4023. struct objc_property32 op;
  4024. const char *r;
  4025. uint32_t offset, xoffset, left, j;
  4026. SectionRef S, xS;
  4027. const char *name;
  4028. r = get_pointer_32(p, offset, left, S, info);
  4029. if (r == nullptr)
  4030. return;
  4031. memset(&opl, '\0', sizeof(struct objc_property_list32));
  4032. if (left < sizeof(struct objc_property_list32)) {
  4033. memcpy(&opl, r, left);
  4034. outs() << " (objc_property_list entends past the end of the section)\n";
  4035. } else
  4036. memcpy(&opl, r, sizeof(struct objc_property_list32));
  4037. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4038. swapStruct(opl);
  4039. outs() << " entsize " << opl.entsize << "\n";
  4040. outs() << " count " << opl.count << "\n";
  4041. p += sizeof(struct objc_property_list32);
  4042. offset += sizeof(struct objc_property_list32);
  4043. for (j = 0; j < opl.count; j++) {
  4044. r = get_pointer_32(p, offset, left, S, info);
  4045. if (r == nullptr)
  4046. return;
  4047. memset(&op, '\0', sizeof(struct objc_property32));
  4048. if (left < sizeof(struct objc_property32)) {
  4049. memcpy(&op, r, left);
  4050. outs() << " (objc_property entends past the end of the section)\n";
  4051. } else
  4052. memcpy(&op, r, sizeof(struct objc_property32));
  4053. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4054. swapStruct(op);
  4055. outs() << "\t\t\t name " << format("0x%" PRIx32, op.name);
  4056. name = get_pointer_32(op.name, xoffset, left, xS, info);
  4057. if (name != nullptr)
  4058. outs() << format(" %.*s", left, name);
  4059. outs() << "\n";
  4060. outs() << "\t\t\tattributes " << format("0x%" PRIx32, op.attributes);
  4061. name = get_pointer_32(op.attributes, xoffset, left, xS, info);
  4062. if (name != nullptr)
  4063. outs() << format(" %.*s", left, name);
  4064. outs() << "\n";
  4065. p += sizeof(struct objc_property32);
  4066. offset += sizeof(struct objc_property32);
  4067. }
  4068. }
  4069. static bool print_class_ro64_t(uint64_t p, struct DisassembleInfo *info,
  4070. bool &is_meta_class) {
  4071. struct class_ro64_t cro;
  4072. const char *r;
  4073. uint32_t offset, xoffset, left;
  4074. SectionRef S, xS;
  4075. const char *name, *sym_name;
  4076. uint64_t n_value;
  4077. r = get_pointer_64(p, offset, left, S, info);
  4078. if (r == nullptr || left < sizeof(struct class_ro64_t))
  4079. return false;
  4080. memset(&cro, '\0', sizeof(struct class_ro64_t));
  4081. if (left < sizeof(struct class_ro64_t)) {
  4082. memcpy(&cro, r, left);
  4083. outs() << " (class_ro_t entends past the end of the section)\n";
  4084. } else
  4085. memcpy(&cro, r, sizeof(struct class_ro64_t));
  4086. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4087. swapStruct(cro);
  4088. outs() << " flags " << format("0x%" PRIx32, cro.flags);
  4089. if (cro.flags & RO_META)
  4090. outs() << " RO_META";
  4091. if (cro.flags & RO_ROOT)
  4092. outs() << " RO_ROOT";
  4093. if (cro.flags & RO_HAS_CXX_STRUCTORS)
  4094. outs() << " RO_HAS_CXX_STRUCTORS";
  4095. outs() << "\n";
  4096. outs() << " instanceStart " << cro.instanceStart << "\n";
  4097. outs() << " instanceSize " << cro.instanceSize << "\n";
  4098. outs() << " reserved " << format("0x%" PRIx32, cro.reserved)
  4099. << "\n";
  4100. outs() << " ivarLayout " << format("0x%" PRIx64, cro.ivarLayout)
  4101. << "\n";
  4102. print_layout_map64(cro.ivarLayout, info);
  4103. outs() << " name ";
  4104. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, name), S,
  4105. info, n_value, cro.name);
  4106. if (n_value != 0) {
  4107. if (info->verbose && sym_name != nullptr)
  4108. outs() << sym_name;
  4109. else
  4110. outs() << format("0x%" PRIx64, n_value);
  4111. if (cro.name != 0)
  4112. outs() << " + " << format("0x%" PRIx64, cro.name);
  4113. } else
  4114. outs() << format("0x%" PRIx64, cro.name);
  4115. name = get_pointer_64(cro.name + n_value, xoffset, left, xS, info);
  4116. if (name != nullptr)
  4117. outs() << format(" %.*s", left, name);
  4118. outs() << "\n";
  4119. outs() << " baseMethods ";
  4120. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, baseMethods),
  4121. S, info, n_value, cro.baseMethods);
  4122. if (n_value != 0) {
  4123. if (info->verbose && sym_name != nullptr)
  4124. outs() << sym_name;
  4125. else
  4126. outs() << format("0x%" PRIx64, n_value);
  4127. if (cro.baseMethods != 0)
  4128. outs() << " + " << format("0x%" PRIx64, cro.baseMethods);
  4129. } else
  4130. outs() << format("0x%" PRIx64, cro.baseMethods);
  4131. outs() << " (struct method_list_t *)\n";
  4132. if (cro.baseMethods + n_value != 0)
  4133. print_method_list64_t(cro.baseMethods + n_value, info, "");
  4134. outs() << " baseProtocols ";
  4135. sym_name =
  4136. get_symbol_64(offset + offsetof(struct class_ro64_t, baseProtocols), S,
  4137. info, n_value, cro.baseProtocols);
  4138. if (n_value != 0) {
  4139. if (info->verbose && sym_name != nullptr)
  4140. outs() << sym_name;
  4141. else
  4142. outs() << format("0x%" PRIx64, n_value);
  4143. if (cro.baseProtocols != 0)
  4144. outs() << " + " << format("0x%" PRIx64, cro.baseProtocols);
  4145. } else
  4146. outs() << format("0x%" PRIx64, cro.baseProtocols);
  4147. outs() << "\n";
  4148. if (cro.baseProtocols + n_value != 0)
  4149. print_protocol_list64_t(cro.baseProtocols + n_value, info);
  4150. outs() << " ivars ";
  4151. sym_name = get_symbol_64(offset + offsetof(struct class_ro64_t, ivars), S,
  4152. info, n_value, cro.ivars);
  4153. if (n_value != 0) {
  4154. if (info->verbose && sym_name != nullptr)
  4155. outs() << sym_name;
  4156. else
  4157. outs() << format("0x%" PRIx64, n_value);
  4158. if (cro.ivars != 0)
  4159. outs() << " + " << format("0x%" PRIx64, cro.ivars);
  4160. } else
  4161. outs() << format("0x%" PRIx64, cro.ivars);
  4162. outs() << "\n";
  4163. if (cro.ivars + n_value != 0)
  4164. print_ivar_list64_t(cro.ivars + n_value, info);
  4165. outs() << " weakIvarLayout ";
  4166. sym_name =
  4167. get_symbol_64(offset + offsetof(struct class_ro64_t, weakIvarLayout), S,
  4168. info, n_value, cro.weakIvarLayout);
  4169. if (n_value != 0) {
  4170. if (info->verbose && sym_name != nullptr)
  4171. outs() << sym_name;
  4172. else
  4173. outs() << format("0x%" PRIx64, n_value);
  4174. if (cro.weakIvarLayout != 0)
  4175. outs() << " + " << format("0x%" PRIx64, cro.weakIvarLayout);
  4176. } else
  4177. outs() << format("0x%" PRIx64, cro.weakIvarLayout);
  4178. outs() << "\n";
  4179. print_layout_map64(cro.weakIvarLayout + n_value, info);
  4180. outs() << " baseProperties ";
  4181. sym_name =
  4182. get_symbol_64(offset + offsetof(struct class_ro64_t, baseProperties), S,
  4183. info, n_value, cro.baseProperties);
  4184. if (n_value != 0) {
  4185. if (info->verbose && sym_name != nullptr)
  4186. outs() << sym_name;
  4187. else
  4188. outs() << format("0x%" PRIx64, n_value);
  4189. if (cro.baseProperties != 0)
  4190. outs() << " + " << format("0x%" PRIx64, cro.baseProperties);
  4191. } else
  4192. outs() << format("0x%" PRIx64, cro.baseProperties);
  4193. outs() << "\n";
  4194. if (cro.baseProperties + n_value != 0)
  4195. print_objc_property_list64(cro.baseProperties + n_value, info);
  4196. is_meta_class = (cro.flags & RO_META) != 0;
  4197. return true;
  4198. }
  4199. static bool print_class_ro32_t(uint32_t p, struct DisassembleInfo *info,
  4200. bool &is_meta_class) {
  4201. struct class_ro32_t cro;
  4202. const char *r;
  4203. uint32_t offset, xoffset, left;
  4204. SectionRef S, xS;
  4205. const char *name;
  4206. r = get_pointer_32(p, offset, left, S, info);
  4207. if (r == nullptr)
  4208. return false;
  4209. memset(&cro, '\0', sizeof(struct class_ro32_t));
  4210. if (left < sizeof(struct class_ro32_t)) {
  4211. memcpy(&cro, r, left);
  4212. outs() << " (class_ro_t entends past the end of the section)\n";
  4213. } else
  4214. memcpy(&cro, r, sizeof(struct class_ro32_t));
  4215. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4216. swapStruct(cro);
  4217. outs() << " flags " << format("0x%" PRIx32, cro.flags);
  4218. if (cro.flags & RO_META)
  4219. outs() << " RO_META";
  4220. if (cro.flags & RO_ROOT)
  4221. outs() << " RO_ROOT";
  4222. if (cro.flags & RO_HAS_CXX_STRUCTORS)
  4223. outs() << " RO_HAS_CXX_STRUCTORS";
  4224. outs() << "\n";
  4225. outs() << " instanceStart " << cro.instanceStart << "\n";
  4226. outs() << " instanceSize " << cro.instanceSize << "\n";
  4227. outs() << " ivarLayout " << format("0x%" PRIx32, cro.ivarLayout)
  4228. << "\n";
  4229. print_layout_map32(cro.ivarLayout, info);
  4230. outs() << " name " << format("0x%" PRIx32, cro.name);
  4231. name = get_pointer_32(cro.name, xoffset, left, xS, info);
  4232. if (name != nullptr)
  4233. outs() << format(" %.*s", left, name);
  4234. outs() << "\n";
  4235. outs() << " baseMethods "
  4236. << format("0x%" PRIx32, cro.baseMethods)
  4237. << " (struct method_list_t *)\n";
  4238. if (cro.baseMethods != 0)
  4239. print_method_list32_t(cro.baseMethods, info, "");
  4240. outs() << " baseProtocols "
  4241. << format("0x%" PRIx32, cro.baseProtocols) << "\n";
  4242. if (cro.baseProtocols != 0)
  4243. print_protocol_list32_t(cro.baseProtocols, info);
  4244. outs() << " ivars " << format("0x%" PRIx32, cro.ivars)
  4245. << "\n";
  4246. if (cro.ivars != 0)
  4247. print_ivar_list32_t(cro.ivars, info);
  4248. outs() << " weakIvarLayout "
  4249. << format("0x%" PRIx32, cro.weakIvarLayout) << "\n";
  4250. print_layout_map32(cro.weakIvarLayout, info);
  4251. outs() << " baseProperties "
  4252. << format("0x%" PRIx32, cro.baseProperties) << "\n";
  4253. if (cro.baseProperties != 0)
  4254. print_objc_property_list32(cro.baseProperties, info);
  4255. is_meta_class = (cro.flags & RO_META) != 0;
  4256. return true;
  4257. }
  4258. static void print_class64_t(uint64_t p, struct DisassembleInfo *info) {
  4259. struct class64_t c;
  4260. const char *r;
  4261. uint32_t offset, left;
  4262. SectionRef S;
  4263. const char *name;
  4264. uint64_t isa_n_value, n_value;
  4265. r = get_pointer_64(p, offset, left, S, info);
  4266. if (r == nullptr || left < sizeof(struct class64_t))
  4267. return;
  4268. memset(&c, '\0', sizeof(struct class64_t));
  4269. if (left < sizeof(struct class64_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 class64_t));
  4274. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4275. swapStruct(c);
  4276. outs() << " isa " << format("0x%" PRIx64, c.isa);
  4277. name = get_symbol_64(offset + offsetof(struct class64_t, isa), S, info,
  4278. isa_n_value, c.isa);
  4279. if (name != nullptr)
  4280. outs() << " " << name;
  4281. outs() << "\n";
  4282. outs() << " superclass " << format("0x%" PRIx64, c.superclass);
  4283. name = get_symbol_64(offset + offsetof(struct class64_t, superclass), S, info,
  4284. n_value, c.superclass);
  4285. if (name != nullptr)
  4286. outs() << " " << name;
  4287. outs() << "\n";
  4288. outs() << " cache " << format("0x%" PRIx64, c.cache);
  4289. name = get_symbol_64(offset + offsetof(struct class64_t, cache), S, info,
  4290. n_value, c.cache);
  4291. if (name != nullptr)
  4292. outs() << " " << name;
  4293. outs() << "\n";
  4294. outs() << " vtable " << format("0x%" PRIx64, c.vtable);
  4295. name = get_symbol_64(offset + offsetof(struct class64_t, vtable), S, info,
  4296. n_value, c.vtable);
  4297. if (name != nullptr)
  4298. outs() << " " << name;
  4299. outs() << "\n";
  4300. name = get_symbol_64(offset + offsetof(struct class64_t, data), S, info,
  4301. n_value, c.data);
  4302. outs() << " data ";
  4303. if (n_value != 0) {
  4304. if (info->verbose && name != nullptr)
  4305. outs() << name;
  4306. else
  4307. outs() << format("0x%" PRIx64, n_value);
  4308. if (c.data != 0)
  4309. outs() << " + " << format("0x%" PRIx64, c.data);
  4310. } else
  4311. outs() << format("0x%" PRIx64, c.data);
  4312. outs() << " (struct class_ro_t *)";
  4313. // This is a Swift class if some of the low bits of the pointer are set.
  4314. if ((c.data + n_value) & 0x7)
  4315. outs() << " Swift class";
  4316. outs() << "\n";
  4317. bool is_meta_class;
  4318. if (!print_class_ro64_t((c.data + n_value) & ~0x7, info, is_meta_class))
  4319. return;
  4320. if (!is_meta_class &&
  4321. c.isa + isa_n_value != p &&
  4322. c.isa + isa_n_value != 0 &&
  4323. info->depth < 100) {
  4324. info->depth++;
  4325. outs() << "Meta Class\n";
  4326. print_class64_t(c.isa + isa_n_value, info);
  4327. }
  4328. }
  4329. static void print_class32_t(uint32_t p, struct DisassembleInfo *info) {
  4330. struct class32_t c;
  4331. const char *r;
  4332. uint32_t offset, left;
  4333. SectionRef S;
  4334. const char *name;
  4335. r = get_pointer_32(p, offset, left, S, info);
  4336. if (r == nullptr)
  4337. return;
  4338. memset(&c, '\0', sizeof(struct class32_t));
  4339. if (left < sizeof(struct class32_t)) {
  4340. memcpy(&c, r, left);
  4341. outs() << " (class_t entends past the end of the section)\n";
  4342. } else
  4343. memcpy(&c, r, sizeof(struct class32_t));
  4344. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4345. swapStruct(c);
  4346. outs() << " isa " << format("0x%" PRIx32, c.isa);
  4347. name =
  4348. get_symbol_32(offset + offsetof(struct class32_t, isa), S, info, c.isa);
  4349. if (name != nullptr)
  4350. outs() << " " << name;
  4351. outs() << "\n";
  4352. outs() << " superclass " << format("0x%" PRIx32, c.superclass);
  4353. name = get_symbol_32(offset + offsetof(struct class32_t, superclass), S, info,
  4354. c.superclass);
  4355. if (name != nullptr)
  4356. outs() << " " << name;
  4357. outs() << "\n";
  4358. outs() << " cache " << format("0x%" PRIx32, c.cache);
  4359. name = get_symbol_32(offset + offsetof(struct class32_t, cache), S, info,
  4360. c.cache);
  4361. if (name != nullptr)
  4362. outs() << " " << name;
  4363. outs() << "\n";
  4364. outs() << " vtable " << format("0x%" PRIx32, c.vtable);
  4365. name = get_symbol_32(offset + offsetof(struct class32_t, vtable), S, info,
  4366. c.vtable);
  4367. if (name != nullptr)
  4368. outs() << " " << name;
  4369. outs() << "\n";
  4370. name =
  4371. get_symbol_32(offset + offsetof(struct class32_t, data), S, info, c.data);
  4372. outs() << " data " << format("0x%" PRIx32, c.data)
  4373. << " (struct class_ro_t *)";
  4374. // This is a Swift class if some of the low bits of the pointer are set.
  4375. if (c.data & 0x3)
  4376. outs() << " Swift class";
  4377. outs() << "\n";
  4378. bool is_meta_class;
  4379. if (!print_class_ro32_t(c.data & ~0x3, info, is_meta_class))
  4380. return;
  4381. if (!is_meta_class) {
  4382. outs() << "Meta Class\n";
  4383. print_class32_t(c.isa, info);
  4384. }
  4385. }
  4386. static void print_objc_class_t(struct objc_class_t *objc_class,
  4387. struct DisassembleInfo *info) {
  4388. uint32_t offset, left, xleft;
  4389. const char *name, *p, *ivar_list;
  4390. SectionRef S;
  4391. int32_t i;
  4392. struct objc_ivar_list_t objc_ivar_list;
  4393. struct objc_ivar_t ivar;
  4394. outs() << "\t\t isa " << format("0x%08" PRIx32, objc_class->isa);
  4395. if (info->verbose && CLS_GETINFO(objc_class, CLS_META)) {
  4396. name = get_pointer_32(objc_class->isa, offset, left, S, info, true);
  4397. if (name != nullptr)
  4398. outs() << format(" %.*s", left, name);
  4399. else
  4400. outs() << " (not in an __OBJC section)";
  4401. }
  4402. outs() << "\n";
  4403. outs() << "\t super_class "
  4404. << format("0x%08" PRIx32, objc_class->super_class);
  4405. if (info->verbose) {
  4406. name = get_pointer_32(objc_class->super_class, offset, left, S, info, true);
  4407. if (name != nullptr)
  4408. outs() << format(" %.*s", left, name);
  4409. else
  4410. outs() << " (not in an __OBJC section)";
  4411. }
  4412. outs() << "\n";
  4413. outs() << "\t\t name " << format("0x%08" PRIx32, objc_class->name);
  4414. if (info->verbose) {
  4415. name = get_pointer_32(objc_class->name, offset, left, S, info, true);
  4416. if (name != nullptr)
  4417. outs() << format(" %.*s", left, name);
  4418. else
  4419. outs() << " (not in an __OBJC section)";
  4420. }
  4421. outs() << "\n";
  4422. outs() << "\t\t version " << format("0x%08" PRIx32, objc_class->version)
  4423. << "\n";
  4424. outs() << "\t\t info " << format("0x%08" PRIx32, objc_class->info);
  4425. if (info->verbose) {
  4426. if (CLS_GETINFO(objc_class, CLS_CLASS))
  4427. outs() << " CLS_CLASS";
  4428. else if (CLS_GETINFO(objc_class, CLS_META))
  4429. outs() << " CLS_META";
  4430. }
  4431. outs() << "\n";
  4432. outs() << "\t instance_size "
  4433. << format("0x%08" PRIx32, objc_class->instance_size) << "\n";
  4434. p = get_pointer_32(objc_class->ivars, offset, left, S, info, true);
  4435. outs() << "\t\t ivars " << format("0x%08" PRIx32, objc_class->ivars);
  4436. if (p != nullptr) {
  4437. if (left > sizeof(struct objc_ivar_list_t)) {
  4438. outs() << "\n";
  4439. memcpy(&objc_ivar_list, p, sizeof(struct objc_ivar_list_t));
  4440. } else {
  4441. outs() << " (entends past the end of the section)\n";
  4442. memset(&objc_ivar_list, '\0', sizeof(struct objc_ivar_list_t));
  4443. memcpy(&objc_ivar_list, p, left);
  4444. }
  4445. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4446. swapStruct(objc_ivar_list);
  4447. outs() << "\t\t ivar_count " << objc_ivar_list.ivar_count << "\n";
  4448. ivar_list = p + sizeof(struct objc_ivar_list_t);
  4449. for (i = 0; i < objc_ivar_list.ivar_count; i++) {
  4450. if ((i + 1) * sizeof(struct objc_ivar_t) > left) {
  4451. outs() << "\t\t remaining ivar's extend past the of the section\n";
  4452. break;
  4453. }
  4454. memcpy(&ivar, ivar_list + i * sizeof(struct objc_ivar_t),
  4455. sizeof(struct objc_ivar_t));
  4456. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4457. swapStruct(ivar);
  4458. outs() << "\t\t\tivar_name " << format("0x%08" PRIx32, ivar.ivar_name);
  4459. if (info->verbose) {
  4460. name = get_pointer_32(ivar.ivar_name, offset, xleft, S, info, true);
  4461. if (name != nullptr)
  4462. outs() << format(" %.*s", xleft, name);
  4463. else
  4464. outs() << " (not in an __OBJC section)";
  4465. }
  4466. outs() << "\n";
  4467. outs() << "\t\t\tivar_type " << format("0x%08" PRIx32, ivar.ivar_type);
  4468. if (info->verbose) {
  4469. name = get_pointer_32(ivar.ivar_type, offset, xleft, S, info, true);
  4470. if (name != nullptr)
  4471. outs() << format(" %.*s", xleft, name);
  4472. else
  4473. outs() << " (not in an __OBJC section)";
  4474. }
  4475. outs() << "\n";
  4476. outs() << "\t\t ivar_offset "
  4477. << format("0x%08" PRIx32, ivar.ivar_offset) << "\n";
  4478. }
  4479. } else {
  4480. outs() << " (not in an __OBJC section)\n";
  4481. }
  4482. outs() << "\t\t methods " << format("0x%08" PRIx32, objc_class->methodLists);
  4483. if (print_method_list(objc_class->methodLists, info))
  4484. outs() << " (not in an __OBJC section)\n";
  4485. outs() << "\t\t cache " << format("0x%08" PRIx32, objc_class->cache)
  4486. << "\n";
  4487. outs() << "\t\tprotocols " << format("0x%08" PRIx32, objc_class->protocols);
  4488. if (print_protocol_list(objc_class->protocols, 16, info))
  4489. outs() << " (not in an __OBJC section)\n";
  4490. }
  4491. static void print_objc_objc_category_t(struct objc_category_t *objc_category,
  4492. struct DisassembleInfo *info) {
  4493. uint32_t offset, left;
  4494. const char *name;
  4495. SectionRef S;
  4496. outs() << "\t category name "
  4497. << format("0x%08" PRIx32, objc_category->category_name);
  4498. if (info->verbose) {
  4499. name = get_pointer_32(objc_category->category_name, offset, left, S, info,
  4500. true);
  4501. if (name != nullptr)
  4502. outs() << format(" %.*s", left, name);
  4503. else
  4504. outs() << " (not in an __OBJC section)";
  4505. }
  4506. outs() << "\n";
  4507. outs() << "\t\t class name "
  4508. << format("0x%08" PRIx32, objc_category->class_name);
  4509. if (info->verbose) {
  4510. name =
  4511. get_pointer_32(objc_category->class_name, offset, left, S, info, true);
  4512. if (name != nullptr)
  4513. outs() << format(" %.*s", left, name);
  4514. else
  4515. outs() << " (not in an __OBJC section)";
  4516. }
  4517. outs() << "\n";
  4518. outs() << "\t instance methods "
  4519. << format("0x%08" PRIx32, objc_category->instance_methods);
  4520. if (print_method_list(objc_category->instance_methods, info))
  4521. outs() << " (not in an __OBJC section)\n";
  4522. outs() << "\t class methods "
  4523. << format("0x%08" PRIx32, objc_category->class_methods);
  4524. if (print_method_list(objc_category->class_methods, info))
  4525. outs() << " (not in an __OBJC section)\n";
  4526. }
  4527. static void print_category64_t(uint64_t p, struct DisassembleInfo *info) {
  4528. struct category64_t c;
  4529. const char *r;
  4530. uint32_t offset, xoffset, left;
  4531. SectionRef S, xS;
  4532. const char *name, *sym_name;
  4533. uint64_t n_value;
  4534. r = get_pointer_64(p, offset, left, S, info);
  4535. if (r == nullptr)
  4536. return;
  4537. memset(&c, '\0', sizeof(struct category64_t));
  4538. if (left < sizeof(struct category64_t)) {
  4539. memcpy(&c, r, left);
  4540. outs() << " (category_t entends past the end of the section)\n";
  4541. } else
  4542. memcpy(&c, r, sizeof(struct category64_t));
  4543. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4544. swapStruct(c);
  4545. outs() << " name ";
  4546. sym_name = get_symbol_64(offset + offsetof(struct category64_t, name), S,
  4547. info, n_value, c.name);
  4548. if (n_value != 0) {
  4549. if (info->verbose && sym_name != nullptr)
  4550. outs() << sym_name;
  4551. else
  4552. outs() << format("0x%" PRIx64, n_value);
  4553. if (c.name != 0)
  4554. outs() << " + " << format("0x%" PRIx64, c.name);
  4555. } else
  4556. outs() << format("0x%" PRIx64, c.name);
  4557. name = get_pointer_64(c.name + n_value, xoffset, left, xS, info);
  4558. if (name != nullptr)
  4559. outs() << format(" %.*s", left, name);
  4560. outs() << "\n";
  4561. outs() << " cls ";
  4562. sym_name = get_symbol_64(offset + offsetof(struct category64_t, cls), S, info,
  4563. n_value, c.cls);
  4564. if (n_value != 0) {
  4565. if (info->verbose && sym_name != nullptr)
  4566. outs() << sym_name;
  4567. else
  4568. outs() << format("0x%" PRIx64, n_value);
  4569. if (c.cls != 0)
  4570. outs() << " + " << format("0x%" PRIx64, c.cls);
  4571. } else
  4572. outs() << format("0x%" PRIx64, c.cls);
  4573. outs() << "\n";
  4574. if (c.cls + n_value != 0)
  4575. print_class64_t(c.cls + n_value, info);
  4576. outs() << " instanceMethods ";
  4577. sym_name =
  4578. get_symbol_64(offset + offsetof(struct category64_t, instanceMethods), S,
  4579. info, n_value, c.instanceMethods);
  4580. if (n_value != 0) {
  4581. if (info->verbose && sym_name != nullptr)
  4582. outs() << sym_name;
  4583. else
  4584. outs() << format("0x%" PRIx64, n_value);
  4585. if (c.instanceMethods != 0)
  4586. outs() << " + " << format("0x%" PRIx64, c.instanceMethods);
  4587. } else
  4588. outs() << format("0x%" PRIx64, c.instanceMethods);
  4589. outs() << "\n";
  4590. if (c.instanceMethods + n_value != 0)
  4591. print_method_list64_t(c.instanceMethods + n_value, info, "");
  4592. outs() << " classMethods ";
  4593. sym_name = get_symbol_64(offset + offsetof(struct category64_t, classMethods),
  4594. S, info, n_value, c.classMethods);
  4595. if (n_value != 0) {
  4596. if (info->verbose && sym_name != nullptr)
  4597. outs() << sym_name;
  4598. else
  4599. outs() << format("0x%" PRIx64, n_value);
  4600. if (c.classMethods != 0)
  4601. outs() << " + " << format("0x%" PRIx64, c.classMethods);
  4602. } else
  4603. outs() << format("0x%" PRIx64, c.classMethods);
  4604. outs() << "\n";
  4605. if (c.classMethods + n_value != 0)
  4606. print_method_list64_t(c.classMethods + n_value, info, "");
  4607. outs() << " protocols ";
  4608. sym_name = get_symbol_64(offset + offsetof(struct category64_t, protocols), S,
  4609. info, n_value, c.protocols);
  4610. if (n_value != 0) {
  4611. if (info->verbose && sym_name != nullptr)
  4612. outs() << sym_name;
  4613. else
  4614. outs() << format("0x%" PRIx64, n_value);
  4615. if (c.protocols != 0)
  4616. outs() << " + " << format("0x%" PRIx64, c.protocols);
  4617. } else
  4618. outs() << format("0x%" PRIx64, c.protocols);
  4619. outs() << "\n";
  4620. if (c.protocols + n_value != 0)
  4621. print_protocol_list64_t(c.protocols + n_value, info);
  4622. outs() << "instanceProperties ";
  4623. sym_name =
  4624. get_symbol_64(offset + offsetof(struct category64_t, instanceProperties),
  4625. S, info, n_value, c.instanceProperties);
  4626. if (n_value != 0) {
  4627. if (info->verbose && sym_name != nullptr)
  4628. outs() << sym_name;
  4629. else
  4630. outs() << format("0x%" PRIx64, n_value);
  4631. if (c.instanceProperties != 0)
  4632. outs() << " + " << format("0x%" PRIx64, c.instanceProperties);
  4633. } else
  4634. outs() << format("0x%" PRIx64, c.instanceProperties);
  4635. outs() << "\n";
  4636. if (c.instanceProperties + n_value != 0)
  4637. print_objc_property_list64(c.instanceProperties + n_value, info);
  4638. }
  4639. static void print_category32_t(uint32_t p, struct DisassembleInfo *info) {
  4640. struct category32_t c;
  4641. const char *r;
  4642. uint32_t offset, left;
  4643. SectionRef S, xS;
  4644. const char *name;
  4645. r = get_pointer_32(p, offset, left, S, info);
  4646. if (r == nullptr)
  4647. return;
  4648. memset(&c, '\0', sizeof(struct category32_t));
  4649. if (left < sizeof(struct category32_t)) {
  4650. memcpy(&c, r, left);
  4651. outs() << " (category_t entends past the end of the section)\n";
  4652. } else
  4653. memcpy(&c, r, sizeof(struct category32_t));
  4654. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4655. swapStruct(c);
  4656. outs() << " name " << format("0x%" PRIx32, c.name);
  4657. name = get_symbol_32(offset + offsetof(struct category32_t, name), S, info,
  4658. c.name);
  4659. if (name)
  4660. outs() << " " << name;
  4661. outs() << "\n";
  4662. outs() << " cls " << format("0x%" PRIx32, c.cls) << "\n";
  4663. if (c.cls != 0)
  4664. print_class32_t(c.cls, info);
  4665. outs() << " instanceMethods " << format("0x%" PRIx32, c.instanceMethods)
  4666. << "\n";
  4667. if (c.instanceMethods != 0)
  4668. print_method_list32_t(c.instanceMethods, info, "");
  4669. outs() << " classMethods " << format("0x%" PRIx32, c.classMethods)
  4670. << "\n";
  4671. if (c.classMethods != 0)
  4672. print_method_list32_t(c.classMethods, info, "");
  4673. outs() << " protocols " << format("0x%" PRIx32, c.protocols) << "\n";
  4674. if (c.protocols != 0)
  4675. print_protocol_list32_t(c.protocols, info);
  4676. outs() << "instanceProperties " << format("0x%" PRIx32, c.instanceProperties)
  4677. << "\n";
  4678. if (c.instanceProperties != 0)
  4679. print_objc_property_list32(c.instanceProperties, info);
  4680. }
  4681. static void print_message_refs64(SectionRef S, struct DisassembleInfo *info) {
  4682. uint32_t i, left, offset, xoffset;
  4683. uint64_t p, n_value;
  4684. struct message_ref64 mr;
  4685. const char *name, *sym_name;
  4686. const char *r;
  4687. SectionRef xS;
  4688. if (S == SectionRef())
  4689. return;
  4690. StringRef SectName;
  4691. S.getName(SectName);
  4692. DataRefImpl Ref = S.getRawDataRefImpl();
  4693. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4694. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4695. offset = 0;
  4696. for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
  4697. p = S.getAddress() + i;
  4698. r = get_pointer_64(p, offset, left, S, info);
  4699. if (r == nullptr)
  4700. return;
  4701. memset(&mr, '\0', sizeof(struct message_ref64));
  4702. if (left < sizeof(struct message_ref64)) {
  4703. memcpy(&mr, r, left);
  4704. outs() << " (message_ref entends past the end of the section)\n";
  4705. } else
  4706. memcpy(&mr, r, sizeof(struct message_ref64));
  4707. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4708. swapStruct(mr);
  4709. outs() << " imp ";
  4710. name = get_symbol_64(offset + offsetof(struct message_ref64, imp), S, info,
  4711. n_value, mr.imp);
  4712. if (n_value != 0) {
  4713. outs() << format("0x%" PRIx64, n_value) << " ";
  4714. if (mr.imp != 0)
  4715. outs() << "+ " << format("0x%" PRIx64, mr.imp) << " ";
  4716. } else
  4717. outs() << format("0x%" PRIx64, mr.imp) << " ";
  4718. if (name != nullptr)
  4719. outs() << " " << name;
  4720. outs() << "\n";
  4721. outs() << " sel ";
  4722. sym_name = get_symbol_64(offset + offsetof(struct message_ref64, sel), S,
  4723. info, n_value, mr.sel);
  4724. if (n_value != 0) {
  4725. if (info->verbose && sym_name != nullptr)
  4726. outs() << sym_name;
  4727. else
  4728. outs() << format("0x%" PRIx64, n_value);
  4729. if (mr.sel != 0)
  4730. outs() << " + " << format("0x%" PRIx64, mr.sel);
  4731. } else
  4732. outs() << format("0x%" PRIx64, mr.sel);
  4733. name = get_pointer_64(mr.sel + n_value, xoffset, left, xS, info);
  4734. if (name != nullptr)
  4735. outs() << format(" %.*s", left, name);
  4736. outs() << "\n";
  4737. offset += sizeof(struct message_ref64);
  4738. }
  4739. }
  4740. static void print_message_refs32(SectionRef S, struct DisassembleInfo *info) {
  4741. uint32_t i, left, offset, xoffset, p;
  4742. struct message_ref32 mr;
  4743. const char *name, *r;
  4744. SectionRef xS;
  4745. if (S == SectionRef())
  4746. return;
  4747. StringRef SectName;
  4748. S.getName(SectName);
  4749. DataRefImpl Ref = S.getRawDataRefImpl();
  4750. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4751. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4752. offset = 0;
  4753. for (i = 0; i < S.getSize(); i += sizeof(struct message_ref64)) {
  4754. p = S.getAddress() + i;
  4755. r = get_pointer_32(p, offset, left, S, info);
  4756. if (r == nullptr)
  4757. return;
  4758. memset(&mr, '\0', sizeof(struct message_ref32));
  4759. if (left < sizeof(struct message_ref32)) {
  4760. memcpy(&mr, r, left);
  4761. outs() << " (message_ref entends past the end of the section)\n";
  4762. } else
  4763. memcpy(&mr, r, sizeof(struct message_ref32));
  4764. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4765. swapStruct(mr);
  4766. outs() << " imp " << format("0x%" PRIx32, mr.imp);
  4767. name = get_symbol_32(offset + offsetof(struct message_ref32, imp), S, info,
  4768. mr.imp);
  4769. if (name != nullptr)
  4770. outs() << " " << name;
  4771. outs() << "\n";
  4772. outs() << " sel " << format("0x%" PRIx32, mr.sel);
  4773. name = get_pointer_32(mr.sel, xoffset, left, xS, info);
  4774. if (name != nullptr)
  4775. outs() << " " << name;
  4776. outs() << "\n";
  4777. offset += sizeof(struct message_ref32);
  4778. }
  4779. }
  4780. static void print_image_info64(SectionRef S, struct DisassembleInfo *info) {
  4781. uint32_t left, offset, swift_version;
  4782. uint64_t p;
  4783. struct objc_image_info64 o;
  4784. const char *r;
  4785. if (S == SectionRef())
  4786. return;
  4787. StringRef SectName;
  4788. S.getName(SectName);
  4789. DataRefImpl Ref = S.getRawDataRefImpl();
  4790. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4791. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4792. p = S.getAddress();
  4793. r = get_pointer_64(p, offset, left, S, info);
  4794. if (r == nullptr)
  4795. return;
  4796. memset(&o, '\0', sizeof(struct objc_image_info64));
  4797. if (left < sizeof(struct objc_image_info64)) {
  4798. memcpy(&o, r, left);
  4799. outs() << " (objc_image_info entends past the end of the section)\n";
  4800. } else
  4801. memcpy(&o, r, sizeof(struct objc_image_info64));
  4802. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4803. swapStruct(o);
  4804. outs() << " version " << o.version << "\n";
  4805. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4806. if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
  4807. outs() << " OBJC_IMAGE_IS_REPLACEMENT";
  4808. if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
  4809. outs() << " OBJC_IMAGE_SUPPORTS_GC";
  4810. swift_version = (o.flags >> 8) & 0xff;
  4811. if (swift_version != 0) {
  4812. if (swift_version == 1)
  4813. outs() << " Swift 1.0";
  4814. else if (swift_version == 2)
  4815. outs() << " Swift 1.1";
  4816. else
  4817. outs() << " unknown future Swift version (" << swift_version << ")";
  4818. }
  4819. outs() << "\n";
  4820. }
  4821. static void print_image_info32(SectionRef S, struct DisassembleInfo *info) {
  4822. uint32_t left, offset, swift_version, p;
  4823. struct objc_image_info32 o;
  4824. const char *r;
  4825. if (S == SectionRef())
  4826. return;
  4827. StringRef SectName;
  4828. S.getName(SectName);
  4829. DataRefImpl Ref = S.getRawDataRefImpl();
  4830. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4831. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4832. p = S.getAddress();
  4833. r = get_pointer_32(p, offset, left, S, info);
  4834. if (r == nullptr)
  4835. return;
  4836. memset(&o, '\0', sizeof(struct objc_image_info32));
  4837. if (left < sizeof(struct objc_image_info32)) {
  4838. memcpy(&o, r, left);
  4839. outs() << " (objc_image_info entends past the end of the section)\n";
  4840. } else
  4841. memcpy(&o, r, sizeof(struct objc_image_info32));
  4842. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4843. swapStruct(o);
  4844. outs() << " version " << o.version << "\n";
  4845. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4846. if (o.flags & OBJC_IMAGE_IS_REPLACEMENT)
  4847. outs() << " OBJC_IMAGE_IS_REPLACEMENT";
  4848. if (o.flags & OBJC_IMAGE_SUPPORTS_GC)
  4849. outs() << " OBJC_IMAGE_SUPPORTS_GC";
  4850. swift_version = (o.flags >> 8) & 0xff;
  4851. if (swift_version != 0) {
  4852. if (swift_version == 1)
  4853. outs() << " Swift 1.0";
  4854. else if (swift_version == 2)
  4855. outs() << " Swift 1.1";
  4856. else
  4857. outs() << " unknown future Swift version (" << swift_version << ")";
  4858. }
  4859. outs() << "\n";
  4860. }
  4861. static void print_image_info(SectionRef S, struct DisassembleInfo *info) {
  4862. uint32_t left, offset, p;
  4863. struct imageInfo_t o;
  4864. const char *r;
  4865. StringRef SectName;
  4866. S.getName(SectName);
  4867. DataRefImpl Ref = S.getRawDataRefImpl();
  4868. StringRef SegName = info->O->getSectionFinalSegmentName(Ref);
  4869. outs() << "Contents of (" << SegName << "," << SectName << ") section\n";
  4870. p = S.getAddress();
  4871. r = get_pointer_32(p, offset, left, S, info);
  4872. if (r == nullptr)
  4873. return;
  4874. memset(&o, '\0', sizeof(struct imageInfo_t));
  4875. if (left < sizeof(struct imageInfo_t)) {
  4876. memcpy(&o, r, left);
  4877. outs() << " (imageInfo entends past the end of the section)\n";
  4878. } else
  4879. memcpy(&o, r, sizeof(struct imageInfo_t));
  4880. if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
  4881. swapStruct(o);
  4882. outs() << " version " << o.version << "\n";
  4883. outs() << " flags " << format("0x%" PRIx32, o.flags);
  4884. if (o.flags & 0x1)
  4885. outs() << " F&C";
  4886. if (o.flags & 0x2)
  4887. outs() << " GC";
  4888. if (o.flags & 0x4)
  4889. outs() << " GC-only";
  4890. else
  4891. outs() << " RR";
  4892. outs() << "\n";
  4893. }
  4894. static void printObjc2_64bit_MetaData(MachOObjectFile *O, bool verbose) {
  4895. SymbolAddressMap AddrMap;
  4896. if (verbose)
  4897. CreateSymbolAddressMap(O, &AddrMap);
  4898. std::vector<SectionRef> Sections;
  4899. for (const SectionRef &Section : O->sections()) {
  4900. StringRef SectName;
  4901. Section.getName(SectName);
  4902. Sections.push_back(Section);
  4903. }
  4904. struct DisassembleInfo info;
  4905. // Set up the block of info used by the Symbolizer call backs.
  4906. info.verbose = verbose;
  4907. info.O = O;
  4908. info.AddrMap = &AddrMap;
  4909. info.Sections = &Sections;
  4910. info.class_name = nullptr;
  4911. info.selector_name = nullptr;
  4912. info.method = nullptr;
  4913. info.demangled_name = nullptr;
  4914. info.bindtable = nullptr;
  4915. info.adrp_addr = 0;
  4916. info.adrp_inst = 0;
  4917. info.depth = 0;
  4918. SectionRef CL = get_section(O, "__OBJC2", "__class_list");
  4919. if (CL == SectionRef())
  4920. CL = get_section(O, "__DATA", "__objc_classlist");
  4921. info.S = CL;
  4922. walk_pointer_list_64("class", CL, O, &info, print_class64_t);
  4923. SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
  4924. if (CR == SectionRef())
  4925. CR = get_section(O, "__DATA", "__objc_classrefs");
  4926. info.S = CR;
  4927. walk_pointer_list_64("class refs", CR, O, &info, nullptr);
  4928. SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
  4929. if (SR == SectionRef())
  4930. SR = get_section(O, "__DATA", "__objc_superrefs");
  4931. info.S = SR;
  4932. walk_pointer_list_64("super refs", SR, O, &info, nullptr);
  4933. SectionRef CA = get_section(O, "__OBJC2", "__category_list");
  4934. if (CA == SectionRef())
  4935. CA = get_section(O, "__DATA", "__objc_catlist");
  4936. info.S = CA;
  4937. walk_pointer_list_64("category", CA, O, &info, print_category64_t);
  4938. SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
  4939. if (PL == SectionRef())
  4940. PL = get_section(O, "__DATA", "__objc_protolist");
  4941. info.S = PL;
  4942. walk_pointer_list_64("protocol", PL, O, &info, nullptr);
  4943. SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
  4944. if (MR == SectionRef())
  4945. MR = get_section(O, "__DATA", "__objc_msgrefs");
  4946. info.S = MR;
  4947. print_message_refs64(MR, &info);
  4948. SectionRef II = get_section(O, "__OBJC2", "__image_info");
  4949. if (II == SectionRef())
  4950. II = get_section(O, "__DATA", "__objc_imageinfo");
  4951. info.S = II;
  4952. print_image_info64(II, &info);
  4953. if (info.bindtable != nullptr)
  4954. delete info.bindtable;
  4955. }
  4956. static void printObjc2_32bit_MetaData(MachOObjectFile *O, bool verbose) {
  4957. SymbolAddressMap AddrMap;
  4958. if (verbose)
  4959. CreateSymbolAddressMap(O, &AddrMap);
  4960. std::vector<SectionRef> Sections;
  4961. for (const SectionRef &Section : O->sections()) {
  4962. StringRef SectName;
  4963. Section.getName(SectName);
  4964. Sections.push_back(Section);
  4965. }
  4966. struct DisassembleInfo info;
  4967. // Set up the block of info used by the Symbolizer call backs.
  4968. info.verbose = verbose;
  4969. info.O = O;
  4970. info.AddrMap = &AddrMap;
  4971. info.Sections = &Sections;
  4972. info.class_name = nullptr;
  4973. info.selector_name = nullptr;
  4974. info.method = nullptr;
  4975. info.demangled_name = nullptr;
  4976. info.bindtable = nullptr;
  4977. info.adrp_addr = 0;
  4978. info.adrp_inst = 0;
  4979. const SectionRef CL = get_section(O, "__OBJC2", "__class_list");
  4980. if (CL != SectionRef()) {
  4981. info.S = CL;
  4982. walk_pointer_list_32("class", CL, O, &info, print_class32_t);
  4983. } else {
  4984. const SectionRef CL = get_section(O, "__DATA", "__objc_classlist");
  4985. info.S = CL;
  4986. walk_pointer_list_32("class", CL, O, &info, print_class32_t);
  4987. }
  4988. const SectionRef CR = get_section(O, "__OBJC2", "__class_refs");
  4989. if (CR != SectionRef()) {
  4990. info.S = CR;
  4991. walk_pointer_list_32("class refs", CR, O, &info, nullptr);
  4992. } else {
  4993. const SectionRef CR = get_section(O, "__DATA", "__objc_classrefs");
  4994. info.S = CR;
  4995. walk_pointer_list_32("class refs", CR, O, &info, nullptr);
  4996. }
  4997. const SectionRef SR = get_section(O, "__OBJC2", "__super_refs");
  4998. if (SR != SectionRef()) {
  4999. info.S = SR;
  5000. walk_pointer_list_32("super refs", SR, O, &info, nullptr);
  5001. } else {
  5002. const SectionRef SR = get_section(O, "__DATA", "__objc_superrefs");
  5003. info.S = SR;
  5004. walk_pointer_list_32("super refs", SR, O, &info, nullptr);
  5005. }
  5006. const SectionRef CA = get_section(O, "__OBJC2", "__category_list");
  5007. if (CA != SectionRef()) {
  5008. info.S = CA;
  5009. walk_pointer_list_32("category", CA, O, &info, print_category32_t);
  5010. } else {
  5011. const SectionRef CA = get_section(O, "__DATA", "__objc_catlist");
  5012. info.S = CA;
  5013. walk_pointer_list_32("category", CA, O, &info, print_category32_t);
  5014. }
  5015. const SectionRef PL = get_section(O, "__OBJC2", "__protocol_list");
  5016. if (PL != SectionRef()) {
  5017. info.S = PL;
  5018. walk_pointer_list_32("protocol", PL, O, &info, nullptr);
  5019. } else {
  5020. const SectionRef PL = get_section(O, "__DATA", "__objc_protolist");
  5021. info.S = PL;
  5022. walk_pointer_list_32("protocol", PL, O, &info, nullptr);
  5023. }
  5024. const SectionRef MR = get_section(O, "__OBJC2", "__message_refs");
  5025. if (MR != SectionRef()) {
  5026. info.S = MR;
  5027. print_message_refs32(MR, &info);
  5028. } else {
  5029. const SectionRef MR = get_section(O, "__DATA", "__objc_msgrefs");
  5030. info.S = MR;
  5031. print_message_refs32(MR, &info);
  5032. }
  5033. const SectionRef II = get_section(O, "__OBJC2", "__image_info");
  5034. if (II != SectionRef()) {
  5035. info.S = II;
  5036. print_image_info32(II, &info);
  5037. } else {
  5038. const SectionRef II = get_section(O, "__DATA", "__objc_imageinfo");
  5039. info.S = II;
  5040. print_image_info32(II, &info);
  5041. }
  5042. }
  5043. static bool printObjc1_32bit_MetaData(MachOObjectFile *O, bool verbose) {
  5044. uint32_t i, j, p, offset, xoffset, left, defs_left, def;
  5045. const char *r, *name, *defs;
  5046. struct objc_module_t module;
  5047. SectionRef S, xS;
  5048. struct objc_symtab_t symtab;
  5049. struct objc_class_t objc_class;
  5050. struct objc_category_t objc_category;
  5051. outs() << "Objective-C segment\n";
  5052. S = get_section(O, "__OBJC", "__module_info");
  5053. if (S == SectionRef())
  5054. return false;
  5055. SymbolAddressMap AddrMap;
  5056. if (verbose)
  5057. CreateSymbolAddressMap(O, &AddrMap);
  5058. std::vector<SectionRef> Sections;
  5059. for (const SectionRef &Section : O->sections()) {
  5060. StringRef SectName;
  5061. Section.getName(SectName);
  5062. Sections.push_back(Section);
  5063. }
  5064. struct DisassembleInfo info;
  5065. // Set up the block of info used by the Symbolizer call backs.
  5066. info.verbose = verbose;
  5067. info.O = O;
  5068. info.AddrMap = &AddrMap;
  5069. info.Sections = &Sections;
  5070. info.class_name = nullptr;
  5071. info.selector_name = nullptr;
  5072. info.method = nullptr;
  5073. info.demangled_name = nullptr;
  5074. info.bindtable = nullptr;
  5075. info.adrp_addr = 0;
  5076. info.adrp_inst = 0;
  5077. for (i = 0; i < S.getSize(); i += sizeof(struct objc_module_t)) {
  5078. p = S.getAddress() + i;
  5079. r = get_pointer_32(p, offset, left, S, &info, true);
  5080. if (r == nullptr)
  5081. return true;
  5082. memset(&module, '\0', sizeof(struct objc_module_t));
  5083. if (left < sizeof(struct objc_module_t)) {
  5084. memcpy(&module, r, left);
  5085. outs() << " (module extends past end of __module_info section)\n";
  5086. } else
  5087. memcpy(&module, r, sizeof(struct objc_module_t));
  5088. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5089. swapStruct(module);
  5090. outs() << "Module " << format("0x%" PRIx32, p) << "\n";
  5091. outs() << " version " << module.version << "\n";
  5092. outs() << " size " << module.size << "\n";
  5093. outs() << " name ";
  5094. name = get_pointer_32(module.name, xoffset, left, xS, &info, true);
  5095. if (name != nullptr)
  5096. outs() << format("%.*s", left, name);
  5097. else
  5098. outs() << format("0x%08" PRIx32, module.name)
  5099. << "(not in an __OBJC section)";
  5100. outs() << "\n";
  5101. r = get_pointer_32(module.symtab, xoffset, left, xS, &info, true);
  5102. if (module.symtab == 0 || r == nullptr) {
  5103. outs() << " symtab " << format("0x%08" PRIx32, module.symtab)
  5104. << " (not in an __OBJC section)\n";
  5105. continue;
  5106. }
  5107. outs() << " symtab " << format("0x%08" PRIx32, module.symtab) << "\n";
  5108. memset(&symtab, '\0', sizeof(struct objc_symtab_t));
  5109. defs_left = 0;
  5110. defs = nullptr;
  5111. if (left < sizeof(struct objc_symtab_t)) {
  5112. memcpy(&symtab, r, left);
  5113. outs() << "\tsymtab extends past end of an __OBJC section)\n";
  5114. } else {
  5115. memcpy(&symtab, r, sizeof(struct objc_symtab_t));
  5116. if (left > sizeof(struct objc_symtab_t)) {
  5117. defs_left = left - sizeof(struct objc_symtab_t);
  5118. defs = r + sizeof(struct objc_symtab_t);
  5119. }
  5120. }
  5121. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5122. swapStruct(symtab);
  5123. outs() << "\tsel_ref_cnt " << symtab.sel_ref_cnt << "\n";
  5124. r = get_pointer_32(symtab.refs, xoffset, left, xS, &info, true);
  5125. outs() << "\trefs " << format("0x%08" PRIx32, symtab.refs);
  5126. if (r == nullptr)
  5127. outs() << " (not in an __OBJC section)";
  5128. outs() << "\n";
  5129. outs() << "\tcls_def_cnt " << symtab.cls_def_cnt << "\n";
  5130. outs() << "\tcat_def_cnt " << symtab.cat_def_cnt << "\n";
  5131. if (symtab.cls_def_cnt > 0)
  5132. outs() << "\tClass Definitions\n";
  5133. for (j = 0; j < symtab.cls_def_cnt; j++) {
  5134. if ((j + 1) * sizeof(uint32_t) > defs_left) {
  5135. outs() << "\t(remaining class defs entries entends past the end of the "
  5136. << "section)\n";
  5137. break;
  5138. }
  5139. memcpy(&def, defs + j * sizeof(uint32_t), sizeof(uint32_t));
  5140. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5141. sys::swapByteOrder(def);
  5142. r = get_pointer_32(def, xoffset, left, xS, &info, true);
  5143. outs() << "\tdefs[" << j << "] " << format("0x%08" PRIx32, def);
  5144. if (r != nullptr) {
  5145. if (left > sizeof(struct objc_class_t)) {
  5146. outs() << "\n";
  5147. memcpy(&objc_class, r, sizeof(struct objc_class_t));
  5148. } else {
  5149. outs() << " (entends past the end of the section)\n";
  5150. memset(&objc_class, '\0', sizeof(struct objc_class_t));
  5151. memcpy(&objc_class, r, left);
  5152. }
  5153. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5154. swapStruct(objc_class);
  5155. print_objc_class_t(&objc_class, &info);
  5156. } else {
  5157. outs() << "(not in an __OBJC section)\n";
  5158. }
  5159. if (CLS_GETINFO(&objc_class, CLS_CLASS)) {
  5160. outs() << "\tMeta Class";
  5161. r = get_pointer_32(objc_class.isa, xoffset, left, xS, &info, true);
  5162. if (r != nullptr) {
  5163. if (left > sizeof(struct objc_class_t)) {
  5164. outs() << "\n";
  5165. memcpy(&objc_class, r, sizeof(struct objc_class_t));
  5166. } else {
  5167. outs() << " (entends past the end of the section)\n";
  5168. memset(&objc_class, '\0', sizeof(struct objc_class_t));
  5169. memcpy(&objc_class, r, left);
  5170. }
  5171. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5172. swapStruct(objc_class);
  5173. print_objc_class_t(&objc_class, &info);
  5174. } else {
  5175. outs() << "(not in an __OBJC section)\n";
  5176. }
  5177. }
  5178. }
  5179. if (symtab.cat_def_cnt > 0)
  5180. outs() << "\tCategory Definitions\n";
  5181. for (j = 0; j < symtab.cat_def_cnt; j++) {
  5182. if ((j + symtab.cls_def_cnt + 1) * sizeof(uint32_t) > defs_left) {
  5183. outs() << "\t(remaining category defs entries entends past the end of "
  5184. << "the section)\n";
  5185. break;
  5186. }
  5187. memcpy(&def, defs + (j + symtab.cls_def_cnt) * sizeof(uint32_t),
  5188. sizeof(uint32_t));
  5189. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5190. sys::swapByteOrder(def);
  5191. r = get_pointer_32(def, xoffset, left, xS, &info, true);
  5192. outs() << "\tdefs[" << j + symtab.cls_def_cnt << "] "
  5193. << format("0x%08" PRIx32, def);
  5194. if (r != nullptr) {
  5195. if (left > sizeof(struct objc_category_t)) {
  5196. outs() << "\n";
  5197. memcpy(&objc_category, r, sizeof(struct objc_category_t));
  5198. } else {
  5199. outs() << " (entends past the end of the section)\n";
  5200. memset(&objc_category, '\0', sizeof(struct objc_category_t));
  5201. memcpy(&objc_category, r, left);
  5202. }
  5203. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5204. swapStruct(objc_category);
  5205. print_objc_objc_category_t(&objc_category, &info);
  5206. } else {
  5207. outs() << "(not in an __OBJC section)\n";
  5208. }
  5209. }
  5210. }
  5211. const SectionRef II = get_section(O, "__OBJC", "__image_info");
  5212. if (II != SectionRef())
  5213. print_image_info(II, &info);
  5214. return true;
  5215. }
  5216. static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
  5217. uint32_t size, uint32_t addr) {
  5218. SymbolAddressMap AddrMap;
  5219. CreateSymbolAddressMap(O, &AddrMap);
  5220. std::vector<SectionRef> Sections;
  5221. for (const SectionRef &Section : O->sections()) {
  5222. StringRef SectName;
  5223. Section.getName(SectName);
  5224. Sections.push_back(Section);
  5225. }
  5226. struct DisassembleInfo info;
  5227. // Set up the block of info used by the Symbolizer call backs.
  5228. info.verbose = true;
  5229. info.O = O;
  5230. info.AddrMap = &AddrMap;
  5231. info.Sections = &Sections;
  5232. info.class_name = nullptr;
  5233. info.selector_name = nullptr;
  5234. info.method = nullptr;
  5235. info.demangled_name = nullptr;
  5236. info.bindtable = nullptr;
  5237. info.adrp_addr = 0;
  5238. info.adrp_inst = 0;
  5239. const char *p;
  5240. struct objc_protocol_t protocol;
  5241. uint32_t left, paddr;
  5242. for (p = sect; p < sect + size; p += sizeof(struct objc_protocol_t)) {
  5243. memset(&protocol, '\0', sizeof(struct objc_protocol_t));
  5244. left = size - (p - sect);
  5245. if (left < sizeof(struct objc_protocol_t)) {
  5246. outs() << "Protocol extends past end of __protocol section\n";
  5247. memcpy(&protocol, p, left);
  5248. } else
  5249. memcpy(&protocol, p, sizeof(struct objc_protocol_t));
  5250. if (O->isLittleEndian() != sys::IsLittleEndianHost)
  5251. swapStruct(protocol);
  5252. paddr = addr + (p - sect);
  5253. outs() << "Protocol " << format("0x%" PRIx32, paddr);
  5254. if (print_protocol(paddr, 0, &info))
  5255. outs() << "(not in an __OBJC section)\n";
  5256. }
  5257. }
  5258. #ifdef HAVE_LIBXAR
  5259. inline void swapStruct(struct xar_header &xar) {
  5260. sys::swapByteOrder(xar.magic);
  5261. sys::swapByteOrder(xar.size);
  5262. sys::swapByteOrder(xar.version);
  5263. sys::swapByteOrder(xar.toc_length_compressed);
  5264. sys::swapByteOrder(xar.toc_length_uncompressed);
  5265. sys::swapByteOrder(xar.cksum_alg);
  5266. }
  5267. static void PrintModeVerbose(uint32_t mode) {
  5268. switch(mode & S_IFMT){
  5269. case S_IFDIR:
  5270. outs() << "d";
  5271. break;
  5272. case S_IFCHR:
  5273. outs() << "c";
  5274. break;
  5275. case S_IFBLK:
  5276. outs() << "b";
  5277. break;
  5278. case S_IFREG:
  5279. outs() << "-";
  5280. break;
  5281. case S_IFLNK:
  5282. outs() << "l";
  5283. break;
  5284. case S_IFSOCK:
  5285. outs() << "s";
  5286. break;
  5287. default:
  5288. outs() << "?";
  5289. break;
  5290. }
  5291. /* owner permissions */
  5292. if(mode & S_IREAD)
  5293. outs() << "r";
  5294. else
  5295. outs() << "-";
  5296. if(mode & S_IWRITE)
  5297. outs() << "w";
  5298. else
  5299. outs() << "-";
  5300. if(mode & S_ISUID)
  5301. outs() << "s";
  5302. else if(mode & S_IEXEC)
  5303. outs() << "x";
  5304. else
  5305. outs() << "-";
  5306. /* group permissions */
  5307. if(mode & (S_IREAD >> 3))
  5308. outs() << "r";
  5309. else
  5310. outs() << "-";
  5311. if(mode & (S_IWRITE >> 3))
  5312. outs() << "w";
  5313. else
  5314. outs() << "-";
  5315. if(mode & S_ISGID)
  5316. outs() << "s";
  5317. else if(mode & (S_IEXEC >> 3))
  5318. outs() << "x";
  5319. else
  5320. outs() << "-";
  5321. /* other permissions */
  5322. if(mode & (S_IREAD >> 6))
  5323. outs() << "r";
  5324. else
  5325. outs() << "-";
  5326. if(mode & (S_IWRITE >> 6))
  5327. outs() << "w";
  5328. else
  5329. outs() << "-";
  5330. if(mode & S_ISVTX)
  5331. outs() << "t";
  5332. else if(mode & (S_IEXEC >> 6))
  5333. outs() << "x";
  5334. else
  5335. outs() << "-";
  5336. }
  5337. static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
  5338. xar_iter_t xi;
  5339. xar_file_t xf;
  5340. xar_iter_t xp;
  5341. const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
  5342. char *endp;
  5343. uint32_t mode_value;
  5344. xi = xar_iter_new();
  5345. if (!xi) {
  5346. errs() << "Can't obtain an xar iterator for xar archive "
  5347. << XarFilename << "\n";
  5348. return;
  5349. }
  5350. // Go through the xar's files.
  5351. for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
  5352. xp = xar_iter_new();
  5353. if(!xp){
  5354. errs() << "Can't obtain an xar iterator for xar archive "
  5355. << XarFilename << "\n";
  5356. return;
  5357. }
  5358. type = nullptr;
  5359. mode = nullptr;
  5360. user = nullptr;
  5361. group = nullptr;
  5362. size = nullptr;
  5363. mtime = nullptr;
  5364. name = nullptr;
  5365. for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
  5366. const char *val = nullptr;
  5367. xar_prop_get(xf, key, &val);
  5368. #if 0 // Useful for debugging.
  5369. outs() << "key: " << key << " value: " << val << "\n";
  5370. #endif
  5371. if(strcmp(key, "type") == 0)
  5372. type = val;
  5373. if(strcmp(key, "mode") == 0)
  5374. mode = val;
  5375. if(strcmp(key, "user") == 0)
  5376. user = val;
  5377. if(strcmp(key, "group") == 0)
  5378. group = val;
  5379. if(strcmp(key, "data/size") == 0)
  5380. size = val;
  5381. if(strcmp(key, "mtime") == 0)
  5382. mtime = val;
  5383. if(strcmp(key, "name") == 0)
  5384. name = val;
  5385. }
  5386. if(mode != nullptr){
  5387. mode_value = strtoul(mode, &endp, 8);
  5388. if(*endp != '\0')
  5389. outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
  5390. if(strcmp(type, "file") == 0)
  5391. mode_value |= S_IFREG;
  5392. PrintModeVerbose(mode_value);
  5393. outs() << " ";
  5394. }
  5395. if(user != nullptr)
  5396. outs() << format("%10s/", user);
  5397. if(group != nullptr)
  5398. outs() << format("%-10s ", group);
  5399. if(size != nullptr)
  5400. outs() << format("%7s ", size);
  5401. if(mtime != nullptr){
  5402. for(m = mtime; *m != 'T' && *m != '\0'; m++)
  5403. outs() << *m;
  5404. if(*m == 'T')
  5405. m++;
  5406. outs() << " ";
  5407. for( ; *m != 'Z' && *m != '\0'; m++)
  5408. outs() << *m;
  5409. outs() << " ";
  5410. }
  5411. if(name != nullptr)
  5412. outs() << name;
  5413. outs() << "\n";
  5414. }
  5415. }
  5416. static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
  5417. uint32_t size, bool verbose,
  5418. bool PrintXarHeader, bool PrintXarFileHeaders,
  5419. std::string XarMemberName) {
  5420. if(size < sizeof(struct xar_header)) {
  5421. outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
  5422. "of struct xar_header)\n";
  5423. return;
  5424. }
  5425. struct xar_header XarHeader;
  5426. memcpy(&XarHeader, sect, sizeof(struct xar_header));
  5427. if (sys::IsLittleEndianHost)
  5428. swapStruct(XarHeader);
  5429. if (PrintXarHeader) {
  5430. if (!XarMemberName.empty())
  5431. outs() << "In xar member " << XarMemberName << ": ";
  5432. else
  5433. outs() << "For (__LLVM,__bundle) section: ";
  5434. outs() << "xar header\n";
  5435. if (XarHeader.magic == XAR_HEADER_MAGIC)
  5436. outs() << " magic XAR_HEADER_MAGIC\n";
  5437. else
  5438. outs() << " magic "
  5439. << format_hex(XarHeader.magic, 10, true)
  5440. << " (not XAR_HEADER_MAGIC)\n";
  5441. outs() << " size " << XarHeader.size << "\n";
  5442. outs() << " version " << XarHeader.version << "\n";
  5443. outs() << " toc_length_compressed " << XarHeader.toc_length_compressed
  5444. << "\n";
  5445. outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
  5446. << "\n";
  5447. outs() << " cksum_alg ";
  5448. switch (XarHeader.cksum_alg) {
  5449. case XAR_CKSUM_NONE:
  5450. outs() << "XAR_CKSUM_NONE\n";
  5451. break;
  5452. case XAR_CKSUM_SHA1:
  5453. outs() << "XAR_CKSUM_SHA1\n";
  5454. break;
  5455. case XAR_CKSUM_MD5:
  5456. outs() << "XAR_CKSUM_MD5\n";
  5457. break;
  5458. #ifdef XAR_CKSUM_SHA256
  5459. case XAR_CKSUM_SHA256:
  5460. outs() << "XAR_CKSUM_SHA256\n";
  5461. break;
  5462. #endif
  5463. #ifdef XAR_CKSUM_SHA512
  5464. case XAR_CKSUM_SHA512:
  5465. outs() << "XAR_CKSUM_SHA512\n";
  5466. break;
  5467. #endif
  5468. default:
  5469. outs() << XarHeader.cksum_alg << "\n";
  5470. }
  5471. }
  5472. SmallString<128> XarFilename;
  5473. int FD;
  5474. std::error_code XarEC =
  5475. sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
  5476. if (XarEC) {
  5477. errs() << XarEC.message() << "\n";
  5478. return;
  5479. }
  5480. tool_output_file XarFile(XarFilename, FD);
  5481. raw_fd_ostream &XarOut = XarFile.os();
  5482. StringRef XarContents(sect, size);
  5483. XarOut << XarContents;
  5484. XarOut.close();
  5485. if (XarOut.has_error())
  5486. return;
  5487. xar_t xar = xar_open(XarFilename.c_str(), READ);
  5488. if (!xar) {
  5489. errs() << "Can't create temporary xar archive " << XarFilename << "\n";
  5490. return;
  5491. }
  5492. SmallString<128> TocFilename;
  5493. std::error_code TocEC =
  5494. sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
  5495. if (TocEC) {
  5496. errs() << TocEC.message() << "\n";
  5497. return;
  5498. }
  5499. xar_serialize(xar, TocFilename.c_str());
  5500. if (PrintXarFileHeaders) {
  5501. if (!XarMemberName.empty())
  5502. outs() << "In xar member " << XarMemberName << ": ";
  5503. else
  5504. outs() << "For (__LLVM,__bundle) section: ";
  5505. outs() << "xar archive files:\n";
  5506. PrintXarFilesSummary(XarFilename.c_str(), xar);
  5507. }
  5508. ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
  5509. MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
  5510. if (std::error_code EC = FileOrErr.getError()) {
  5511. errs() << EC.message() << "\n";
  5512. return;
  5513. }
  5514. std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
  5515. if (!XarMemberName.empty())
  5516. outs() << "In xar member " << XarMemberName << ": ";
  5517. else
  5518. outs() << "For (__LLVM,__bundle) section: ";
  5519. outs() << "xar table of contents:\n";
  5520. outs() << Buffer->getBuffer() << "\n";
  5521. // TODO: Go through the xar's files.
  5522. xar_iter_t xi = xar_iter_new();
  5523. if(!xi){
  5524. errs() << "Can't obtain an xar iterator for xar archive "
  5525. << XarFilename.c_str() << "\n";
  5526. xar_close(xar);
  5527. return;
  5528. }
  5529. for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
  5530. const char *key;
  5531. xar_iter_t xp;
  5532. const char *member_name, *member_type, *member_size_string;
  5533. size_t member_size;
  5534. xp = xar_iter_new();
  5535. if(!xp){
  5536. errs() << "Can't obtain an xar iterator for xar archive "
  5537. << XarFilename.c_str() << "\n";
  5538. xar_close(xar);
  5539. return;
  5540. }
  5541. member_name = NULL;
  5542. member_type = NULL;
  5543. member_size_string = NULL;
  5544. for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
  5545. const char *val = nullptr;
  5546. xar_prop_get(xf, key, &val);
  5547. #if 0 // Useful for debugging.
  5548. outs() << "key: " << key << " value: " << val << "\n";
  5549. #endif
  5550. if(strcmp(key, "name") == 0)
  5551. member_name = val;
  5552. if(strcmp(key, "type") == 0)
  5553. member_type = val;
  5554. if(strcmp(key, "data/size") == 0)
  5555. member_size_string = val;
  5556. }
  5557. /*
  5558. * If we find a file with a name, date/size and type properties
  5559. * and with the type being "file" see if that is a xar file.
  5560. */
  5561. if (member_name != NULL && member_type != NULL &&
  5562. strcmp(member_type, "file") == 0 &&
  5563. member_size_string != NULL){
  5564. // Extract the file into a buffer.
  5565. char *endptr;
  5566. member_size = strtoul(member_size_string, &endptr, 10);
  5567. if (*endptr == '\0' && member_size != 0) {
  5568. char *buffer = (char *) ::operator new (member_size);
  5569. if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
  5570. #if 0 // Useful for debugging.
  5571. outs() << "xar member: " << member_name << " extracted\n";
  5572. #endif
  5573. // Set the XarMemberName we want to see printed in the header.
  5574. std::string OldXarMemberName;
  5575. // If XarMemberName is already set this is nested. So
  5576. // save the old name and create the nested name.
  5577. if (!XarMemberName.empty()) {
  5578. OldXarMemberName = XarMemberName;
  5579. XarMemberName =
  5580. (Twine("[") + XarMemberName + "]" + member_name).str();
  5581. } else {
  5582. OldXarMemberName = "";
  5583. XarMemberName = member_name;
  5584. }
  5585. // See if this is could be a xar file (nested).
  5586. if (member_size >= sizeof(struct xar_header)) {
  5587. #if 0 // Useful for debugging.
  5588. outs() << "could be a xar file: " << member_name << "\n";
  5589. #endif
  5590. memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
  5591. if (sys::IsLittleEndianHost)
  5592. swapStruct(XarHeader);
  5593. if(XarHeader.magic == XAR_HEADER_MAGIC)
  5594. DumpBitcodeSection(O, buffer, member_size, verbose,
  5595. PrintXarHeader, PrintXarFileHeaders,
  5596. XarMemberName);
  5597. }
  5598. XarMemberName = OldXarMemberName;
  5599. }
  5600. delete buffer;
  5601. }
  5602. }
  5603. xar_iter_free(xp);
  5604. }
  5605. xar_close(xar);
  5606. }
  5607. #endif // defined(HAVE_LIBXAR)
  5608. static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
  5609. if (O->is64Bit())
  5610. printObjc2_64bit_MetaData(O, verbose);
  5611. else {
  5612. MachO::mach_header H;
  5613. H = O->getHeader();
  5614. if (H.cputype == MachO::CPU_TYPE_ARM)
  5615. printObjc2_32bit_MetaData(O, verbose);
  5616. else {
  5617. // This is the 32-bit non-arm cputype case. Which is normally
  5618. // the first Objective-C ABI. But it may be the case of a
  5619. // binary for the iOS simulator which is the second Objective-C
  5620. // ABI. In that case printObjc1_32bit_MetaData() will determine that
  5621. // and return false.
  5622. if (!printObjc1_32bit_MetaData(O, verbose))
  5623. printObjc2_32bit_MetaData(O, verbose);
  5624. }
  5625. }
  5626. }
  5627. // GuessLiteralPointer returns a string which for the item in the Mach-O file
  5628. // for the address passed in as ReferenceValue for printing as a comment with
  5629. // the instruction and also returns the corresponding type of that item
  5630. // indirectly through ReferenceType.
  5631. //
  5632. // If ReferenceValue is an address of literal cstring then a pointer to the
  5633. // cstring is returned and ReferenceType is set to
  5634. // LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
  5635. //
  5636. // If ReferenceValue is an address of an Objective-C CFString, Selector ref or
  5637. // Class ref that name is returned and the ReferenceType is set accordingly.
  5638. //
  5639. // Lastly, literals which are Symbol address in a literal pool are looked for
  5640. // and if found the symbol name is returned and ReferenceType is set to
  5641. // LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
  5642. //
  5643. // If there is no item in the Mach-O file for the address passed in as
  5644. // ReferenceValue nullptr is returned and ReferenceType is unchanged.
  5645. static const char *GuessLiteralPointer(uint64_t ReferenceValue,
  5646. uint64_t ReferencePC,
  5647. uint64_t *ReferenceType,
  5648. struct DisassembleInfo *info) {
  5649. // First see if there is an external relocation entry at the ReferencePC.
  5650. if (info->O->getHeader().filetype == MachO::MH_OBJECT) {
  5651. uint64_t sect_addr = info->S.getAddress();
  5652. uint64_t sect_offset = ReferencePC - sect_addr;
  5653. bool reloc_found = false;
  5654. DataRefImpl Rel;
  5655. MachO::any_relocation_info RE;
  5656. bool isExtern = false;
  5657. SymbolRef Symbol;
  5658. for (const RelocationRef &Reloc : info->S.relocations()) {
  5659. uint64_t RelocOffset = Reloc.getOffset();
  5660. if (RelocOffset == sect_offset) {
  5661. Rel = Reloc.getRawDataRefImpl();
  5662. RE = info->O->getRelocation(Rel);
  5663. if (info->O->isRelocationScattered(RE))
  5664. continue;
  5665. isExtern = info->O->getPlainRelocationExternal(RE);
  5666. if (isExtern) {
  5667. symbol_iterator RelocSym = Reloc.getSymbol();
  5668. Symbol = *RelocSym;
  5669. }
  5670. reloc_found = true;
  5671. break;
  5672. }
  5673. }
  5674. // If there is an external relocation entry for a symbol in a section
  5675. // then used that symbol's value for the value of the reference.
  5676. if (reloc_found && isExtern) {
  5677. if (info->O->getAnyRelocationPCRel(RE)) {
  5678. unsigned Type = info->O->getAnyRelocationType(RE);
  5679. if (Type == MachO::X86_64_RELOC_SIGNED) {
  5680. ReferenceValue = Symbol.getValue();
  5681. }
  5682. }
  5683. }
  5684. }
  5685. // Look for literals such as Objective-C CFStrings refs, Selector refs,
  5686. // Message refs and Class refs.
  5687. bool classref, selref, msgref, cfstring;
  5688. uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
  5689. selref, msgref, cfstring);
  5690. if (classref && pointer_value == 0) {
  5691. // Note the ReferenceValue is a pointer into the __objc_classrefs section.
  5692. // And the pointer_value in that section is typically zero as it will be
  5693. // set by dyld as part of the "bind information".
  5694. const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
  5695. if (name != nullptr) {
  5696. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
  5697. const char *class_name = strrchr(name, '$');
  5698. if (class_name != nullptr && class_name[1] == '_' &&
  5699. class_name[2] != '\0') {
  5700. info->class_name = class_name + 2;
  5701. return name;
  5702. }
  5703. }
  5704. }
  5705. if (classref) {
  5706. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
  5707. const char *name =
  5708. get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
  5709. if (name != nullptr)
  5710. info->class_name = name;
  5711. else
  5712. name = "bad class ref";
  5713. return name;
  5714. }
  5715. if (cfstring) {
  5716. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
  5717. const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
  5718. return name;
  5719. }
  5720. if (selref && pointer_value == 0)
  5721. pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
  5722. if (pointer_value != 0)
  5723. ReferenceValue = pointer_value;
  5724. const char *name = GuessCstringPointer(ReferenceValue, info);
  5725. if (name) {
  5726. if (pointer_value != 0 && selref) {
  5727. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
  5728. info->selector_name = name;
  5729. } else if (pointer_value != 0 && msgref) {
  5730. info->class_name = nullptr;
  5731. *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
  5732. info->selector_name = name;
  5733. } else
  5734. *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
  5735. return name;
  5736. }
  5737. // Lastly look for an indirect symbol with this ReferenceValue which is in
  5738. // a literal pool. If found return that symbol name.
  5739. name = GuessIndirectSymbol(ReferenceValue, info);
  5740. if (name) {
  5741. *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
  5742. return name;
  5743. }
  5744. return nullptr;
  5745. }
  5746. // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
  5747. // the Symbolizer. It looks up the ReferenceValue using the info passed via the
  5748. // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
  5749. // is created and returns the symbol name that matches the ReferenceValue or
  5750. // nullptr if none. The ReferenceType is passed in for the IN type of
  5751. // reference the instruction is making from the values in defined in the header
  5752. // "llvm-c/Disassembler.h". On return the ReferenceType can set to a specific
  5753. // Out type and the ReferenceName will also be set which is added as a comment
  5754. // to the disassembled instruction.
  5755. //
  5756. #if HAVE_CXXABI_H
  5757. // If the symbol name is a C++ mangled name then the demangled name is
  5758. // returned through ReferenceName and ReferenceType is set to
  5759. // LLVMDisassembler_ReferenceType_DeMangled_Name .
  5760. #endif
  5761. //
  5762. // When this is called to get a symbol name for a branch target then the
  5763. // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
  5764. // SymbolValue will be looked for in the indirect symbol table to determine if
  5765. // it is an address for a symbol stub. If so then the symbol name for that
  5766. // stub is returned indirectly through ReferenceName and then ReferenceType is
  5767. // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
  5768. //
  5769. // When this is called with an value loaded via a PC relative load then
  5770. // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
  5771. // SymbolValue is checked to be an address of literal pointer, symbol pointer,
  5772. // or an Objective-C meta data reference. If so the output ReferenceType is
  5773. // set to correspond to that as well as setting the ReferenceName.
  5774. static const char *SymbolizerSymbolLookUp(void *DisInfo,
  5775. uint64_t ReferenceValue,
  5776. uint64_t *ReferenceType,
  5777. uint64_t ReferencePC,
  5778. const char **ReferenceName) {
  5779. struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
  5780. // If no verbose symbolic information is wanted then just return nullptr.
  5781. if (!info->verbose) {
  5782. *ReferenceName = nullptr;
  5783. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5784. return nullptr;
  5785. }
  5786. const char *SymbolName = GuessSymbolName(ReferenceValue, info->AddrMap);
  5787. if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
  5788. *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
  5789. if (*ReferenceName != nullptr) {
  5790. method_reference(info, ReferenceType, ReferenceName);
  5791. if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
  5792. *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
  5793. } else
  5794. #if HAVE_CXXABI_H
  5795. if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
  5796. if (info->demangled_name != nullptr)
  5797. free(info->demangled_name);
  5798. int status;
  5799. info->demangled_name =
  5800. abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status);
  5801. if (info->demangled_name != nullptr) {
  5802. *ReferenceName = info->demangled_name;
  5803. *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
  5804. } else
  5805. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5806. } else
  5807. #endif
  5808. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5809. } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
  5810. *ReferenceName =
  5811. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5812. if (*ReferenceName)
  5813. method_reference(info, ReferenceType, ReferenceName);
  5814. else
  5815. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5816. // If this is arm64 and the reference is an adrp instruction save the
  5817. // instruction, passed in ReferenceValue and the address of the instruction
  5818. // for use later if we see and add immediate instruction.
  5819. } else if (info->O->getArch() == Triple::aarch64 &&
  5820. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADRP) {
  5821. info->adrp_inst = ReferenceValue;
  5822. info->adrp_addr = ReferencePC;
  5823. SymbolName = nullptr;
  5824. *ReferenceName = nullptr;
  5825. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5826. // If this is arm64 and reference is an add immediate instruction and we
  5827. // have
  5828. // seen an adrp instruction just before it and the adrp's Xd register
  5829. // matches
  5830. // this add's Xn register reconstruct the value being referenced and look to
  5831. // see if it is a literal pointer. Note the add immediate instruction is
  5832. // passed in ReferenceValue.
  5833. } else if (info->O->getArch() == Triple::aarch64 &&
  5834. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri &&
  5835. ReferencePC - 4 == info->adrp_addr &&
  5836. (info->adrp_inst & 0x9f000000) == 0x90000000 &&
  5837. (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
  5838. uint32_t addxri_inst;
  5839. uint64_t adrp_imm, addxri_imm;
  5840. adrp_imm =
  5841. ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
  5842. if (info->adrp_inst & 0x0200000)
  5843. adrp_imm |= 0xfffffffffc000000LL;
  5844. addxri_inst = ReferenceValue;
  5845. addxri_imm = (addxri_inst >> 10) & 0xfff;
  5846. if (((addxri_inst >> 22) & 0x3) == 1)
  5847. addxri_imm <<= 12;
  5848. ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
  5849. (adrp_imm << 12) + addxri_imm;
  5850. *ReferenceName =
  5851. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5852. if (*ReferenceName == nullptr)
  5853. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5854. // If this is arm64 and the reference is a load register instruction and we
  5855. // have seen an adrp instruction just before it and the adrp's Xd register
  5856. // matches this add's Xn register reconstruct the value being referenced and
  5857. // look to see if it is a literal pointer. Note the load register
  5858. // instruction is passed in ReferenceValue.
  5859. } else if (info->O->getArch() == Triple::aarch64 &&
  5860. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXui &&
  5861. ReferencePC - 4 == info->adrp_addr &&
  5862. (info->adrp_inst & 0x9f000000) == 0x90000000 &&
  5863. (info->adrp_inst & 0x1f) == ((ReferenceValue >> 5) & 0x1f)) {
  5864. uint32_t ldrxui_inst;
  5865. uint64_t adrp_imm, ldrxui_imm;
  5866. adrp_imm =
  5867. ((info->adrp_inst & 0x00ffffe0) >> 3) | ((info->adrp_inst >> 29) & 0x3);
  5868. if (info->adrp_inst & 0x0200000)
  5869. adrp_imm |= 0xfffffffffc000000LL;
  5870. ldrxui_inst = ReferenceValue;
  5871. ldrxui_imm = (ldrxui_inst >> 10) & 0xfff;
  5872. ReferenceValue = (info->adrp_addr & 0xfffffffffffff000LL) +
  5873. (adrp_imm << 12) + (ldrxui_imm << 3);
  5874. *ReferenceName =
  5875. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5876. if (*ReferenceName == nullptr)
  5877. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5878. }
  5879. // If this arm64 and is an load register (PC-relative) instruction the
  5880. // ReferenceValue is the PC plus the immediate value.
  5881. else if (info->O->getArch() == Triple::aarch64 &&
  5882. (*ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_LDRXl ||
  5883. *ReferenceType == LLVMDisassembler_ReferenceType_In_ARM64_ADR)) {
  5884. *ReferenceName =
  5885. GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
  5886. if (*ReferenceName == nullptr)
  5887. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5888. }
  5889. #if HAVE_CXXABI_H
  5890. else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
  5891. if (info->demangled_name != nullptr)
  5892. free(info->demangled_name);
  5893. int status;
  5894. info->demangled_name =
  5895. abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr, &status);
  5896. if (info->demangled_name != nullptr) {
  5897. *ReferenceName = info->demangled_name;
  5898. *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
  5899. }
  5900. }
  5901. #endif
  5902. else {
  5903. *ReferenceName = nullptr;
  5904. *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
  5905. }
  5906. return SymbolName;
  5907. }
  5908. /// \brief Emits the comments that are stored in the CommentStream.
  5909. /// Each comment in the CommentStream must end with a newline.
  5910. static void emitComments(raw_svector_ostream &CommentStream,
  5911. SmallString<128> &CommentsToEmit,
  5912. formatted_raw_ostream &FormattedOS,
  5913. const MCAsmInfo &MAI) {
  5914. // Flush the stream before taking its content.
  5915. StringRef Comments = CommentsToEmit.str();
  5916. // Get the default information for printing a comment.
  5917. const char *CommentBegin = MAI.getCommentString();
  5918. unsigned CommentColumn = MAI.getCommentColumn();
  5919. bool IsFirst = true;
  5920. while (!Comments.empty()) {
  5921. if (!IsFirst)
  5922. FormattedOS << '\n';
  5923. // Emit a line of comments.
  5924. FormattedOS.PadToColumn(CommentColumn);
  5925. size_t Position = Comments.find('\n');
  5926. FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
  5927. // Move after the newline character.
  5928. Comments = Comments.substr(Position + 1);
  5929. IsFirst = false;
  5930. }
  5931. FormattedOS.flush();
  5932. // Tell the comment stream that the vector changed underneath it.
  5933. CommentsToEmit.clear();
  5934. }
  5935. static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
  5936. StringRef DisSegName, StringRef DisSectName) {
  5937. const char *McpuDefault = nullptr;
  5938. const Target *ThumbTarget = nullptr;
  5939. const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget);
  5940. if (!TheTarget) {
  5941. // GetTarget prints out stuff.
  5942. return;
  5943. }
  5944. if (MCPU.empty() && McpuDefault)
  5945. MCPU = McpuDefault;
  5946. std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
  5947. std::unique_ptr<const MCInstrInfo> ThumbInstrInfo;
  5948. if (ThumbTarget)
  5949. ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo());
  5950. // Package up features to be passed to target/subtarget
  5951. std::string FeaturesStr;
  5952. if (MAttrs.size()) {
  5953. SubtargetFeatures Features;
  5954. for (unsigned i = 0; i != MAttrs.size(); ++i)
  5955. Features.AddFeature(MAttrs[i]);
  5956. FeaturesStr = Features.getString();
  5957. }
  5958. // Set up disassembler.
  5959. std::unique_ptr<const MCRegisterInfo> MRI(
  5960. TheTarget->createMCRegInfo(TripleName));
  5961. std::unique_ptr<const MCAsmInfo> AsmInfo(
  5962. TheTarget->createMCAsmInfo(*MRI, TripleName));
  5963. std::unique_ptr<const MCSubtargetInfo> STI(
  5964. TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr));
  5965. MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr);
  5966. std::unique_ptr<MCDisassembler> DisAsm(
  5967. TheTarget->createMCDisassembler(*STI, Ctx));
  5968. std::unique_ptr<MCSymbolizer> Symbolizer;
  5969. struct DisassembleInfo SymbolizerInfo;
  5970. std::unique_ptr<MCRelocationInfo> RelInfo(
  5971. TheTarget->createMCRelocationInfo(TripleName, Ctx));
  5972. if (RelInfo) {
  5973. Symbolizer.reset(TheTarget->createMCSymbolizer(
  5974. TripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
  5975. &SymbolizerInfo, &Ctx, std::move(RelInfo)));
  5976. DisAsm->setSymbolizer(std::move(Symbolizer));
  5977. }
  5978. int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
  5979. std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
  5980. Triple(TripleName), AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI));
  5981. // Set the display preference for hex vs. decimal immediates.
  5982. IP->setPrintImmHex(PrintImmHex);
  5983. // Comment stream and backing vector.
  5984. SmallString<128> CommentsToEmit;
  5985. raw_svector_ostream CommentStream(CommentsToEmit);
  5986. // FIXME: Setting the CommentStream in the InstPrinter is problematic in that
  5987. // if it is done then arm64 comments for string literals don't get printed
  5988. // and some constant get printed instead and not setting it causes intel
  5989. // (32-bit and 64-bit) comments printed with different spacing before the
  5990. // comment causing different diffs with the 'C' disassembler library API.
  5991. // IP->setCommentStream(CommentStream);
  5992. if (!AsmInfo || !STI || !DisAsm || !IP) {
  5993. errs() << "error: couldn't initialize disassembler for target "
  5994. << TripleName << '\n';
  5995. return;
  5996. }
  5997. // Set up separate thumb disassembler if needed.
  5998. std::unique_ptr<const MCRegisterInfo> ThumbMRI;
  5999. std::unique_ptr<const MCAsmInfo> ThumbAsmInfo;
  6000. std::unique_ptr<const MCSubtargetInfo> ThumbSTI;
  6001. std::unique_ptr<MCDisassembler> ThumbDisAsm;
  6002. std::unique_ptr<MCInstPrinter> ThumbIP;
  6003. std::unique_ptr<MCContext> ThumbCtx;
  6004. std::unique_ptr<MCSymbolizer> ThumbSymbolizer;
  6005. struct DisassembleInfo ThumbSymbolizerInfo;
  6006. std::unique_ptr<MCRelocationInfo> ThumbRelInfo;
  6007. if (ThumbTarget) {
  6008. ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName));
  6009. ThumbAsmInfo.reset(
  6010. ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName));
  6011. ThumbSTI.reset(
  6012. ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr));
  6013. ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
  6014. ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
  6015. MCContext *PtrThumbCtx = ThumbCtx.get();
  6016. ThumbRelInfo.reset(
  6017. ThumbTarget->createMCRelocationInfo(ThumbTripleName, *PtrThumbCtx));
  6018. if (ThumbRelInfo) {
  6019. ThumbSymbolizer.reset(ThumbTarget->createMCSymbolizer(
  6020. ThumbTripleName, SymbolizerGetOpInfo, SymbolizerSymbolLookUp,
  6021. &ThumbSymbolizerInfo, PtrThumbCtx, std::move(ThumbRelInfo)));
  6022. ThumbDisAsm->setSymbolizer(std::move(ThumbSymbolizer));
  6023. }
  6024. int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
  6025. ThumbIP.reset(ThumbTarget->createMCInstPrinter(
  6026. Triple(ThumbTripleName), ThumbAsmPrinterVariant, *ThumbAsmInfo,
  6027. *ThumbInstrInfo, *ThumbMRI));
  6028. // Set the display preference for hex vs. decimal immediates.
  6029. ThumbIP->setPrintImmHex(PrintImmHex);
  6030. }
  6031. if (ThumbTarget && (!ThumbAsmInfo || !ThumbSTI || !ThumbDisAsm || !ThumbIP)) {
  6032. errs() << "error: couldn't initialize disassembler for target "
  6033. << ThumbTripleName << '\n';
  6034. return;
  6035. }
  6036. MachO::mach_header Header = MachOOF->getHeader();
  6037. // FIXME: Using the -cfg command line option, this code used to be able to
  6038. // annotate relocations with the referenced symbol's name, and if this was
  6039. // inside a __[cf]string section, the data it points to. This is now replaced
  6040. // by the upcoming MCSymbolizer, which needs the appropriate setup done above.
  6041. std::vector<SectionRef> Sections;
  6042. std::vector<SymbolRef> Symbols;
  6043. SmallVector<uint64_t, 8> FoundFns;
  6044. uint64_t BaseSegmentAddress;
  6045. getSectionsAndSymbols(MachOOF, Sections, Symbols, FoundFns,
  6046. BaseSegmentAddress);
  6047. // Sort the symbols by address, just in case they didn't come in that way.
  6048. std::sort(Symbols.begin(), Symbols.end(), SymbolSorter());
  6049. // Build a data in code table that is sorted on by the address of each entry.
  6050. uint64_t BaseAddress = 0;
  6051. if (Header.filetype == MachO::MH_OBJECT)
  6052. BaseAddress = Sections[0].getAddress();
  6053. else
  6054. BaseAddress = BaseSegmentAddress;
  6055. DiceTable Dices;
  6056. for (dice_iterator DI = MachOOF->begin_dices(), DE = MachOOF->end_dices();
  6057. DI != DE; ++DI) {
  6058. uint32_t Offset;
  6059. DI->getOffset(Offset);
  6060. Dices.push_back(std::make_pair(BaseAddress + Offset, *DI));
  6061. }
  6062. array_pod_sort(Dices.begin(), Dices.end());
  6063. #ifndef NDEBUG
  6064. raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
  6065. #else
  6066. raw_ostream &DebugOut = nulls();
  6067. #endif
  6068. std::unique_ptr<DIContext> diContext;
  6069. ObjectFile *DbgObj = MachOOF;
  6070. // Try to find debug info and set up the DIContext for it.
  6071. if (UseDbg) {
  6072. // A separate DSym file path was specified, parse it as a macho file,
  6073. // get the sections and supply it to the section name parsing machinery.
  6074. if (!DSYMFile.empty()) {
  6075. ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
  6076. MemoryBuffer::getFileOrSTDIN(DSYMFile);
  6077. if (std::error_code EC = BufOrErr.getError()) {
  6078. errs() << "llvm-objdump: " << Filename << ": " << EC.message() << '\n';
  6079. return;
  6080. }
  6081. DbgObj =
  6082. ObjectFile::createMachOObjectFile(BufOrErr.get()->getMemBufferRef())
  6083. .get()
  6084. .release();
  6085. }
  6086. // Setup the DIContext
  6087. diContext.reset(new DWARFContextInMemory(*DbgObj));
  6088. }
  6089. if (FilterSections.size() == 0)
  6090. outs() << "(" << DisSegName << "," << DisSectName << ") section\n";
  6091. for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
  6092. StringRef SectName;
  6093. if (Sections[SectIdx].getName(SectName) || SectName != DisSectName)
  6094. continue;
  6095. DataRefImpl DR = Sections[SectIdx].getRawDataRefImpl();
  6096. StringRef SegmentName = MachOOF->getSectionFinalSegmentName(DR);
  6097. if (SegmentName != DisSegName)
  6098. continue;
  6099. StringRef BytesStr;
  6100. Sections[SectIdx].getContents(BytesStr);
  6101. ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(BytesStr.data()),
  6102. BytesStr.size());
  6103. uint64_t SectAddress = Sections[SectIdx].getAddress();
  6104. bool symbolTableWorked = false;
  6105. // Create a map of symbol addresses to symbol names for use by
  6106. // the SymbolizerSymbolLookUp() routine.
  6107. SymbolAddressMap AddrMap;
  6108. bool DisSymNameFound = false;
  6109. for (const SymbolRef &Symbol : MachOOF->symbols()) {
  6110. Expected<SymbolRef::Type> STOrErr = Symbol.getType();
  6111. if (!STOrErr) {
  6112. std::string Buf;
  6113. raw_string_ostream OS(Buf);
  6114. logAllUnhandledErrors(STOrErr.takeError(), OS, "");
  6115. OS.flush();
  6116. report_fatal_error(Buf);
  6117. }
  6118. SymbolRef::Type ST = *STOrErr;
  6119. if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
  6120. ST == SymbolRef::ST_Other) {
  6121. uint64_t Address = Symbol.getValue();
  6122. Expected<StringRef> SymNameOrErr = Symbol.getName();
  6123. if (!SymNameOrErr) {
  6124. std::string Buf;
  6125. raw_string_ostream OS(Buf);
  6126. logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
  6127. OS.flush();
  6128. report_fatal_error(Buf);
  6129. }
  6130. StringRef SymName = *SymNameOrErr;
  6131. AddrMap[Address] = SymName;
  6132. if (!DisSymName.empty() && DisSymName == SymName)
  6133. DisSymNameFound = true;
  6134. }
  6135. }
  6136. if (!DisSymName.empty() && !DisSymNameFound) {
  6137. outs() << "Can't find -dis-symname: " << DisSymName << "\n";
  6138. return;
  6139. }
  6140. // Set up the block of info used by the Symbolizer call backs.
  6141. SymbolizerInfo.verbose = !NoSymbolicOperands;
  6142. SymbolizerInfo.O = MachOOF;
  6143. SymbolizerInfo.S = Sections[SectIdx];
  6144. SymbolizerInfo.AddrMap = &AddrMap;
  6145. SymbolizerInfo.Sections = &Sections;
  6146. SymbolizerInfo.class_name = nullptr;
  6147. SymbolizerInfo.selector_name = nullptr;
  6148. SymbolizerInfo.method = nullptr;
  6149. SymbolizerInfo.demangled_name = nullptr;
  6150. SymbolizerInfo.bindtable = nullptr;
  6151. SymbolizerInfo.adrp_addr = 0;
  6152. SymbolizerInfo.adrp_inst = 0;
  6153. // Same for the ThumbSymbolizer
  6154. ThumbSymbolizerInfo.verbose = !NoSymbolicOperands;
  6155. ThumbSymbolizerInfo.O = MachOOF;
  6156. ThumbSymbolizerInfo.S = Sections[SectIdx];
  6157. ThumbSymbolizerInfo.AddrMap = &AddrMap;
  6158. ThumbSymbolizerInfo.Sections = &Sections;
  6159. ThumbSymbolizerInfo.class_name = nullptr;
  6160. ThumbSymbolizerInfo.selector_name = nullptr;
  6161. ThumbSymbolizerInfo.method = nullptr;
  6162. ThumbSymbolizerInfo.demangled_name = nullptr;
  6163. ThumbSymbolizerInfo.bindtable = nullptr;
  6164. ThumbSymbolizerInfo.adrp_addr = 0;
  6165. ThumbSymbolizerInfo.adrp_inst = 0;
  6166. unsigned int Arch = MachOOF->getArch();
  6167. // Skip all symbols if this is a stubs file.
  6168. if (Bytes.size() == 0)
  6169. return;
  6170. // Disassemble symbol by symbol.
  6171. for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
  6172. Expected<StringRef> SymNameOrErr = Symbols[SymIdx].getName();
  6173. if (!SymNameOrErr) {
  6174. std::string Buf;
  6175. raw_string_ostream OS(Buf);
  6176. logAllUnhandledErrors(SymNameOrErr.takeError(), OS, "");
  6177. OS.flush();
  6178. report_fatal_error(Buf);
  6179. }
  6180. StringRef SymName = *SymNameOrErr;
  6181. Expected<SymbolRef::Type> STOrErr = Symbols[SymIdx].getType();
  6182. if (!STOrErr) {
  6183. std::string Buf;
  6184. raw_string_ostream OS(Buf);
  6185. logAllUnhandledErrors(STOrErr.takeError(), OS, "");
  6186. OS.flush();
  6187. report_fatal_error(Buf);
  6188. }
  6189. SymbolRef::Type ST = *STOrErr;
  6190. if (ST != SymbolRef::ST_Function && ST != SymbolRef::ST_Data)
  6191. continue;
  6192. // Make sure the symbol is defined in this section.
  6193. bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
  6194. if (!containsSym) {
  6195. if (!DisSymName.empty() && DisSymName == SymName) {
  6196. outs() << "-dis-symname: " << DisSymName << " not in the section\n";
  6197. return;
  6198. }
  6199. continue;
  6200. }
  6201. // The __mh_execute_header is special and we need to deal with that fact
  6202. // this symbol is before the start of the (__TEXT,__text) section and at the
  6203. // address of the start of the __TEXT segment. This is because this symbol
  6204. // is an N_SECT symbol in the (__TEXT,__text) but its address is before the
  6205. // start of the section in a standard MH_EXECUTE filetype.
  6206. if (!DisSymName.empty() && DisSymName == "__mh_execute_header") {
  6207. outs() << "-dis-symname: __mh_execute_header not in any section\n";
  6208. return;
  6209. }
  6210. // When this code is trying to disassemble a symbol at a time and in the
  6211. // case there is only the __mh_execute_header symbol left as in a stripped
  6212. // executable, we need to deal with this by ignoring this symbol so the
  6213. // whole section is disassembled and this symbol is then not displayed.
  6214. if (SymName == "__mh_execute_header" || SymName == "__mh_dylib_header" ||
  6215. SymName == "__mh_bundle_header" || SymName == "__mh_object_header" ||
  6216. SymName == "__mh_preload_header" || SymName == "__mh_dylinker_header")
  6217. continue;
  6218. // If we are only disassembling one symbol see if this is that symbol.
  6219. if (!DisSymName.empty() && DisSymName != SymName)
  6220. continue;
  6221. // Start at the address of the symbol relative to the section's address.
  6222. uint64_t SectSize = Sections[SectIdx].getSize();
  6223. uint64_t Start = Symbols[SymIdx].getValue();
  6224. uint64_t SectionAddress = Sections[SectIdx].getAddress();
  6225. Start -= SectionAddress;
  6226. if (Start > SectSize) {
  6227. outs() << "section data ends, " << SymName
  6228. << " lies outside valid range\n";
  6229. return;
  6230. }
  6231. // Stop disassembling either at the beginning of the next symbol or at
  6232. // the end of the section.
  6233. bool containsNextSym = false;
  6234. uint64_t NextSym = 0;
  6235. uint64_t NextSymIdx = SymIdx + 1;
  6236. while (Symbols.size() > NextSymIdx) {
  6237. Expected<SymbolRef::Type> STOrErr = Symbols[NextSymIdx].getType();
  6238. if (!STOrErr) {
  6239. std::string Buf;
  6240. raw_string_ostream OS(Buf);
  6241. logAllUnhandledErrors(STOrErr.takeError(), OS, "");
  6242. OS.flush();
  6243. report_fatal_error(Buf);
  6244. }
  6245. SymbolRef::Type NextSymType = *STOrErr;
  6246. if (NextSymType == SymbolRef::ST_Function) {
  6247. containsNextSym =
  6248. Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
  6249. NextSym = Symbols[NextSymIdx].getValue();
  6250. NextSym -= SectionAddress;
  6251. break;
  6252. }
  6253. ++NextSymIdx;
  6254. }
  6255. uint64_t End = containsNextSym ? std::min(NextSym, SectSize) : SectSize;
  6256. uint64_t Size;
  6257. symbolTableWorked = true;
  6258. DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
  6259. bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb;
  6260. // We only need the dedicated Thumb target if there's a real choice
  6261. // (i.e. we're not targeting M-class) and the function is Thumb.
  6262. bool UseThumbTarget = IsThumb && ThumbTarget;
  6263. outs() << SymName << ":\n";
  6264. DILineInfo lastLine;
  6265. for (uint64_t Index = Start; Index < End; Index += Size) {
  6266. MCInst Inst;
  6267. uint64_t PC = SectAddress + Index;
  6268. if (!NoLeadingAddr) {
  6269. if (FullLeadingAddr) {
  6270. if (MachOOF->is64Bit())
  6271. outs() << format("%016" PRIx64, PC);
  6272. else
  6273. outs() << format("%08" PRIx64, PC);
  6274. } else {
  6275. outs() << format("%8" PRIx64 ":", PC);
  6276. }
  6277. }
  6278. if (!NoShowRawInsn || Arch == Triple::arm)
  6279. outs() << "\t";
  6280. // Check the data in code table here to see if this is data not an
  6281. // instruction to be disassembled.
  6282. DiceTable Dice;
  6283. Dice.push_back(std::make_pair(PC, DiceRef()));
  6284. dice_table_iterator DTI =
  6285. std::search(Dices.begin(), Dices.end(), Dice.begin(), Dice.end(),
  6286. compareDiceTableEntries);
  6287. if (DTI != Dices.end()) {
  6288. uint16_t Length;
  6289. DTI->second.getLength(Length);
  6290. uint16_t Kind;
  6291. DTI->second.getKind(Kind);
  6292. Size = DumpDataInCode(Bytes.data() + Index, Length, Kind);
  6293. if ((Kind == MachO::DICE_KIND_JUMP_TABLE8) &&
  6294. (PC == (DTI->first + Length - 1)) && (Length & 1))
  6295. Size++;
  6296. continue;
  6297. }
  6298. SmallVector<char, 64> AnnotationsBytes;
  6299. raw_svector_ostream Annotations(AnnotationsBytes);
  6300. bool gotInst;
  6301. if (UseThumbTarget)
  6302. gotInst = ThumbDisAsm->getInstruction(Inst, Size, Bytes.slice(Index),
  6303. PC, DebugOut, Annotations);
  6304. else
  6305. gotInst = DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), PC,
  6306. DebugOut, Annotations);
  6307. if (gotInst) {
  6308. if (!NoShowRawInsn || Arch == Triple::arm) {
  6309. dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
  6310. }
  6311. formatted_raw_ostream FormattedOS(outs());
  6312. StringRef AnnotationsStr = Annotations.str();
  6313. if (UseThumbTarget)
  6314. ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr, *ThumbSTI);
  6315. else
  6316. IP->printInst(&Inst, FormattedOS, AnnotationsStr, *STI);
  6317. emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
  6318. // Print debug info.
  6319. if (diContext) {
  6320. DILineInfo dli = diContext->getLineInfoForAddress(PC);
  6321. // Print valid line info if it changed.
  6322. if (dli != lastLine && dli.Line != 0)
  6323. outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
  6324. << dli.Column;
  6325. lastLine = dli;
  6326. }
  6327. outs() << "\n";
  6328. } else {
  6329. unsigned int Arch = MachOOF->getArch();
  6330. if (Arch == Triple::x86_64 || Arch == Triple::x86) {
  6331. outs() << format("\t.byte 0x%02x #bad opcode\n",
  6332. *(Bytes.data() + Index) & 0xff);
  6333. Size = 1; // skip exactly one illegible byte and move on.
  6334. } else if (Arch == Triple::aarch64 ||
  6335. (Arch == Triple::arm && !IsThumb)) {
  6336. uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
  6337. (*(Bytes.data() + Index + 1) & 0xff) << 8 |
  6338. (*(Bytes.data() + Index + 2) & 0xff) << 16 |
  6339. (*(Bytes.data() + Index + 3) & 0xff) << 24;
  6340. outs() << format("\t.long\t0x%08x\n", opcode);
  6341. Size = 4;
  6342. } else if (Arch == Triple::arm) {
  6343. assert(IsThumb && "ARM mode should have been dealt with above");
  6344. uint32_t opcode = (*(Bytes.data() + Index) & 0xff) |
  6345. (*(Bytes.data() + Index + 1) & 0xff) << 8;
  6346. outs() << format("\t.short\t0x%04x\n", opcode);
  6347. Size = 2;
  6348. } else{
  6349. errs() << "llvm-objdump: warning: invalid instruction encoding\n";
  6350. if (Size == 0)
  6351. Size = 1; // skip illegible bytes
  6352. }
  6353. }
  6354. }
  6355. }
  6356. if (!symbolTableWorked) {
  6357. // Reading the symbol table didn't work, disassemble the whole section.
  6358. uint64_t SectAddress = Sections[SectIdx].getAddress();
  6359. uint64_t SectSize = Sections[SectIdx].getSize();
  6360. uint64_t InstSize;
  6361. for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
  6362. MCInst Inst;
  6363. uint64_t PC = SectAddress + Index;
  6364. if (DisAsm->getInstruction(Inst, InstSize, Bytes.slice(Index), PC,
  6365. DebugOut, nulls())) {
  6366. if (!NoLeadingAddr) {
  6367. if (FullLeadingAddr) {
  6368. if (MachOOF->is64Bit())
  6369. outs() << format("%016" PRIx64, PC);
  6370. else
  6371. outs() << format("%08" PRIx64, PC);
  6372. } else {
  6373. outs() << format("%8" PRIx64 ":", PC);
  6374. }
  6375. }
  6376. if (!NoShowRawInsn || Arch == Triple::arm) {
  6377. outs() << "\t";
  6378. dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
  6379. }
  6380. IP->printInst(&Inst, outs(), "", *STI);
  6381. outs() << "\n";
  6382. } else {
  6383. unsigned int Arch = MachOOF->getArch();
  6384. if (Arch == Triple::x86_64 || Arch == Triple::x86) {
  6385. outs() << format("\t.byte 0x%02x #bad opcode\n",
  6386. *(Bytes.data() + Index) & 0xff);
  6387. InstSize = 1; // skip exactly one illegible byte and move on.
  6388. } else {
  6389. errs() << "llvm-objdump: warning: invalid instruction encoding\n";
  6390. if (InstSize == 0)
  6391. InstSize = 1; // skip illegible bytes
  6392. }
  6393. }
  6394. }
  6395. }
  6396. // The TripleName's need to be reset if we are called again for a different
  6397. // archtecture.
  6398. TripleName = "";
  6399. ThumbTripleName = "";
  6400. if (SymbolizerInfo.method != nullptr)
  6401. free(SymbolizerInfo.method);
  6402. if (SymbolizerInfo.demangled_name != nullptr)
  6403. free(SymbolizerInfo.demangled_name);
  6404. if (SymbolizerInfo.bindtable != nullptr)
  6405. delete SymbolizerInfo.bindtable;
  6406. if (ThumbSymbolizerInfo.method != nullptr)
  6407. free(ThumbSymbolizerInfo.method);
  6408. if (ThumbSymbolizerInfo.demangled_name != nullptr)
  6409. free(ThumbSymbolizerInfo.demangled_name);
  6410. if (ThumbSymbolizerInfo.bindtable != nullptr)
  6411. delete ThumbSymbolizerInfo.bindtable;
  6412. }
  6413. }
  6414. //===----------------------------------------------------------------------===//
  6415. // __compact_unwind section dumping
  6416. //===----------------------------------------------------------------------===//
  6417. namespace {
  6418. template <typename T> static uint64_t readNext(const char *&Buf) {
  6419. using llvm::support::little;
  6420. using llvm::support::unaligned;
  6421. uint64_t Val = support::endian::read<T, little, unaligned>(Buf);
  6422. Buf += sizeof(T);
  6423. return Val;
  6424. }
  6425. struct CompactUnwindEntry {
  6426. uint32_t OffsetInSection;
  6427. uint64_t FunctionAddr;
  6428. uint32_t Length;
  6429. uint32_t CompactEncoding;
  6430. uint64_t PersonalityAddr;
  6431. uint64_t LSDAAddr;
  6432. RelocationRef FunctionReloc;
  6433. RelocationRef PersonalityReloc;
  6434. RelocationRef LSDAReloc;
  6435. CompactUnwindEntry(StringRef Contents, unsigned Offset, bool Is64)
  6436. : OffsetInSection(Offset) {
  6437. if (Is64)
  6438. read<uint64_t>(Contents.data() + Offset);
  6439. else
  6440. read<uint32_t>(Contents.data() + Offset);
  6441. }
  6442. private:
  6443. template <typename UIntPtr> void read(const char *Buf) {
  6444. FunctionAddr = readNext<UIntPtr>(Buf);
  6445. Length = readNext<uint32_t>(Buf);
  6446. CompactEncoding = readNext<uint32_t>(Buf);
  6447. PersonalityAddr = readNext<UIntPtr>(Buf);
  6448. LSDAAddr = readNext<UIntPtr>(Buf);
  6449. }
  6450. };
  6451. }
  6452. /// Given a relocation from __compact_unwind, consisting of the RelocationRef
  6453. /// and data being relocated, determine the best base Name and Addend to use for
  6454. /// display purposes.
  6455. ///
  6456. /// 1. An Extern relocation will directly reference a symbol (and the data is
  6457. /// then already an addend), so use that.
  6458. /// 2. Otherwise the data is an offset in the object file's layout; try to find
  6459. // a symbol before it in the same section, and use the offset from there.
  6460. /// 3. Finally, if all that fails, fall back to an offset from the start of the
  6461. /// referenced section.
  6462. static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
  6463. std::map<uint64_t, SymbolRef> &Symbols,
  6464. const RelocationRef &Reloc, uint64_t Addr,
  6465. StringRef &Name, uint64_t &Addend) {
  6466. if (Reloc.getSymbol() != Obj->symbol_end()) {
  6467. Expected<StringRef> NameOrErr = Reloc.getSymbol()->getName();
  6468. if (!NameOrErr) {
  6469. std::string Buf;
  6470. raw_string_ostream OS(Buf);
  6471. logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
  6472. OS.flush();
  6473. report_fatal_error(Buf);
  6474. }
  6475. Name = *NameOrErr;
  6476. Addend = Addr;
  6477. return;
  6478. }
  6479. auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
  6480. SectionRef RelocSection = Obj->getAnyRelocationSection(RE);
  6481. uint64_t SectionAddr = RelocSection.getAddress();
  6482. auto Sym = Symbols.upper_bound(Addr);
  6483. if (Sym == Symbols.begin()) {
  6484. // The first symbol in the object is after this reference, the best we can
  6485. // do is section-relative notation.
  6486. RelocSection.getName(Name);
  6487. Addend = Addr - SectionAddr;
  6488. return;
  6489. }
  6490. // Go back one so that SymbolAddress <= Addr.
  6491. --Sym;
  6492. auto SectOrErr = Sym->second.getSection();
  6493. if (!SectOrErr) {
  6494. std::string Buf;
  6495. raw_string_ostream OS(Buf);
  6496. logAllUnhandledErrors(SectOrErr.takeError(), OS, "");
  6497. OS.flush();
  6498. report_fatal_error(Buf);
  6499. }
  6500. section_iterator SymSection = *SectOrErr;
  6501. if (RelocSection == *SymSection) {
  6502. // There's a valid symbol in the same section before this reference.
  6503. Expected<StringRef> NameOrErr = Sym->second.getName();
  6504. if (!NameOrErr) {
  6505. std::string Buf;
  6506. raw_string_ostream OS(Buf);
  6507. logAllUnhandledErrors(NameOrErr.takeError(), OS, "");
  6508. OS.flush();
  6509. report_fatal_error(Buf);
  6510. }
  6511. Name = *NameOrErr;
  6512. Addend = Addr - Sym->first;
  6513. return;
  6514. }
  6515. // There is a symbol before this reference, but it's in a different
  6516. // section. Probably not helpful to mention it, so use the section name.
  6517. RelocSection.getName(Name);
  6518. Addend = Addr - SectionAddr;
  6519. }
  6520. static void printUnwindRelocDest(const MachOObjectFile *Obj,
  6521. std::map<uint64_t, SymbolRef> &Symbols,
  6522. const RelocationRef &Reloc, uint64_t Addr) {
  6523. StringRef Name;
  6524. uint64_t Addend;
  6525. if (!Reloc.getObject())
  6526. return;
  6527. findUnwindRelocNameAddend(Obj, Symbols, Reloc, Addr, Name, Addend);
  6528. outs() << Name;
  6529. if (Addend)
  6530. outs() << " + " << format("0x%" PRIx64, Addend);
  6531. }
  6532. static void
  6533. printMachOCompactUnwindSection(const MachOObjectFile *Obj,
  6534. std::map<uint64_t, SymbolRef> &Symbols,
  6535. const SectionRef &CompactUnwind) {
  6536. assert(Obj->isLittleEndian() &&
  6537. "There should not be a big-endian .o with __compact_unwind");
  6538. bool Is64 = Obj->is64Bit();
  6539. uint32_t PointerSize = Is64 ? sizeof(uint64_t) : sizeof(uint32_t);
  6540. uint32_t EntrySize = 3 * PointerSize + 2 * sizeof(uint32_t);
  6541. StringRef Contents;
  6542. CompactUnwind.getContents(Contents);
  6543. SmallVector<CompactUnwindEntry, 4> CompactUnwinds;
  6544. // First populate the initial raw offsets, encodings and so on from the entry.
  6545. for (unsigned Offset = 0; Offset < Contents.size(); Offset += EntrySize) {
  6546. CompactUnwindEntry Entry(Contents.data(), Offset, Is64);
  6547. CompactUnwinds.push_back(Entry);
  6548. }
  6549. // Next we need to look at the relocations to find out what objects are
  6550. // actually being referred to.
  6551. for (const RelocationRef &Reloc : CompactUnwind.relocations()) {
  6552. uint64_t RelocAddress = Reloc.getOffset();
  6553. uint32_t EntryIdx = RelocAddress / EntrySize;
  6554. uint32_t OffsetInEntry = RelocAddress - EntryIdx * EntrySize;
  6555. CompactUnwindEntry &Entry = CompactUnwinds[EntryIdx];
  6556. if (OffsetInEntry == 0)
  6557. Entry.FunctionReloc = Reloc;
  6558. else if (OffsetInEntry == PointerSize + 2 * sizeof(uint32_t))
  6559. Entry.PersonalityReloc = Reloc;
  6560. else if (OffsetInEntry == 2 * PointerSize + 2 * sizeof(uint32_t))
  6561. Entry.LSDAReloc = Reloc;
  6562. else
  6563. llvm_unreachable("Unexpected relocation in __compact_unwind section");
  6564. }
  6565. // Finally, we're ready to print the data we've gathered.
  6566. outs() << "Contents of __compact_unwind section:\n";
  6567. for (auto &Entry : CompactUnwinds) {
  6568. outs() << " Entry at offset "
  6569. << format("0x%" PRIx32, Entry.OffsetInSection) << ":\n";
  6570. // 1. Start of the region this entry applies to.
  6571. outs() << " start: " << format("0x%" PRIx64,
  6572. Entry.FunctionAddr) << ' ';
  6573. printUnwindRelocDest(Obj, Symbols, Entry.FunctionReloc, Entry.FunctionAddr);
  6574. outs() << '\n';
  6575. // 2. Length of the region this entry applies to.
  6576. outs() << " length: " << format("0x%" PRIx32, Entry.Length)
  6577. << '\n';
  6578. // 3. The 32-bit compact encoding.
  6579. outs() << " compact encoding: "
  6580. << format("0x%08" PRIx32, Entry.CompactEncoding) << '\n';
  6581. // 4. The personality function, if present.
  6582. if (Entry.PersonalityReloc.getObject()) {
  6583. outs() << " personality function: "
  6584. << format("0x%" PRIx64, Entry.PersonalityAddr) << ' ';
  6585. printUnwindRelocDest(Obj, Symbols, Entry.PersonalityReloc,
  6586. Entry.PersonalityAddr);
  6587. outs() << '\n';
  6588. }
  6589. // 5. This entry's language-specific data area.
  6590. if (Entry.LSDAReloc.getObject()) {
  6591. outs() << " LSDA: " << format("0x%" PRIx64,
  6592. Entry.LSDAAddr) << ' ';
  6593. printUnwindRelocDest(Obj, Symbols, Entry.LSDAReloc, Entry.LSDAAddr);
  6594. outs() << '\n';
  6595. }
  6596. }
  6597. }
  6598. //===----------------------------------------------------------------------===//
  6599. // __unwind_info section dumping
  6600. //===----------------------------------------------------------------------===//
  6601. static void printRegularSecondLevelUnwindPage(const char *PageStart) {
  6602. const char *Pos = PageStart;
  6603. uint32_t Kind = readNext<uint32_t>(Pos);
  6604. (void)Kind;
  6605. assert(Kind == 2 && "kind for a regular 2nd level index should be 2");
  6606. uint16_t EntriesStart = readNext<uint16_t>(Pos);
  6607. uint16_t NumEntries = readNext<uint16_t>(Pos);
  6608. Pos = PageStart + EntriesStart;
  6609. for (unsigned i = 0; i < NumEntries; ++i) {
  6610. uint32_t FunctionOffset = readNext<uint32_t>(Pos);
  6611. uint32_t Encoding = readNext<uint32_t>(Pos);
  6612. outs() << " [" << i << "]: "
  6613. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6614. << ", "
  6615. << "encoding=" << format("0x%08" PRIx32, Encoding) << '\n';
  6616. }
  6617. }
  6618. static void printCompressedSecondLevelUnwindPage(
  6619. const char *PageStart, uint32_t FunctionBase,
  6620. const SmallVectorImpl<uint32_t> &CommonEncodings) {
  6621. const char *Pos = PageStart;
  6622. uint32_t Kind = readNext<uint32_t>(Pos);
  6623. (void)Kind;
  6624. assert(Kind == 3 && "kind for a compressed 2nd level index should be 3");
  6625. uint16_t EntriesStart = readNext<uint16_t>(Pos);
  6626. uint16_t NumEntries = readNext<uint16_t>(Pos);
  6627. uint16_t EncodingsStart = readNext<uint16_t>(Pos);
  6628. readNext<uint16_t>(Pos);
  6629. const auto *PageEncodings = reinterpret_cast<const support::ulittle32_t *>(
  6630. PageStart + EncodingsStart);
  6631. Pos = PageStart + EntriesStart;
  6632. for (unsigned i = 0; i < NumEntries; ++i) {
  6633. uint32_t Entry = readNext<uint32_t>(Pos);
  6634. uint32_t FunctionOffset = FunctionBase + (Entry & 0xffffff);
  6635. uint32_t EncodingIdx = Entry >> 24;
  6636. uint32_t Encoding;
  6637. if (EncodingIdx < CommonEncodings.size())
  6638. Encoding = CommonEncodings[EncodingIdx];
  6639. else
  6640. Encoding = PageEncodings[EncodingIdx - CommonEncodings.size()];
  6641. outs() << " [" << i << "]: "
  6642. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6643. << ", "
  6644. << "encoding[" << EncodingIdx
  6645. << "]=" << format("0x%08" PRIx32, Encoding) << '\n';
  6646. }
  6647. }
  6648. static void printMachOUnwindInfoSection(const MachOObjectFile *Obj,
  6649. std::map<uint64_t, SymbolRef> &Symbols,
  6650. const SectionRef &UnwindInfo) {
  6651. assert(Obj->isLittleEndian() &&
  6652. "There should not be a big-endian .o with __unwind_info");
  6653. outs() << "Contents of __unwind_info section:\n";
  6654. StringRef Contents;
  6655. UnwindInfo.getContents(Contents);
  6656. const char *Pos = Contents.data();
  6657. //===----------------------------------
  6658. // Section header
  6659. //===----------------------------------
  6660. uint32_t Version = readNext<uint32_t>(Pos);
  6661. outs() << " Version: "
  6662. << format("0x%" PRIx32, Version) << '\n';
  6663. assert(Version == 1 && "only understand version 1");
  6664. uint32_t CommonEncodingsStart = readNext<uint32_t>(Pos);
  6665. outs() << " Common encodings array section offset: "
  6666. << format("0x%" PRIx32, CommonEncodingsStart) << '\n';
  6667. uint32_t NumCommonEncodings = readNext<uint32_t>(Pos);
  6668. outs() << " Number of common encodings in array: "
  6669. << format("0x%" PRIx32, NumCommonEncodings) << '\n';
  6670. uint32_t PersonalitiesStart = readNext<uint32_t>(Pos);
  6671. outs() << " Personality function array section offset: "
  6672. << format("0x%" PRIx32, PersonalitiesStart) << '\n';
  6673. uint32_t NumPersonalities = readNext<uint32_t>(Pos);
  6674. outs() << " Number of personality functions in array: "
  6675. << format("0x%" PRIx32, NumPersonalities) << '\n';
  6676. uint32_t IndicesStart = readNext<uint32_t>(Pos);
  6677. outs() << " Index array section offset: "
  6678. << format("0x%" PRIx32, IndicesStart) << '\n';
  6679. uint32_t NumIndices = readNext<uint32_t>(Pos);
  6680. outs() << " Number of indices in array: "
  6681. << format("0x%" PRIx32, NumIndices) << '\n';
  6682. //===----------------------------------
  6683. // A shared list of common encodings
  6684. //===----------------------------------
  6685. // These occupy indices in the range [0, N] whenever an encoding is referenced
  6686. // from a compressed 2nd level index table. In practice the linker only
  6687. // creates ~128 of these, so that indices are available to embed encodings in
  6688. // the 2nd level index.
  6689. SmallVector<uint32_t, 64> CommonEncodings;
  6690. outs() << " Common encodings: (count = " << NumCommonEncodings << ")\n";
  6691. Pos = Contents.data() + CommonEncodingsStart;
  6692. for (unsigned i = 0; i < NumCommonEncodings; ++i) {
  6693. uint32_t Encoding = readNext<uint32_t>(Pos);
  6694. CommonEncodings.push_back(Encoding);
  6695. outs() << " encoding[" << i << "]: " << format("0x%08" PRIx32, Encoding)
  6696. << '\n';
  6697. }
  6698. //===----------------------------------
  6699. // Personality functions used in this executable
  6700. //===----------------------------------
  6701. // There should be only a handful of these (one per source language,
  6702. // roughly). Particularly since they only get 2 bits in the compact encoding.
  6703. outs() << " Personality functions: (count = " << NumPersonalities << ")\n";
  6704. Pos = Contents.data() + PersonalitiesStart;
  6705. for (unsigned i = 0; i < NumPersonalities; ++i) {
  6706. uint32_t PersonalityFn = readNext<uint32_t>(Pos);
  6707. outs() << " personality[" << i + 1
  6708. << "]: " << format("0x%08" PRIx32, PersonalityFn) << '\n';
  6709. }
  6710. //===----------------------------------
  6711. // The level 1 index entries
  6712. //===----------------------------------
  6713. // These specify an approximate place to start searching for the more detailed
  6714. // information, sorted by PC.
  6715. struct IndexEntry {
  6716. uint32_t FunctionOffset;
  6717. uint32_t SecondLevelPageStart;
  6718. uint32_t LSDAStart;
  6719. };
  6720. SmallVector<IndexEntry, 4> IndexEntries;
  6721. outs() << " Top level indices: (count = " << NumIndices << ")\n";
  6722. Pos = Contents.data() + IndicesStart;
  6723. for (unsigned i = 0; i < NumIndices; ++i) {
  6724. IndexEntry Entry;
  6725. Entry.FunctionOffset = readNext<uint32_t>(Pos);
  6726. Entry.SecondLevelPageStart = readNext<uint32_t>(Pos);
  6727. Entry.LSDAStart = readNext<uint32_t>(Pos);
  6728. IndexEntries.push_back(Entry);
  6729. outs() << " [" << i << "]: "
  6730. << "function offset=" << format("0x%08" PRIx32, Entry.FunctionOffset)
  6731. << ", "
  6732. << "2nd level page offset="
  6733. << format("0x%08" PRIx32, Entry.SecondLevelPageStart) << ", "
  6734. << "LSDA offset=" << format("0x%08" PRIx32, Entry.LSDAStart) << '\n';
  6735. }
  6736. //===----------------------------------
  6737. // Next come the LSDA tables
  6738. //===----------------------------------
  6739. // The LSDA layout is rather implicit: it's a contiguous array of entries from
  6740. // the first top-level index's LSDAOffset to the last (sentinel).
  6741. outs() << " LSDA descriptors:\n";
  6742. Pos = Contents.data() + IndexEntries[0].LSDAStart;
  6743. int NumLSDAs = (IndexEntries.back().LSDAStart - IndexEntries[0].LSDAStart) /
  6744. (2 * sizeof(uint32_t));
  6745. for (int i = 0; i < NumLSDAs; ++i) {
  6746. uint32_t FunctionOffset = readNext<uint32_t>(Pos);
  6747. uint32_t LSDAOffset = readNext<uint32_t>(Pos);
  6748. outs() << " [" << i << "]: "
  6749. << "function offset=" << format("0x%08" PRIx32, FunctionOffset)
  6750. << ", "
  6751. << "LSDA offset=" << format("0x%08" PRIx32, LSDAOffset) << '\n';
  6752. }
  6753. //===----------------------------------
  6754. // Finally, the 2nd level indices
  6755. //===----------------------------------
  6756. // Generally these are 4K in size, and have 2 possible forms:
  6757. // + Regular stores up to 511 entries with disparate encodings
  6758. // + Compressed stores up to 1021 entries if few enough compact encoding
  6759. // values are used.
  6760. outs() << " Second level indices:\n";
  6761. for (unsigned i = 0; i < IndexEntries.size() - 1; ++i) {
  6762. // The final sentinel top-level index has no associated 2nd level page
  6763. if (IndexEntries[i].SecondLevelPageStart == 0)
  6764. break;
  6765. outs() << " Second level index[" << i << "]: "
  6766. << "offset in section="
  6767. << format("0x%08" PRIx32, IndexEntries[i].SecondLevelPageStart)
  6768. << ", "
  6769. << "base function offset="
  6770. << format("0x%08" PRIx32, IndexEntries[i].FunctionOffset) << '\n';
  6771. Pos = Contents.data() + IndexEntries[i].SecondLevelPageStart;
  6772. uint32_t Kind = *reinterpret_cast<const support::ulittle32_t *>(Pos);
  6773. if (Kind == 2)
  6774. printRegularSecondLevelUnwindPage(Pos);
  6775. else if (Kind == 3)
  6776. printCompressedSecondLevelUnwindPage(Pos, IndexEntries[i].FunctionOffset,
  6777. CommonEncodings);
  6778. else
  6779. llvm_unreachable("Do not know how to print this kind of 2nd level page");
  6780. }
  6781. }
  6782. void llvm::printMachOUnwindInfo(const MachOObjectFile *Obj) {
  6783. std::map<uint64_t, SymbolRef> Symbols;
  6784. for (const SymbolRef &SymRef : Obj->symbols()) {
  6785. // Discard any undefined or absolute symbols. They're not going to take part
  6786. // in the convenience lookup for unwind info and just take up resources.
  6787. auto SectOrErr = SymRef.getSection();
  6788. if (!SectOrErr) {
  6789. // TODO: Actually report errors helpfully.
  6790. consumeError(SectOrErr.takeError());
  6791. continue;
  6792. }
  6793. section_iterator Section = *SectOrErr;
  6794. if (Section == Obj->section_end())
  6795. continue;
  6796. uint64_t Addr = SymRef.getValue();
  6797. Symbols.insert(std::make_pair(Addr, SymRef));
  6798. }
  6799. for (const SectionRef &Section : Obj->sections()) {
  6800. StringRef SectName;
  6801. Section.getName(SectName);
  6802. if (SectName == "__compact_unwind")
  6803. printMachOCompactUnwindSection(Obj, Symbols, Section);
  6804. else if (SectName == "__unwind_info")
  6805. printMachOUnwindInfoSection(Obj, Symbols, Section);
  6806. }
  6807. }
  6808. static void PrintMachHeader(uint32_t magic, uint32_t cputype,
  6809. uint32_t cpusubtype, uint32_t filetype,
  6810. uint32_t ncmds, uint32_t sizeofcmds, uint32_t flags,
  6811. bool verbose) {
  6812. outs() << "Mach header\n";
  6813. outs() << " magic cputype cpusubtype caps filetype ncmds "
  6814. "sizeofcmds flags\n";
  6815. if (verbose) {
  6816. if (magic == MachO::MH_MAGIC)
  6817. outs() << " MH_MAGIC";
  6818. else if (magic == MachO::MH_MAGIC_64)
  6819. outs() << "MH_MAGIC_64";
  6820. else
  6821. outs() << format(" 0x%08" PRIx32, magic);
  6822. switch (cputype) {
  6823. case MachO::CPU_TYPE_I386:
  6824. outs() << " I386";
  6825. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6826. case MachO::CPU_SUBTYPE_I386_ALL:
  6827. outs() << " ALL";
  6828. break;
  6829. default:
  6830. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6831. break;
  6832. }
  6833. break;
  6834. case MachO::CPU_TYPE_X86_64:
  6835. outs() << " X86_64";
  6836. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6837. case MachO::CPU_SUBTYPE_X86_64_ALL:
  6838. outs() << " ALL";
  6839. break;
  6840. case MachO::CPU_SUBTYPE_X86_64_H:
  6841. outs() << " Haswell";
  6842. break;
  6843. default:
  6844. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6845. break;
  6846. }
  6847. break;
  6848. case MachO::CPU_TYPE_ARM:
  6849. outs() << " ARM";
  6850. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6851. case MachO::CPU_SUBTYPE_ARM_ALL:
  6852. outs() << " ALL";
  6853. break;
  6854. case MachO::CPU_SUBTYPE_ARM_V4T:
  6855. outs() << " V4T";
  6856. break;
  6857. case MachO::CPU_SUBTYPE_ARM_V5TEJ:
  6858. outs() << " V5TEJ";
  6859. break;
  6860. case MachO::CPU_SUBTYPE_ARM_XSCALE:
  6861. outs() << " XSCALE";
  6862. break;
  6863. case MachO::CPU_SUBTYPE_ARM_V6:
  6864. outs() << " V6";
  6865. break;
  6866. case MachO::CPU_SUBTYPE_ARM_V6M:
  6867. outs() << " V6M";
  6868. break;
  6869. case MachO::CPU_SUBTYPE_ARM_V7:
  6870. outs() << " V7";
  6871. break;
  6872. case MachO::CPU_SUBTYPE_ARM_V7EM:
  6873. outs() << " V7EM";
  6874. break;
  6875. case MachO::CPU_SUBTYPE_ARM_V7K:
  6876. outs() << " V7K";
  6877. break;
  6878. case MachO::CPU_SUBTYPE_ARM_V7M:
  6879. outs() << " V7M";
  6880. break;
  6881. case MachO::CPU_SUBTYPE_ARM_V7S:
  6882. outs() << " V7S";
  6883. break;
  6884. default:
  6885. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6886. break;
  6887. }
  6888. break;
  6889. case MachO::CPU_TYPE_ARM64:
  6890. outs() << " ARM64";
  6891. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6892. case MachO::CPU_SUBTYPE_ARM64_ALL:
  6893. outs() << " ALL";
  6894. break;
  6895. default:
  6896. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6897. break;
  6898. }
  6899. break;
  6900. case MachO::CPU_TYPE_POWERPC:
  6901. outs() << " PPC";
  6902. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6903. case MachO::CPU_SUBTYPE_POWERPC_ALL:
  6904. outs() << " ALL";
  6905. break;
  6906. default:
  6907. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6908. break;
  6909. }
  6910. break;
  6911. case MachO::CPU_TYPE_POWERPC64:
  6912. outs() << " PPC64";
  6913. switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
  6914. case MachO::CPU_SUBTYPE_POWERPC_ALL:
  6915. outs() << " ALL";
  6916. break;
  6917. default:
  6918. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6919. break;
  6920. }
  6921. break;
  6922. default:
  6923. outs() << format(" %7d", cputype);
  6924. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  6925. break;
  6926. }
  6927. if ((cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64) {
  6928. outs() << " LIB64";
  6929. } else {
  6930. outs() << format(" 0x%02" PRIx32,
  6931. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
  6932. }
  6933. switch (filetype) {
  6934. case MachO::MH_OBJECT:
  6935. outs() << " OBJECT";
  6936. break;
  6937. case MachO::MH_EXECUTE:
  6938. outs() << " EXECUTE";
  6939. break;
  6940. case MachO::MH_FVMLIB:
  6941. outs() << " FVMLIB";
  6942. break;
  6943. case MachO::MH_CORE:
  6944. outs() << " CORE";
  6945. break;
  6946. case MachO::MH_PRELOAD:
  6947. outs() << " PRELOAD";
  6948. break;
  6949. case MachO::MH_DYLIB:
  6950. outs() << " DYLIB";
  6951. break;
  6952. case MachO::MH_DYLIB_STUB:
  6953. outs() << " DYLIB_STUB";
  6954. break;
  6955. case MachO::MH_DYLINKER:
  6956. outs() << " DYLINKER";
  6957. break;
  6958. case MachO::MH_BUNDLE:
  6959. outs() << " BUNDLE";
  6960. break;
  6961. case MachO::MH_DSYM:
  6962. outs() << " DSYM";
  6963. break;
  6964. case MachO::MH_KEXT_BUNDLE:
  6965. outs() << " KEXTBUNDLE";
  6966. break;
  6967. default:
  6968. outs() << format(" %10u", filetype);
  6969. break;
  6970. }
  6971. outs() << format(" %5u", ncmds);
  6972. outs() << format(" %10u", sizeofcmds);
  6973. uint32_t f = flags;
  6974. if (f & MachO::MH_NOUNDEFS) {
  6975. outs() << " NOUNDEFS";
  6976. f &= ~MachO::MH_NOUNDEFS;
  6977. }
  6978. if (f & MachO::MH_INCRLINK) {
  6979. outs() << " INCRLINK";
  6980. f &= ~MachO::MH_INCRLINK;
  6981. }
  6982. if (f & MachO::MH_DYLDLINK) {
  6983. outs() << " DYLDLINK";
  6984. f &= ~MachO::MH_DYLDLINK;
  6985. }
  6986. if (f & MachO::MH_BINDATLOAD) {
  6987. outs() << " BINDATLOAD";
  6988. f &= ~MachO::MH_BINDATLOAD;
  6989. }
  6990. if (f & MachO::MH_PREBOUND) {
  6991. outs() << " PREBOUND";
  6992. f &= ~MachO::MH_PREBOUND;
  6993. }
  6994. if (f & MachO::MH_SPLIT_SEGS) {
  6995. outs() << " SPLIT_SEGS";
  6996. f &= ~MachO::MH_SPLIT_SEGS;
  6997. }
  6998. if (f & MachO::MH_LAZY_INIT) {
  6999. outs() << " LAZY_INIT";
  7000. f &= ~MachO::MH_LAZY_INIT;
  7001. }
  7002. if (f & MachO::MH_TWOLEVEL) {
  7003. outs() << " TWOLEVEL";
  7004. f &= ~MachO::MH_TWOLEVEL;
  7005. }
  7006. if (f & MachO::MH_FORCE_FLAT) {
  7007. outs() << " FORCE_FLAT";
  7008. f &= ~MachO::MH_FORCE_FLAT;
  7009. }
  7010. if (f & MachO::MH_NOMULTIDEFS) {
  7011. outs() << " NOMULTIDEFS";
  7012. f &= ~MachO::MH_NOMULTIDEFS;
  7013. }
  7014. if (f & MachO::MH_NOFIXPREBINDING) {
  7015. outs() << " NOFIXPREBINDING";
  7016. f &= ~MachO::MH_NOFIXPREBINDING;
  7017. }
  7018. if (f & MachO::MH_PREBINDABLE) {
  7019. outs() << " PREBINDABLE";
  7020. f &= ~MachO::MH_PREBINDABLE;
  7021. }
  7022. if (f & MachO::MH_ALLMODSBOUND) {
  7023. outs() << " ALLMODSBOUND";
  7024. f &= ~MachO::MH_ALLMODSBOUND;
  7025. }
  7026. if (f & MachO::MH_SUBSECTIONS_VIA_SYMBOLS) {
  7027. outs() << " SUBSECTIONS_VIA_SYMBOLS";
  7028. f &= ~MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
  7029. }
  7030. if (f & MachO::MH_CANONICAL) {
  7031. outs() << " CANONICAL";
  7032. f &= ~MachO::MH_CANONICAL;
  7033. }
  7034. if (f & MachO::MH_WEAK_DEFINES) {
  7035. outs() << " WEAK_DEFINES";
  7036. f &= ~MachO::MH_WEAK_DEFINES;
  7037. }
  7038. if (f & MachO::MH_BINDS_TO_WEAK) {
  7039. outs() << " BINDS_TO_WEAK";
  7040. f &= ~MachO::MH_BINDS_TO_WEAK;
  7041. }
  7042. if (f & MachO::MH_ALLOW_STACK_EXECUTION) {
  7043. outs() << " ALLOW_STACK_EXECUTION";
  7044. f &= ~MachO::MH_ALLOW_STACK_EXECUTION;
  7045. }
  7046. if (f & MachO::MH_DEAD_STRIPPABLE_DYLIB) {
  7047. outs() << " DEAD_STRIPPABLE_DYLIB";
  7048. f &= ~MachO::MH_DEAD_STRIPPABLE_DYLIB;
  7049. }
  7050. if (f & MachO::MH_PIE) {
  7051. outs() << " PIE";
  7052. f &= ~MachO::MH_PIE;
  7053. }
  7054. if (f & MachO::MH_NO_REEXPORTED_DYLIBS) {
  7055. outs() << " NO_REEXPORTED_DYLIBS";
  7056. f &= ~MachO::MH_NO_REEXPORTED_DYLIBS;
  7057. }
  7058. if (f & MachO::MH_HAS_TLV_DESCRIPTORS) {
  7059. outs() << " MH_HAS_TLV_DESCRIPTORS";
  7060. f &= ~MachO::MH_HAS_TLV_DESCRIPTORS;
  7061. }
  7062. if (f & MachO::MH_NO_HEAP_EXECUTION) {
  7063. outs() << " MH_NO_HEAP_EXECUTION";
  7064. f &= ~MachO::MH_NO_HEAP_EXECUTION;
  7065. }
  7066. if (f & MachO::MH_APP_EXTENSION_SAFE) {
  7067. outs() << " APP_EXTENSION_SAFE";
  7068. f &= ~MachO::MH_APP_EXTENSION_SAFE;
  7069. }
  7070. if (f != 0 || flags == 0)
  7071. outs() << format(" 0x%08" PRIx32, f);
  7072. } else {
  7073. outs() << format(" 0x%08" PRIx32, magic);
  7074. outs() << format(" %7d", cputype);
  7075. outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
  7076. outs() << format(" 0x%02" PRIx32,
  7077. (cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24);
  7078. outs() << format(" %10u", filetype);
  7079. outs() << format(" %5u", ncmds);
  7080. outs() << format(" %10u", sizeofcmds);
  7081. outs() << format(" 0x%08" PRIx32, flags);
  7082. }
  7083. outs() << "\n";
  7084. }
  7085. static void PrintSegmentCommand(uint32_t cmd, uint32_t cmdsize,
  7086. StringRef SegName, uint64_t vmaddr,
  7087. uint64_t vmsize, uint64_t fileoff,
  7088. uint64_t filesize, uint32_t maxprot,
  7089. uint32_t initprot, uint32_t nsects,
  7090. uint32_t flags, uint32_t object_size,
  7091. bool verbose) {
  7092. uint64_t expected_cmdsize;
  7093. if (cmd == MachO::LC_SEGMENT) {
  7094. outs() << " cmd LC_SEGMENT\n";
  7095. expected_cmdsize = nsects;
  7096. expected_cmdsize *= sizeof(struct MachO::section);
  7097. expected_cmdsize += sizeof(struct MachO::segment_command);
  7098. } else {
  7099. outs() << " cmd LC_SEGMENT_64\n";
  7100. expected_cmdsize = nsects;
  7101. expected_cmdsize *= sizeof(struct MachO::section_64);
  7102. expected_cmdsize += sizeof(struct MachO::segment_command_64);
  7103. }
  7104. outs() << " cmdsize " << cmdsize;
  7105. if (cmdsize != expected_cmdsize)
  7106. outs() << " Inconsistent size\n";
  7107. else
  7108. outs() << "\n";
  7109. outs() << " segname " << SegName << "\n";
  7110. if (cmd == MachO::LC_SEGMENT_64) {
  7111. outs() << " vmaddr " << format("0x%016" PRIx64, vmaddr) << "\n";
  7112. outs() << " vmsize " << format("0x%016" PRIx64, vmsize) << "\n";
  7113. } else {
  7114. outs() << " vmaddr " << format("0x%08" PRIx64, vmaddr) << "\n";
  7115. outs() << " vmsize " << format("0x%08" PRIx64, vmsize) << "\n";
  7116. }
  7117. outs() << " fileoff " << fileoff;
  7118. if (fileoff > object_size)
  7119. outs() << " (past end of file)\n";
  7120. else
  7121. outs() << "\n";
  7122. outs() << " filesize " << filesize;
  7123. if (fileoff + filesize > object_size)
  7124. outs() << " (past end of file)\n";
  7125. else
  7126. outs() << "\n";
  7127. if (verbose) {
  7128. if ((maxprot &
  7129. ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
  7130. MachO::VM_PROT_EXECUTE)) != 0)
  7131. outs() << " maxprot ?" << format("0x%08" PRIx32, maxprot) << "\n";
  7132. else {
  7133. outs() << " maxprot ";
  7134. outs() << ((maxprot & MachO::VM_PROT_READ) ? "r" : "-");
  7135. outs() << ((maxprot & MachO::VM_PROT_WRITE) ? "w" : "-");
  7136. outs() << ((maxprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
  7137. }
  7138. if ((initprot &
  7139. ~(MachO::VM_PROT_READ | MachO::VM_PROT_WRITE |
  7140. MachO::VM_PROT_EXECUTE)) != 0)
  7141. outs() << " initprot ?" << format("0x%08" PRIx32, initprot) << "\n";
  7142. else {
  7143. outs() << " initprot ";
  7144. outs() << ((initprot & MachO::VM_PROT_READ) ? "r" : "-");
  7145. outs() << ((initprot & MachO::VM_PROT_WRITE) ? "w" : "-");
  7146. outs() << ((initprot & MachO::VM_PROT_EXECUTE) ? "x\n" : "-\n");
  7147. }
  7148. } else {
  7149. outs() << " maxprot " << format("0x%08" PRIx32, maxprot) << "\n";
  7150. outs() << " initprot " << format("0x%08" PRIx32, initprot) << "\n";
  7151. }
  7152. outs() << " nsects " << nsects << "\n";
  7153. if (verbose) {
  7154. outs() << " flags";
  7155. if (flags == 0)
  7156. outs() << " (none)\n";
  7157. else {
  7158. if (flags & MachO::SG_HIGHVM) {
  7159. outs() << " HIGHVM";
  7160. flags &= ~MachO::SG_HIGHVM;
  7161. }
  7162. if (flags & MachO::SG_FVMLIB) {
  7163. outs() << " FVMLIB";
  7164. flags &= ~MachO::SG_FVMLIB;
  7165. }
  7166. if (flags & MachO::SG_NORELOC) {
  7167. outs() << " NORELOC";
  7168. flags &= ~MachO::SG_NORELOC;
  7169. }
  7170. if (flags & MachO::SG_PROTECTED_VERSION_1) {
  7171. outs() << " PROTECTED_VERSION_1";
  7172. flags &= ~MachO::SG_PROTECTED_VERSION_1;
  7173. }
  7174. if (flags)
  7175. outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
  7176. else
  7177. outs() << "\n";
  7178. }
  7179. } else {
  7180. outs() << " flags " << format("0x%" PRIx32, flags) << "\n";
  7181. }
  7182. }
  7183. static void PrintSection(const char *sectname, const char *segname,
  7184. uint64_t addr, uint64_t size, uint32_t offset,
  7185. uint32_t align, uint32_t reloff, uint32_t nreloc,
  7186. uint32_t flags, uint32_t reserved1, uint32_t reserved2,
  7187. uint32_t cmd, const char *sg_segname,
  7188. uint32_t filetype, uint32_t object_size,
  7189. bool verbose) {
  7190. outs() << "Section\n";
  7191. outs() << " sectname " << format("%.16s\n", sectname);
  7192. outs() << " segname " << format("%.16s", segname);
  7193. if (filetype != MachO::MH_OBJECT && strncmp(sg_segname, segname, 16) != 0)
  7194. outs() << " (does not match segment)\n";
  7195. else
  7196. outs() << "\n";
  7197. if (cmd == MachO::LC_SEGMENT_64) {
  7198. outs() << " addr " << format("0x%016" PRIx64, addr) << "\n";
  7199. outs() << " size " << format("0x%016" PRIx64, size);
  7200. } else {
  7201. outs() << " addr " << format("0x%08" PRIx64, addr) << "\n";
  7202. outs() << " size " << format("0x%08" PRIx64, size);
  7203. }
  7204. if ((flags & MachO::S_ZEROFILL) != 0 && offset + size > object_size)
  7205. outs() << " (past end of file)\n";
  7206. else
  7207. outs() << "\n";
  7208. outs() << " offset " << offset;
  7209. if (offset > object_size)
  7210. outs() << " (past end of file)\n";
  7211. else
  7212. outs() << "\n";
  7213. uint32_t align_shifted = 1 << align;
  7214. outs() << " align 2^" << align << " (" << align_shifted << ")\n";
  7215. outs() << " reloff " << reloff;
  7216. if (reloff > object_size)
  7217. outs() << " (past end of file)\n";
  7218. else
  7219. outs() << "\n";
  7220. outs() << " nreloc " << nreloc;
  7221. if (reloff + nreloc * sizeof(struct MachO::relocation_info) > object_size)
  7222. outs() << " (past end of file)\n";
  7223. else
  7224. outs() << "\n";
  7225. uint32_t section_type = flags & MachO::SECTION_TYPE;
  7226. if (verbose) {
  7227. outs() << " type";
  7228. if (section_type == MachO::S_REGULAR)
  7229. outs() << " S_REGULAR\n";
  7230. else if (section_type == MachO::S_ZEROFILL)
  7231. outs() << " S_ZEROFILL\n";
  7232. else if (section_type == MachO::S_CSTRING_LITERALS)
  7233. outs() << " S_CSTRING_LITERALS\n";
  7234. else if (section_type == MachO::S_4BYTE_LITERALS)
  7235. outs() << " S_4BYTE_LITERALS\n";
  7236. else if (section_type == MachO::S_8BYTE_LITERALS)
  7237. outs() << " S_8BYTE_LITERALS\n";
  7238. else if (section_type == MachO::S_16BYTE_LITERALS)
  7239. outs() << " S_16BYTE_LITERALS\n";
  7240. else if (section_type == MachO::S_LITERAL_POINTERS)
  7241. outs() << " S_LITERAL_POINTERS\n";
  7242. else if (section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS)
  7243. outs() << " S_NON_LAZY_SYMBOL_POINTERS\n";
  7244. else if (section_type == MachO::S_LAZY_SYMBOL_POINTERS)
  7245. outs() << " S_LAZY_SYMBOL_POINTERS\n";
  7246. else if (section_type == MachO::S_SYMBOL_STUBS)
  7247. outs() << " S_SYMBOL_STUBS\n";
  7248. else if (section_type == MachO::S_MOD_INIT_FUNC_POINTERS)
  7249. outs() << " S_MOD_INIT_FUNC_POINTERS\n";
  7250. else if (section_type == MachO::S_MOD_TERM_FUNC_POINTERS)
  7251. outs() << " S_MOD_TERM_FUNC_POINTERS\n";
  7252. else if (section_type == MachO::S_COALESCED)
  7253. outs() << " S_COALESCED\n";
  7254. else if (section_type == MachO::S_INTERPOSING)
  7255. outs() << " S_INTERPOSING\n";
  7256. else if (section_type == MachO::S_DTRACE_DOF)
  7257. outs() << " S_DTRACE_DOF\n";
  7258. else if (section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS)
  7259. outs() << " S_LAZY_DYLIB_SYMBOL_POINTERS\n";
  7260. else if (section_type == MachO::S_THREAD_LOCAL_REGULAR)
  7261. outs() << " S_THREAD_LOCAL_REGULAR\n";
  7262. else if (section_type == MachO::S_THREAD_LOCAL_ZEROFILL)
  7263. outs() << " S_THREAD_LOCAL_ZEROFILL\n";
  7264. else if (section_type == MachO::S_THREAD_LOCAL_VARIABLES)
  7265. outs() << " S_THREAD_LOCAL_VARIABLES\n";
  7266. else if (section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
  7267. outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
  7268. else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
  7269. outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
  7270. else
  7271. outs() << format("0x%08" PRIx32, section_type) << "\n";
  7272. outs() << "attributes";
  7273. uint32_t section_attributes = flags & MachO::SECTION_ATTRIBUTES;
  7274. if (section_attributes & MachO::S_ATTR_PURE_INSTRUCTIONS)
  7275. outs() << " PURE_INSTRUCTIONS";
  7276. if (section_attributes & MachO::S_ATTR_NO_TOC)
  7277. outs() << " NO_TOC";
  7278. if (section_attributes & MachO::S_ATTR_STRIP_STATIC_SYMS)
  7279. outs() << " STRIP_STATIC_SYMS";
  7280. if (section_attributes & MachO::S_ATTR_NO_DEAD_STRIP)
  7281. outs() << " NO_DEAD_STRIP";
  7282. if (section_attributes & MachO::S_ATTR_LIVE_SUPPORT)
  7283. outs() << " LIVE_SUPPORT";
  7284. if (section_attributes & MachO::S_ATTR_SELF_MODIFYING_CODE)
  7285. outs() << " SELF_MODIFYING_CODE";
  7286. if (section_attributes & MachO::S_ATTR_DEBUG)
  7287. outs() << " DEBUG";
  7288. if (section_attributes & MachO::S_ATTR_SOME_INSTRUCTIONS)
  7289. outs() << " SOME_INSTRUCTIONS";
  7290. if (section_attributes & MachO::S_ATTR_EXT_RELOC)
  7291. outs() << " EXT_RELOC";
  7292. if (section_attributes & MachO::S_ATTR_LOC_RELOC)
  7293. outs() << " LOC_RELOC";
  7294. if (section_attributes == 0)
  7295. outs() << " (none)";
  7296. outs() << "\n";
  7297. } else
  7298. outs() << " flags " << format("0x%08" PRIx32, flags) << "\n";
  7299. outs() << " reserved1 " << reserved1;
  7300. if (section_type == MachO::S_SYMBOL_STUBS ||
  7301. section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
  7302. section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
  7303. section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
  7304. section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
  7305. outs() << " (index into indirect symbol table)\n";
  7306. else
  7307. outs() << "\n";
  7308. outs() << " reserved2 " << reserved2;
  7309. if (section_type == MachO::S_SYMBOL_STUBS)
  7310. outs() << " (size of stubs)\n";
  7311. else
  7312. outs() << "\n";
  7313. }
  7314. static void PrintSymtabLoadCommand(MachO::symtab_command st, bool Is64Bit,
  7315. uint32_t object_size) {
  7316. outs() << " cmd LC_SYMTAB\n";
  7317. outs() << " cmdsize " << st.cmdsize;
  7318. if (st.cmdsize != sizeof(struct MachO::symtab_command))
  7319. outs() << " Incorrect size\n";
  7320. else
  7321. outs() << "\n";
  7322. outs() << " symoff " << st.symoff;
  7323. if (st.symoff > object_size)
  7324. outs() << " (past end of file)\n";
  7325. else
  7326. outs() << "\n";
  7327. outs() << " nsyms " << st.nsyms;
  7328. uint64_t big_size;
  7329. if (Is64Bit) {
  7330. big_size = st.nsyms;
  7331. big_size *= sizeof(struct MachO::nlist_64);
  7332. big_size += st.symoff;
  7333. if (big_size > object_size)
  7334. outs() << " (past end of file)\n";
  7335. else
  7336. outs() << "\n";
  7337. } else {
  7338. big_size = st.nsyms;
  7339. big_size *= sizeof(struct MachO::nlist);
  7340. big_size += st.symoff;
  7341. if (big_size > object_size)
  7342. outs() << " (past end of file)\n";
  7343. else
  7344. outs() << "\n";
  7345. }
  7346. outs() << " stroff " << st.stroff;
  7347. if (st.stroff > object_size)
  7348. outs() << " (past end of file)\n";
  7349. else
  7350. outs() << "\n";
  7351. outs() << " strsize " << st.strsize;
  7352. big_size = st.stroff;
  7353. big_size += st.strsize;
  7354. if (big_size > object_size)
  7355. outs() << " (past end of file)\n";
  7356. else
  7357. outs() << "\n";
  7358. }
  7359. static void PrintDysymtabLoadCommand(MachO::dysymtab_command dyst,
  7360. uint32_t nsyms, uint32_t object_size,
  7361. bool Is64Bit) {
  7362. outs() << " cmd LC_DYSYMTAB\n";
  7363. outs() << " cmdsize " << dyst.cmdsize;
  7364. if (dyst.cmdsize != sizeof(struct MachO::dysymtab_command))
  7365. outs() << " Incorrect size\n";
  7366. else
  7367. outs() << "\n";
  7368. outs() << " ilocalsym " << dyst.ilocalsym;
  7369. if (dyst.ilocalsym > nsyms)
  7370. outs() << " (greater than the number of symbols)\n";
  7371. else
  7372. outs() << "\n";
  7373. outs() << " nlocalsym " << dyst.nlocalsym;
  7374. uint64_t big_size;
  7375. big_size = dyst.ilocalsym;
  7376. big_size += dyst.nlocalsym;
  7377. if (big_size > nsyms)
  7378. outs() << " (past the end of the symbol table)\n";
  7379. else
  7380. outs() << "\n";
  7381. outs() << " iextdefsym " << dyst.iextdefsym;
  7382. if (dyst.iextdefsym > nsyms)
  7383. outs() << " (greater than the number of symbols)\n";
  7384. else
  7385. outs() << "\n";
  7386. outs() << " nextdefsym " << dyst.nextdefsym;
  7387. big_size = dyst.iextdefsym;
  7388. big_size += dyst.nextdefsym;
  7389. if (big_size > nsyms)
  7390. outs() << " (past the end of the symbol table)\n";
  7391. else
  7392. outs() << "\n";
  7393. outs() << " iundefsym " << dyst.iundefsym;
  7394. if (dyst.iundefsym > nsyms)
  7395. outs() << " (greater than the number of symbols)\n";
  7396. else
  7397. outs() << "\n";
  7398. outs() << " nundefsym " << dyst.nundefsym;
  7399. big_size = dyst.iundefsym;
  7400. big_size += dyst.nundefsym;
  7401. if (big_size > nsyms)
  7402. outs() << " (past the end of the symbol table)\n";
  7403. else
  7404. outs() << "\n";
  7405. outs() << " tocoff " << dyst.tocoff;
  7406. if (dyst.tocoff > object_size)
  7407. outs() << " (past end of file)\n";
  7408. else
  7409. outs() << "\n";
  7410. outs() << " ntoc " << dyst.ntoc;
  7411. big_size = dyst.ntoc;
  7412. big_size *= sizeof(struct MachO::dylib_table_of_contents);
  7413. big_size += dyst.tocoff;
  7414. if (big_size > object_size)
  7415. outs() << " (past end of file)\n";
  7416. else
  7417. outs() << "\n";
  7418. outs() << " modtaboff " << dyst.modtaboff;
  7419. if (dyst.modtaboff > object_size)
  7420. outs() << " (past end of file)\n";
  7421. else
  7422. outs() << "\n";
  7423. outs() << " nmodtab " << dyst.nmodtab;
  7424. uint64_t modtabend;
  7425. if (Is64Bit) {
  7426. modtabend = dyst.nmodtab;
  7427. modtabend *= sizeof(struct MachO::dylib_module_64);
  7428. modtabend += dyst.modtaboff;
  7429. } else {
  7430. modtabend = dyst.nmodtab;
  7431. modtabend *= sizeof(struct MachO::dylib_module);
  7432. modtabend += dyst.modtaboff;
  7433. }
  7434. if (modtabend > object_size)
  7435. outs() << " (past end of file)\n";
  7436. else
  7437. outs() << "\n";
  7438. outs() << " extrefsymoff " << dyst.extrefsymoff;
  7439. if (dyst.extrefsymoff > object_size)
  7440. outs() << " (past end of file)\n";
  7441. else
  7442. outs() << "\n";
  7443. outs() << " nextrefsyms " << dyst.nextrefsyms;
  7444. big_size = dyst.nextrefsyms;
  7445. big_size *= sizeof(struct MachO::dylib_reference);
  7446. big_size += dyst.extrefsymoff;
  7447. if (big_size > object_size)
  7448. outs() << " (past end of file)\n";
  7449. else
  7450. outs() << "\n";
  7451. outs() << " indirectsymoff " << dyst.indirectsymoff;
  7452. if (dyst.indirectsymoff > object_size)
  7453. outs() << " (past end of file)\n";
  7454. else
  7455. outs() << "\n";
  7456. outs() << " nindirectsyms " << dyst.nindirectsyms;
  7457. big_size = dyst.nindirectsyms;
  7458. big_size *= sizeof(uint32_t);
  7459. big_size += dyst.indirectsymoff;
  7460. if (big_size > object_size)
  7461. outs() << " (past end of file)\n";
  7462. else
  7463. outs() << "\n";
  7464. outs() << " extreloff " << dyst.extreloff;
  7465. if (dyst.extreloff > object_size)
  7466. outs() << " (past end of file)\n";
  7467. else
  7468. outs() << "\n";
  7469. outs() << " nextrel " << dyst.nextrel;
  7470. big_size = dyst.nextrel;
  7471. big_size *= sizeof(struct MachO::relocation_info);
  7472. big_size += dyst.extreloff;
  7473. if (big_size > object_size)
  7474. outs() << " (past end of file)\n";
  7475. else
  7476. outs() << "\n";
  7477. outs() << " locreloff " << dyst.locreloff;
  7478. if (dyst.locreloff > object_size)
  7479. outs() << " (past end of file)\n";
  7480. else
  7481. outs() << "\n";
  7482. outs() << " nlocrel " << dyst.nlocrel;
  7483. big_size = dyst.nlocrel;
  7484. big_size *= sizeof(struct MachO::relocation_info);
  7485. big_size += dyst.locreloff;
  7486. if (big_size > object_size)
  7487. outs() << " (past end of file)\n";
  7488. else
  7489. outs() << "\n";
  7490. }
  7491. static void PrintDyldInfoLoadCommand(MachO::dyld_info_command dc,
  7492. uint32_t object_size) {
  7493. if (dc.cmd == MachO::LC_DYLD_INFO)
  7494. outs() << " cmd LC_DYLD_INFO\n";
  7495. else
  7496. outs() << " cmd LC_DYLD_INFO_ONLY\n";
  7497. outs() << " cmdsize " << dc.cmdsize;
  7498. if (dc.cmdsize != sizeof(struct MachO::dyld_info_command))
  7499. outs() << " Incorrect size\n";
  7500. else
  7501. outs() << "\n";
  7502. outs() << " rebase_off " << dc.rebase_off;
  7503. if (dc.rebase_off > object_size)
  7504. outs() << " (past end of file)\n";
  7505. else
  7506. outs() << "\n";
  7507. outs() << " rebase_size " << dc.rebase_size;
  7508. uint64_t big_size;
  7509. big_size = dc.rebase_off;
  7510. big_size += dc.rebase_size;
  7511. if (big_size > object_size)
  7512. outs() << " (past end of file)\n";
  7513. else
  7514. outs() << "\n";
  7515. outs() << " bind_off " << dc.bind_off;
  7516. if (dc.bind_off > object_size)
  7517. outs() << " (past end of file)\n";
  7518. else
  7519. outs() << "\n";
  7520. outs() << " bind_size " << dc.bind_size;
  7521. big_size = dc.bind_off;
  7522. big_size += dc.bind_size;
  7523. if (big_size > object_size)
  7524. outs() << " (past end of file)\n";
  7525. else
  7526. outs() << "\n";
  7527. outs() << " weak_bind_off " << dc.weak_bind_off;
  7528. if (dc.weak_bind_off > object_size)
  7529. outs() << " (past end of file)\n";
  7530. else
  7531. outs() << "\n";
  7532. outs() << " weak_bind_size " << dc.weak_bind_size;
  7533. big_size = dc.weak_bind_off;
  7534. big_size += dc.weak_bind_size;
  7535. if (big_size > object_size)
  7536. outs() << " (past end of file)\n";
  7537. else
  7538. outs() << "\n";
  7539. outs() << " lazy_bind_off " << dc.lazy_bind_off;
  7540. if (dc.lazy_bind_off > object_size)
  7541. outs() << " (past end of file)\n";
  7542. else
  7543. outs() << "\n";
  7544. outs() << " lazy_bind_size " << dc.lazy_bind_size;
  7545. big_size = dc.lazy_bind_off;
  7546. big_size += dc.lazy_bind_size;
  7547. if (big_size > object_size)
  7548. outs() << " (past end of file)\n";
  7549. else
  7550. outs() << "\n";
  7551. outs() << " export_off " << dc.export_off;
  7552. if (dc.export_off > object_size)
  7553. outs() << " (past end of file)\n";
  7554. else
  7555. outs() << "\n";
  7556. outs() << " export_size " << dc.export_size;
  7557. big_size = dc.export_off;
  7558. big_size += dc.export_size;
  7559. if (big_size > object_size)
  7560. outs() << " (past end of file)\n";
  7561. else
  7562. outs() << "\n";
  7563. }
  7564. static void PrintDyldLoadCommand(MachO::dylinker_command dyld,
  7565. const char *Ptr) {
  7566. if (dyld.cmd == MachO::LC_ID_DYLINKER)
  7567. outs() << " cmd LC_ID_DYLINKER\n";
  7568. else if (dyld.cmd == MachO::LC_LOAD_DYLINKER)
  7569. outs() << " cmd LC_LOAD_DYLINKER\n";
  7570. else if (dyld.cmd == MachO::LC_DYLD_ENVIRONMENT)
  7571. outs() << " cmd LC_DYLD_ENVIRONMENT\n";
  7572. else
  7573. outs() << " cmd ?(" << dyld.cmd << ")\n";
  7574. outs() << " cmdsize " << dyld.cmdsize;
  7575. if (dyld.cmdsize < sizeof(struct MachO::dylinker_command))
  7576. outs() << " Incorrect size\n";
  7577. else
  7578. outs() << "\n";
  7579. if (dyld.name >= dyld.cmdsize)
  7580. outs() << " name ?(bad offset " << dyld.name << ")\n";
  7581. else {
  7582. const char *P = (const char *)(Ptr) + dyld.name;
  7583. outs() << " name " << P << " (offset " << dyld.name << ")\n";
  7584. }
  7585. }
  7586. static void PrintUuidLoadCommand(MachO::uuid_command uuid) {
  7587. outs() << " cmd LC_UUID\n";
  7588. outs() << " cmdsize " << uuid.cmdsize;
  7589. if (uuid.cmdsize != sizeof(struct MachO::uuid_command))
  7590. outs() << " Incorrect size\n";
  7591. else
  7592. outs() << "\n";
  7593. outs() << " uuid ";
  7594. for (int i = 0; i < 16; ++i) {
  7595. outs() << format("%02" PRIX32, uuid.uuid[i]);
  7596. if (i == 3 || i == 5 || i == 7 || i == 9)
  7597. outs() << "-";
  7598. }
  7599. outs() << "\n";
  7600. }
  7601. static void PrintRpathLoadCommand(MachO::rpath_command rpath, const char *Ptr) {
  7602. outs() << " cmd LC_RPATH\n";
  7603. outs() << " cmdsize " << rpath.cmdsize;
  7604. if (rpath.cmdsize < sizeof(struct MachO::rpath_command))
  7605. outs() << " Incorrect size\n";
  7606. else
  7607. outs() << "\n";
  7608. if (rpath.path >= rpath.cmdsize)
  7609. outs() << " path ?(bad offset " << rpath.path << ")\n";
  7610. else {
  7611. const char *P = (const char *)(Ptr) + rpath.path;
  7612. outs() << " path " << P << " (offset " << rpath.path << ")\n";
  7613. }
  7614. }
  7615. static void PrintVersionMinLoadCommand(MachO::version_min_command vd) {
  7616. StringRef LoadCmdName;
  7617. switch (vd.cmd) {
  7618. case MachO::LC_VERSION_MIN_MACOSX:
  7619. LoadCmdName = "LC_VERSION_MIN_MACOSX";
  7620. break;
  7621. case MachO::LC_VERSION_MIN_IPHONEOS:
  7622. LoadCmdName = "LC_VERSION_MIN_IPHONEOS";
  7623. break;
  7624. case MachO::LC_VERSION_MIN_TVOS:
  7625. LoadCmdName = "LC_VERSION_MIN_TVOS";
  7626. break;
  7627. case MachO::LC_VERSION_MIN_WATCHOS:
  7628. LoadCmdName = "LC_VERSION_MIN_WATCHOS";
  7629. break;
  7630. default:
  7631. llvm_unreachable("Unknown version min load command");
  7632. }
  7633. outs() << " cmd " << LoadCmdName << '\n';
  7634. outs() << " cmdsize " << vd.cmdsize;
  7635. if (vd.cmdsize != sizeof(struct MachO::version_min_command))
  7636. outs() << " Incorrect size\n";
  7637. else
  7638. outs() << "\n";
  7639. outs() << " version "
  7640. << MachOObjectFile::getVersionMinMajor(vd, false) << "."
  7641. << MachOObjectFile::getVersionMinMinor(vd, false);
  7642. uint32_t Update = MachOObjectFile::getVersionMinUpdate(vd, false);
  7643. if (Update != 0)
  7644. outs() << "." << Update;
  7645. outs() << "\n";
  7646. if (vd.sdk == 0)
  7647. outs() << " sdk n/a";
  7648. else {
  7649. outs() << " sdk "
  7650. << MachOObjectFile::getVersionMinMajor(vd, true) << "."
  7651. << MachOObjectFile::getVersionMinMinor(vd, true);
  7652. }
  7653. Update = MachOObjectFile::getVersionMinUpdate(vd, true);
  7654. if (Update != 0)
  7655. outs() << "." << Update;
  7656. outs() << "\n";
  7657. }
  7658. static void PrintSourceVersionCommand(MachO::source_version_command sd) {
  7659. outs() << " cmd LC_SOURCE_VERSION\n";
  7660. outs() << " cmdsize " << sd.cmdsize;
  7661. if (sd.cmdsize != sizeof(struct MachO::source_version_command))
  7662. outs() << " Incorrect size\n";
  7663. else
  7664. outs() << "\n";
  7665. uint64_t a = (sd.version >> 40) & 0xffffff;
  7666. uint64_t b = (sd.version >> 30) & 0x3ff;
  7667. uint64_t c = (sd.version >> 20) & 0x3ff;
  7668. uint64_t d = (sd.version >> 10) & 0x3ff;
  7669. uint64_t e = sd.version & 0x3ff;
  7670. outs() << " version " << a << "." << b;
  7671. if (e != 0)
  7672. outs() << "." << c << "." << d << "." << e;
  7673. else if (d != 0)
  7674. outs() << "." << c << "." << d;
  7675. else if (c != 0)
  7676. outs() << "." << c;
  7677. outs() << "\n";
  7678. }
  7679. static void PrintEntryPointCommand(MachO::entry_point_command ep) {
  7680. outs() << " cmd LC_MAIN\n";
  7681. outs() << " cmdsize " << ep.cmdsize;
  7682. if (ep.cmdsize != sizeof(struct MachO::entry_point_command))
  7683. outs() << " Incorrect size\n";
  7684. else
  7685. outs() << "\n";
  7686. outs() << " entryoff " << ep.entryoff << "\n";
  7687. outs() << " stacksize " << ep.stacksize << "\n";
  7688. }
  7689. static void PrintEncryptionInfoCommand(MachO::encryption_info_command ec,
  7690. uint32_t object_size) {
  7691. outs() << " cmd LC_ENCRYPTION_INFO\n";
  7692. outs() << " cmdsize " << ec.cmdsize;
  7693. if (ec.cmdsize != sizeof(struct MachO::encryption_info_command))
  7694. outs() << " Incorrect size\n";
  7695. else
  7696. outs() << "\n";
  7697. outs() << " cryptoff " << ec.cryptoff;
  7698. if (ec.cryptoff > object_size)
  7699. outs() << " (past end of file)\n";
  7700. else
  7701. outs() << "\n";
  7702. outs() << " cryptsize " << ec.cryptsize;
  7703. if (ec.cryptsize > object_size)
  7704. outs() << " (past end of file)\n";
  7705. else
  7706. outs() << "\n";
  7707. outs() << " cryptid " << ec.cryptid << "\n";
  7708. }
  7709. static void PrintEncryptionInfoCommand64(MachO::encryption_info_command_64 ec,
  7710. uint32_t object_size) {
  7711. outs() << " cmd LC_ENCRYPTION_INFO_64\n";
  7712. outs() << " cmdsize " << ec.cmdsize;
  7713. if (ec.cmdsize != sizeof(struct MachO::encryption_info_command_64))
  7714. outs() << " Incorrect size\n";
  7715. else
  7716. outs() << "\n";
  7717. outs() << " cryptoff " << ec.cryptoff;
  7718. if (ec.cryptoff > object_size)
  7719. outs() << " (past end of file)\n";
  7720. else
  7721. outs() << "\n";
  7722. outs() << " cryptsize " << ec.cryptsize;
  7723. if (ec.cryptsize > object_size)
  7724. outs() << " (past end of file)\n";
  7725. else
  7726. outs() << "\n";
  7727. outs() << " cryptid " << ec.cryptid << "\n";
  7728. outs() << " pad " << ec.pad << "\n";
  7729. }
  7730. static void PrintLinkerOptionCommand(MachO::linker_option_command lo,
  7731. const char *Ptr) {
  7732. outs() << " cmd LC_LINKER_OPTION\n";
  7733. outs() << " cmdsize " << lo.cmdsize;
  7734. if (lo.cmdsize < sizeof(struct MachO::linker_option_command))
  7735. outs() << " Incorrect size\n";
  7736. else
  7737. outs() << "\n";
  7738. outs() << " count " << lo.count << "\n";
  7739. const char *string = Ptr + sizeof(struct MachO::linker_option_command);
  7740. uint32_t left = lo.cmdsize - sizeof(struct MachO::linker_option_command);
  7741. uint32_t i = 0;
  7742. while (left > 0) {
  7743. while (*string == '\0' && left > 0) {
  7744. string++;
  7745. left--;
  7746. }
  7747. if (left > 0) {
  7748. i++;
  7749. outs() << " string #" << i << " " << format("%.*s\n", left, string);
  7750. uint32_t NullPos = StringRef(string, left).find('\0');
  7751. uint32_t len = std::min(NullPos, left) + 1;
  7752. string += len;
  7753. left -= len;
  7754. }
  7755. }
  7756. if (lo.count != i)
  7757. outs() << " count " << lo.count << " does not match number of strings "
  7758. << i << "\n";
  7759. }
  7760. static void PrintSubFrameworkCommand(MachO::sub_framework_command sub,
  7761. const char *Ptr) {
  7762. outs() << " cmd LC_SUB_FRAMEWORK\n";
  7763. outs() << " cmdsize " << sub.cmdsize;
  7764. if (sub.cmdsize < sizeof(struct MachO::sub_framework_command))
  7765. outs() << " Incorrect size\n";
  7766. else
  7767. outs() << "\n";
  7768. if (sub.umbrella < sub.cmdsize) {
  7769. const char *P = Ptr + sub.umbrella;
  7770. outs() << " umbrella " << P << " (offset " << sub.umbrella << ")\n";
  7771. } else {
  7772. outs() << " umbrella ?(bad offset " << sub.umbrella << ")\n";
  7773. }
  7774. }
  7775. static void PrintSubUmbrellaCommand(MachO::sub_umbrella_command sub,
  7776. const char *Ptr) {
  7777. outs() << " cmd LC_SUB_UMBRELLA\n";
  7778. outs() << " cmdsize " << sub.cmdsize;
  7779. if (sub.cmdsize < sizeof(struct MachO::sub_umbrella_command))
  7780. outs() << " Incorrect size\n";
  7781. else
  7782. outs() << "\n";
  7783. if (sub.sub_umbrella < sub.cmdsize) {
  7784. const char *P = Ptr + sub.sub_umbrella;
  7785. outs() << " sub_umbrella " << P << " (offset " << sub.sub_umbrella << ")\n";
  7786. } else {
  7787. outs() << " sub_umbrella ?(bad offset " << sub.sub_umbrella << ")\n";
  7788. }
  7789. }
  7790. static void PrintSubLibraryCommand(MachO::sub_library_command sub,
  7791. const char *Ptr) {
  7792. outs() << " cmd LC_SUB_LIBRARY\n";
  7793. outs() << " cmdsize " << sub.cmdsize;
  7794. if (sub.cmdsize < sizeof(struct MachO::sub_library_command))
  7795. outs() << " Incorrect size\n";
  7796. else
  7797. outs() << "\n";
  7798. if (sub.sub_library < sub.cmdsize) {
  7799. const char *P = Ptr + sub.sub_library;
  7800. outs() << " sub_library " << P << " (offset " << sub.sub_library << ")\n";
  7801. } else {
  7802. outs() << " sub_library ?(bad offset " << sub.sub_library << ")\n";
  7803. }
  7804. }
  7805. static void PrintSubClientCommand(MachO::sub_client_command sub,
  7806. const char *Ptr) {
  7807. outs() << " cmd LC_SUB_CLIENT\n";
  7808. outs() << " cmdsize " << sub.cmdsize;
  7809. if (sub.cmdsize < sizeof(struct MachO::sub_client_command))
  7810. outs() << " Incorrect size\n";
  7811. else
  7812. outs() << "\n";
  7813. if (sub.client < sub.cmdsize) {
  7814. const char *P = Ptr + sub.client;
  7815. outs() << " client " << P << " (offset " << sub.client << ")\n";
  7816. } else {
  7817. outs() << " client ?(bad offset " << sub.client << ")\n";
  7818. }
  7819. }
  7820. static void PrintRoutinesCommand(MachO::routines_command r) {
  7821. outs() << " cmd LC_ROUTINES\n";
  7822. outs() << " cmdsize " << r.cmdsize;
  7823. if (r.cmdsize != sizeof(struct MachO::routines_command))
  7824. outs() << " Incorrect size\n";
  7825. else
  7826. outs() << "\n";
  7827. outs() << " init_address " << format("0x%08" PRIx32, r.init_address) << "\n";
  7828. outs() << " init_module " << r.init_module << "\n";
  7829. outs() << " reserved1 " << r.reserved1 << "\n";
  7830. outs() << " reserved2 " << r.reserved2 << "\n";
  7831. outs() << " reserved3 " << r.reserved3 << "\n";
  7832. outs() << " reserved4 " << r.reserved4 << "\n";
  7833. outs() << " reserved5 " << r.reserved5 << "\n";
  7834. outs() << " reserved6 " << r.reserved6 << "\n";
  7835. }
  7836. static void PrintRoutinesCommand64(MachO::routines_command_64 r) {
  7837. outs() << " cmd LC_ROUTINES_64\n";
  7838. outs() << " cmdsize " << r.cmdsize;
  7839. if (r.cmdsize != sizeof(struct MachO::routines_command_64))
  7840. outs() << " Incorrect size\n";
  7841. else
  7842. outs() << "\n";
  7843. outs() << " init_address " << format("0x%016" PRIx64, r.init_address) << "\n";
  7844. outs() << " init_module " << r.init_module << "\n";
  7845. outs() << " reserved1 " << r.reserved1 << "\n";
  7846. outs() << " reserved2 " << r.reserved2 << "\n";
  7847. outs() << " reserved3 " << r.reserved3 << "\n";
  7848. outs() << " reserved4 " << r.reserved4 << "\n";
  7849. outs() << " reserved5 " << r.reserved5 << "\n";
  7850. outs() << " reserved6 " << r.reserved6 << "\n";
  7851. }
  7852. static void Print_x86_thread_state64_t(MachO::x86_thread_state64_t &cpu64) {
  7853. outs() << " rax " << format("0x%016" PRIx64, cpu64.rax);
  7854. outs() << " rbx " << format("0x%016" PRIx64, cpu64.rbx);
  7855. outs() << " rcx " << format("0x%016" PRIx64, cpu64.rcx) << "\n";
  7856. outs() << " rdx " << format("0x%016" PRIx64, cpu64.rdx);
  7857. outs() << " rdi " << format("0x%016" PRIx64, cpu64.rdi);
  7858. outs() << " rsi " << format("0x%016" PRIx64, cpu64.rsi) << "\n";
  7859. outs() << " rbp " << format("0x%016" PRIx64, cpu64.rbp);
  7860. outs() << " rsp " << format("0x%016" PRIx64, cpu64.rsp);
  7861. outs() << " r8 " << format("0x%016" PRIx64, cpu64.r8) << "\n";
  7862. outs() << " r9 " << format("0x%016" PRIx64, cpu64.r9);
  7863. outs() << " r10 " << format("0x%016" PRIx64, cpu64.r10);
  7864. outs() << " r11 " << format("0x%016" PRIx64, cpu64.r11) << "\n";
  7865. outs() << " r12 " << format("0x%016" PRIx64, cpu64.r12);
  7866. outs() << " r13 " << format("0x%016" PRIx64, cpu64.r13);
  7867. outs() << " r14 " << format("0x%016" PRIx64, cpu64.r14) << "\n";
  7868. outs() << " r15 " << format("0x%016" PRIx64, cpu64.r15);
  7869. outs() << " rip " << format("0x%016" PRIx64, cpu64.rip) << "\n";
  7870. outs() << "rflags " << format("0x%016" PRIx64, cpu64.rflags);
  7871. outs() << " cs " << format("0x%016" PRIx64, cpu64.cs);
  7872. outs() << " fs " << format("0x%016" PRIx64, cpu64.fs) << "\n";
  7873. outs() << " gs " << format("0x%016" PRIx64, cpu64.gs) << "\n";
  7874. }
  7875. static void Print_mmst_reg(MachO::mmst_reg_t &r) {
  7876. uint32_t f;
  7877. outs() << "\t mmst_reg ";
  7878. for (f = 0; f < 10; f++)
  7879. outs() << format("%02" PRIx32, (r.mmst_reg[f] & 0xff)) << " ";
  7880. outs() << "\n";
  7881. outs() << "\t mmst_rsrv ";
  7882. for (f = 0; f < 6; f++)
  7883. outs() << format("%02" PRIx32, (r.mmst_rsrv[f] & 0xff)) << " ";
  7884. outs() << "\n";
  7885. }
  7886. static void Print_xmm_reg(MachO::xmm_reg_t &r) {
  7887. uint32_t f;
  7888. outs() << "\t xmm_reg ";
  7889. for (f = 0; f < 16; f++)
  7890. outs() << format("%02" PRIx32, (r.xmm_reg[f] & 0xff)) << " ";
  7891. outs() << "\n";
  7892. }
  7893. static void Print_x86_float_state_t(MachO::x86_float_state64_t &fpu) {
  7894. outs() << "\t fpu_reserved[0] " << fpu.fpu_reserved[0];
  7895. outs() << " fpu_reserved[1] " << fpu.fpu_reserved[1] << "\n";
  7896. outs() << "\t control: invalid " << fpu.fpu_fcw.invalid;
  7897. outs() << " denorm " << fpu.fpu_fcw.denorm;
  7898. outs() << " zdiv " << fpu.fpu_fcw.zdiv;
  7899. outs() << " ovrfl " << fpu.fpu_fcw.ovrfl;
  7900. outs() << " undfl " << fpu.fpu_fcw.undfl;
  7901. outs() << " precis " << fpu.fpu_fcw.precis << "\n";
  7902. outs() << "\t\t pc ";
  7903. if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_24B)
  7904. outs() << "FP_PREC_24B ";
  7905. else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_53B)
  7906. outs() << "FP_PREC_53B ";
  7907. else if (fpu.fpu_fcw.pc == MachO::x86_FP_PREC_64B)
  7908. outs() << "FP_PREC_64B ";
  7909. else
  7910. outs() << fpu.fpu_fcw.pc << " ";
  7911. outs() << "rc ";
  7912. if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_NEAR)
  7913. outs() << "FP_RND_NEAR ";
  7914. else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_DOWN)
  7915. outs() << "FP_RND_DOWN ";
  7916. else if (fpu.fpu_fcw.rc == MachO::x86_FP_RND_UP)
  7917. outs() << "FP_RND_UP ";
  7918. else if (fpu.fpu_fcw.rc == MachO::x86_FP_CHOP)
  7919. outs() << "FP_CHOP ";
  7920. outs() << "\n";
  7921. outs() << "\t status: invalid " << fpu.fpu_fsw.invalid;
  7922. outs() << " denorm " << fpu.fpu_fsw.denorm;
  7923. outs() << " zdiv " << fpu.fpu_fsw.zdiv;
  7924. outs() << " ovrfl " << fpu.fpu_fsw.ovrfl;
  7925. outs() << " undfl " << fpu.fpu_fsw.undfl;
  7926. outs() << " precis " << fpu.fpu_fsw.precis;
  7927. outs() << " stkflt " << fpu.fpu_fsw.stkflt << "\n";
  7928. outs() << "\t errsumm " << fpu.fpu_fsw.errsumm;
  7929. outs() << " c0 " << fpu.fpu_fsw.c0;
  7930. outs() << " c1 " << fpu.fpu_fsw.c1;
  7931. outs() << " c2 " << fpu.fpu_fsw.c2;
  7932. outs() << " tos " << fpu.fpu_fsw.tos;
  7933. outs() << " c3 " << fpu.fpu_fsw.c3;
  7934. outs() << " busy " << fpu.fpu_fsw.busy << "\n";
  7935. outs() << "\t fpu_ftw " << format("0x%02" PRIx32, fpu.fpu_ftw);
  7936. outs() << " fpu_rsrv1 " << format("0x%02" PRIx32, fpu.fpu_rsrv1);
  7937. outs() << " fpu_fop " << format("0x%04" PRIx32, fpu.fpu_fop);
  7938. outs() << " fpu_ip " << format("0x%08" PRIx32, fpu.fpu_ip) << "\n";
  7939. outs() << "\t fpu_cs " << format("0x%04" PRIx32, fpu.fpu_cs);
  7940. outs() << " fpu_rsrv2 " << format("0x%04" PRIx32, fpu.fpu_rsrv2);
  7941. outs() << " fpu_dp " << format("0x%08" PRIx32, fpu.fpu_dp);
  7942. outs() << " fpu_ds " << format("0x%04" PRIx32, fpu.fpu_ds) << "\n";
  7943. outs() << "\t fpu_rsrv3 " << format("0x%04" PRIx32, fpu.fpu_rsrv3);
  7944. outs() << " fpu_mxcsr " << format("0x%08" PRIx32, fpu.fpu_mxcsr);
  7945. outs() << " fpu_mxcsrmask " << format("0x%08" PRIx32, fpu.fpu_mxcsrmask);
  7946. outs() << "\n";
  7947. outs() << "\t fpu_stmm0:\n";
  7948. Print_mmst_reg(fpu.fpu_stmm0);
  7949. outs() << "\t fpu_stmm1:\n";
  7950. Print_mmst_reg(fpu.fpu_stmm1);
  7951. outs() << "\t fpu_stmm2:\n";
  7952. Print_mmst_reg(fpu.fpu_stmm2);
  7953. outs() << "\t fpu_stmm3:\n";
  7954. Print_mmst_reg(fpu.fpu_stmm3);
  7955. outs() << "\t fpu_stmm4:\n";
  7956. Print_mmst_reg(fpu.fpu_stmm4);
  7957. outs() << "\t fpu_stmm5:\n";
  7958. Print_mmst_reg(fpu.fpu_stmm5);
  7959. outs() << "\t fpu_stmm6:\n";
  7960. Print_mmst_reg(fpu.fpu_stmm6);
  7961. outs() << "\t fpu_stmm7:\n";
  7962. Print_mmst_reg(fpu.fpu_stmm7);
  7963. outs() << "\t fpu_xmm0:\n";
  7964. Print_xmm_reg(fpu.fpu_xmm0);
  7965. outs() << "\t fpu_xmm1:\n";
  7966. Print_xmm_reg(fpu.fpu_xmm1);
  7967. outs() << "\t fpu_xmm2:\n";
  7968. Print_xmm_reg(fpu.fpu_xmm2);
  7969. outs() << "\t fpu_xmm3:\n";
  7970. Print_xmm_reg(fpu.fpu_xmm3);
  7971. outs() << "\t fpu_xmm4:\n";
  7972. Print_xmm_reg(fpu.fpu_xmm4);
  7973. outs() << "\t fpu_xmm5:\n";
  7974. Print_xmm_reg(fpu.fpu_xmm5);
  7975. outs() << "\t fpu_xmm6:\n";
  7976. Print_xmm_reg(fpu.fpu_xmm6);
  7977. outs() << "\t fpu_xmm7:\n";
  7978. Print_xmm_reg(fpu.fpu_xmm7);
  7979. outs() << "\t fpu_xmm8:\n";
  7980. Print_xmm_reg(fpu.fpu_xmm8);
  7981. outs() << "\t fpu_xmm9:\n";
  7982. Print_xmm_reg(fpu.fpu_xmm9);
  7983. outs() << "\t fpu_xmm10:\n";
  7984. Print_xmm_reg(fpu.fpu_xmm10);
  7985. outs() << "\t fpu_xmm11:\n";
  7986. Print_xmm_reg(fpu.fpu_xmm11);
  7987. outs() << "\t fpu_xmm12:\n";
  7988. Print_xmm_reg(fpu.fpu_xmm12);
  7989. outs() << "\t fpu_xmm13:\n";
  7990. Print_xmm_reg(fpu.fpu_xmm13);
  7991. outs() << "\t fpu_xmm14:\n";
  7992. Print_xmm_reg(fpu.fpu_xmm14);
  7993. outs() << "\t fpu_xmm15:\n";
  7994. Print_xmm_reg(fpu.fpu_xmm15);
  7995. outs() << "\t fpu_rsrv4:\n";
  7996. for (uint32_t f = 0; f < 6; f++) {
  7997. outs() << "\t ";
  7998. for (uint32_t g = 0; g < 16; g++)
  7999. outs() << format("%02" PRIx32, fpu.fpu_rsrv4[f * g]) << " ";
  8000. outs() << "\n";
  8001. }
  8002. outs() << "\t fpu_reserved1 " << format("0x%08" PRIx32, fpu.fpu_reserved1);
  8003. outs() << "\n";
  8004. }
  8005. static void Print_x86_exception_state_t(MachO::x86_exception_state64_t &exc64) {
  8006. outs() << "\t trapno " << format("0x%08" PRIx32, exc64.trapno);
  8007. outs() << " err " << format("0x%08" PRIx32, exc64.err);
  8008. outs() << " faultvaddr " << format("0x%016" PRIx64, exc64.faultvaddr) << "\n";
  8009. }
  8010. static void PrintThreadCommand(MachO::thread_command t, const char *Ptr,
  8011. bool isLittleEndian, uint32_t cputype) {
  8012. if (t.cmd == MachO::LC_THREAD)
  8013. outs() << " cmd LC_THREAD\n";
  8014. else if (t.cmd == MachO::LC_UNIXTHREAD)
  8015. outs() << " cmd LC_UNIXTHREAD\n";
  8016. else
  8017. outs() << " cmd " << t.cmd << " (unknown)\n";
  8018. outs() << " cmdsize " << t.cmdsize;
  8019. if (t.cmdsize < sizeof(struct MachO::thread_command) + 2 * sizeof(uint32_t))
  8020. outs() << " Incorrect size\n";
  8021. else
  8022. outs() << "\n";
  8023. const char *begin = Ptr + sizeof(struct MachO::thread_command);
  8024. const char *end = Ptr + t.cmdsize;
  8025. uint32_t flavor, count, left;
  8026. if (cputype == MachO::CPU_TYPE_X86_64) {
  8027. while (begin < end) {
  8028. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8029. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  8030. begin += sizeof(uint32_t);
  8031. } else {
  8032. flavor = 0;
  8033. begin = end;
  8034. }
  8035. if (isLittleEndian != sys::IsLittleEndianHost)
  8036. sys::swapByteOrder(flavor);
  8037. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8038. memcpy((char *)&count, begin, sizeof(uint32_t));
  8039. begin += sizeof(uint32_t);
  8040. } else {
  8041. count = 0;
  8042. begin = end;
  8043. }
  8044. if (isLittleEndian != sys::IsLittleEndianHost)
  8045. sys::swapByteOrder(count);
  8046. if (flavor == MachO::x86_THREAD_STATE64) {
  8047. outs() << " flavor x86_THREAD_STATE64\n";
  8048. if (count == MachO::x86_THREAD_STATE64_COUNT)
  8049. outs() << " count x86_THREAD_STATE64_COUNT\n";
  8050. else
  8051. outs() << " count " << count
  8052. << " (not x86_THREAD_STATE64_COUNT)\n";
  8053. MachO::x86_thread_state64_t cpu64;
  8054. left = end - begin;
  8055. if (left >= sizeof(MachO::x86_thread_state64_t)) {
  8056. memcpy(&cpu64, begin, sizeof(MachO::x86_thread_state64_t));
  8057. begin += sizeof(MachO::x86_thread_state64_t);
  8058. } else {
  8059. memset(&cpu64, '\0', sizeof(MachO::x86_thread_state64_t));
  8060. memcpy(&cpu64, begin, left);
  8061. begin += left;
  8062. }
  8063. if (isLittleEndian != sys::IsLittleEndianHost)
  8064. swapStruct(cpu64);
  8065. Print_x86_thread_state64_t(cpu64);
  8066. } else if (flavor == MachO::x86_THREAD_STATE) {
  8067. outs() << " flavor x86_THREAD_STATE\n";
  8068. if (count == MachO::x86_THREAD_STATE_COUNT)
  8069. outs() << " count x86_THREAD_STATE_COUNT\n";
  8070. else
  8071. outs() << " count " << count
  8072. << " (not x86_THREAD_STATE_COUNT)\n";
  8073. struct MachO::x86_thread_state_t ts;
  8074. left = end - begin;
  8075. if (left >= sizeof(MachO::x86_thread_state_t)) {
  8076. memcpy(&ts, begin, sizeof(MachO::x86_thread_state_t));
  8077. begin += sizeof(MachO::x86_thread_state_t);
  8078. } else {
  8079. memset(&ts, '\0', sizeof(MachO::x86_thread_state_t));
  8080. memcpy(&ts, begin, left);
  8081. begin += left;
  8082. }
  8083. if (isLittleEndian != sys::IsLittleEndianHost)
  8084. swapStruct(ts);
  8085. if (ts.tsh.flavor == MachO::x86_THREAD_STATE64) {
  8086. outs() << "\t tsh.flavor x86_THREAD_STATE64 ";
  8087. if (ts.tsh.count == MachO::x86_THREAD_STATE64_COUNT)
  8088. outs() << "tsh.count x86_THREAD_STATE64_COUNT\n";
  8089. else
  8090. outs() << "tsh.count " << ts.tsh.count
  8091. << " (not x86_THREAD_STATE64_COUNT\n";
  8092. Print_x86_thread_state64_t(ts.uts.ts64);
  8093. } else {
  8094. outs() << "\t tsh.flavor " << ts.tsh.flavor << " tsh.count "
  8095. << ts.tsh.count << "\n";
  8096. }
  8097. } else if (flavor == MachO::x86_FLOAT_STATE) {
  8098. outs() << " flavor x86_FLOAT_STATE\n";
  8099. if (count == MachO::x86_FLOAT_STATE_COUNT)
  8100. outs() << " count x86_FLOAT_STATE_COUNT\n";
  8101. else
  8102. outs() << " count " << count << " (not x86_FLOAT_STATE_COUNT)\n";
  8103. struct MachO::x86_float_state_t fs;
  8104. left = end - begin;
  8105. if (left >= sizeof(MachO::x86_float_state_t)) {
  8106. memcpy(&fs, begin, sizeof(MachO::x86_float_state_t));
  8107. begin += sizeof(MachO::x86_float_state_t);
  8108. } else {
  8109. memset(&fs, '\0', sizeof(MachO::x86_float_state_t));
  8110. memcpy(&fs, begin, left);
  8111. begin += left;
  8112. }
  8113. if (isLittleEndian != sys::IsLittleEndianHost)
  8114. swapStruct(fs);
  8115. if (fs.fsh.flavor == MachO::x86_FLOAT_STATE64) {
  8116. outs() << "\t fsh.flavor x86_FLOAT_STATE64 ";
  8117. if (fs.fsh.count == MachO::x86_FLOAT_STATE64_COUNT)
  8118. outs() << "fsh.count x86_FLOAT_STATE64_COUNT\n";
  8119. else
  8120. outs() << "fsh.count " << fs.fsh.count
  8121. << " (not x86_FLOAT_STATE64_COUNT\n";
  8122. Print_x86_float_state_t(fs.ufs.fs64);
  8123. } else {
  8124. outs() << "\t fsh.flavor " << fs.fsh.flavor << " fsh.count "
  8125. << fs.fsh.count << "\n";
  8126. }
  8127. } else if (flavor == MachO::x86_EXCEPTION_STATE) {
  8128. outs() << " flavor x86_EXCEPTION_STATE\n";
  8129. if (count == MachO::x86_EXCEPTION_STATE_COUNT)
  8130. outs() << " count x86_EXCEPTION_STATE_COUNT\n";
  8131. else
  8132. outs() << " count " << count
  8133. << " (not x86_EXCEPTION_STATE_COUNT)\n";
  8134. struct MachO::x86_exception_state_t es;
  8135. left = end - begin;
  8136. if (left >= sizeof(MachO::x86_exception_state_t)) {
  8137. memcpy(&es, begin, sizeof(MachO::x86_exception_state_t));
  8138. begin += sizeof(MachO::x86_exception_state_t);
  8139. } else {
  8140. memset(&es, '\0', sizeof(MachO::x86_exception_state_t));
  8141. memcpy(&es, begin, left);
  8142. begin += left;
  8143. }
  8144. if (isLittleEndian != sys::IsLittleEndianHost)
  8145. swapStruct(es);
  8146. if (es.esh.flavor == MachO::x86_EXCEPTION_STATE64) {
  8147. outs() << "\t esh.flavor x86_EXCEPTION_STATE64\n";
  8148. if (es.esh.count == MachO::x86_EXCEPTION_STATE64_COUNT)
  8149. outs() << "\t esh.count x86_EXCEPTION_STATE64_COUNT\n";
  8150. else
  8151. outs() << "\t esh.count " << es.esh.count
  8152. << " (not x86_EXCEPTION_STATE64_COUNT\n";
  8153. Print_x86_exception_state_t(es.ues.es64);
  8154. } else {
  8155. outs() << "\t esh.flavor " << es.esh.flavor << " esh.count "
  8156. << es.esh.count << "\n";
  8157. }
  8158. } else {
  8159. outs() << " flavor " << flavor << " (unknown)\n";
  8160. outs() << " count " << count << "\n";
  8161. outs() << " state (unknown)\n";
  8162. begin += count * sizeof(uint32_t);
  8163. }
  8164. }
  8165. } else {
  8166. while (begin < end) {
  8167. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8168. memcpy((char *)&flavor, begin, sizeof(uint32_t));
  8169. begin += sizeof(uint32_t);
  8170. } else {
  8171. flavor = 0;
  8172. begin = end;
  8173. }
  8174. if (isLittleEndian != sys::IsLittleEndianHost)
  8175. sys::swapByteOrder(flavor);
  8176. if (end - begin > (ptrdiff_t)sizeof(uint32_t)) {
  8177. memcpy((char *)&count, begin, sizeof(uint32_t));
  8178. begin += sizeof(uint32_t);
  8179. } else {
  8180. count = 0;
  8181. begin = end;
  8182. }
  8183. if (isLittleEndian != sys::IsLittleEndianHost)
  8184. sys::swapByteOrder(count);
  8185. outs() << " flavor " << flavor << "\n";
  8186. outs() << " count " << count << "\n";
  8187. outs() << " state (Unknown cputype/cpusubtype)\n";
  8188. begin += count * sizeof(uint32_t);
  8189. }
  8190. }
  8191. }
  8192. static void PrintDylibCommand(MachO::dylib_command dl, const char *Ptr) {
  8193. if (dl.cmd == MachO::LC_ID_DYLIB)
  8194. outs() << " cmd LC_ID_DYLIB\n";
  8195. else if (dl.cmd == MachO::LC_LOAD_DYLIB)
  8196. outs() << " cmd LC_LOAD_DYLIB\n";
  8197. else if (dl.cmd == MachO::LC_LOAD_WEAK_DYLIB)
  8198. outs() << " cmd LC_LOAD_WEAK_DYLIB\n";
  8199. else if (dl.cmd == MachO::LC_REEXPORT_DYLIB)
  8200. outs() << " cmd LC_REEXPORT_DYLIB\n";
  8201. else if (dl.cmd == MachO::LC_LAZY_LOAD_DYLIB)
  8202. outs() << " cmd LC_LAZY_LOAD_DYLIB\n";
  8203. else if (dl.cmd == MachO::LC_LOAD_UPWARD_DYLIB)
  8204. outs() << " cmd LC_LOAD_UPWARD_DYLIB\n";
  8205. else
  8206. outs() << " cmd " << dl.cmd << " (unknown)\n";
  8207. outs() << " cmdsize " << dl.cmdsize;
  8208. if (dl.cmdsize < sizeof(struct MachO::dylib_command))
  8209. outs() << " Incorrect size\n";
  8210. else
  8211. outs() << "\n";
  8212. if (dl.dylib.name < dl.cmdsize) {
  8213. const char *P = (const char *)(Ptr) + dl.dylib.name;
  8214. outs() << " name " << P << " (offset " << dl.dylib.name << ")\n";
  8215. } else {
  8216. outs() << " name ?(bad offset " << dl.dylib.name << ")\n";
  8217. }
  8218. outs() << " time stamp " << dl.dylib.timestamp << " ";
  8219. time_t t = dl.dylib.timestamp;
  8220. outs() << ctime(&t);
  8221. outs() << " current version ";
  8222. if (dl.dylib.current_version == 0xffffffff)
  8223. outs() << "n/a\n";
  8224. else
  8225. outs() << ((dl.dylib.current_version >> 16) & 0xffff) << "."
  8226. << ((dl.dylib.current_version >> 8) & 0xff) << "."
  8227. << (dl.dylib.current_version & 0xff) << "\n";
  8228. outs() << "compatibility version ";
  8229. if (dl.dylib.compatibility_version == 0xffffffff)
  8230. outs() << "n/a\n";
  8231. else
  8232. outs() << ((dl.dylib.compatibility_version >> 16) & 0xffff) << "."
  8233. << ((dl.dylib.compatibility_version >> 8) & 0xff) << "."
  8234. << (dl.dylib.compatibility_version & 0xff) << "\n";
  8235. }
  8236. static void PrintLinkEditDataCommand(MachO::linkedit_data_command ld,
  8237. uint32_t object_size) {
  8238. if (ld.cmd == MachO::LC_CODE_SIGNATURE)
  8239. outs() << " cmd LC_CODE_SIGNATURE\n";
  8240. else if (ld.cmd == MachO::LC_SEGMENT_SPLIT_INFO)
  8241. outs() << " cmd LC_SEGMENT_SPLIT_INFO\n";
  8242. else if (ld.cmd == MachO::LC_FUNCTION_STARTS)
  8243. outs() << " cmd LC_FUNCTION_STARTS\n";
  8244. else if (ld.cmd == MachO::LC_DATA_IN_CODE)
  8245. outs() << " cmd LC_DATA_IN_CODE\n";
  8246. else if (ld.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS)
  8247. outs() << " cmd LC_DYLIB_CODE_SIGN_DRS\n";
  8248. else if (ld.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT)
  8249. outs() << " cmd LC_LINKER_OPTIMIZATION_HINT\n";
  8250. else
  8251. outs() << " cmd " << ld.cmd << " (?)\n";
  8252. outs() << " cmdsize " << ld.cmdsize;
  8253. if (ld.cmdsize != sizeof(struct MachO::linkedit_data_command))
  8254. outs() << " Incorrect size\n";
  8255. else
  8256. outs() << "\n";
  8257. outs() << " dataoff " << ld.dataoff;
  8258. if (ld.dataoff > object_size)
  8259. outs() << " (past end of file)\n";
  8260. else
  8261. outs() << "\n";
  8262. outs() << " datasize " << ld.datasize;
  8263. uint64_t big_size = ld.dataoff;
  8264. big_size += ld.datasize;
  8265. if (big_size > object_size)
  8266. outs() << " (past end of file)\n";
  8267. else
  8268. outs() << "\n";
  8269. }
  8270. static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t filetype,
  8271. uint32_t cputype, bool verbose) {
  8272. StringRef Buf = Obj->getData();
  8273. unsigned Index = 0;
  8274. for (const auto &Command : Obj->load_commands()) {
  8275. outs() << "Load command " << Index++ << "\n";
  8276. if (Command.C.cmd == MachO::LC_SEGMENT) {
  8277. MachO::segment_command SLC = Obj->getSegmentLoadCommand(Command);
  8278. const char *sg_segname = SLC.segname;
  8279. PrintSegmentCommand(SLC.cmd, SLC.cmdsize, SLC.segname, SLC.vmaddr,
  8280. SLC.vmsize, SLC.fileoff, SLC.filesize, SLC.maxprot,
  8281. SLC.initprot, SLC.nsects, SLC.flags, Buf.size(),
  8282. verbose);
  8283. for (unsigned j = 0; j < SLC.nsects; j++) {
  8284. MachO::section S = Obj->getSection(Command, j);
  8285. PrintSection(S.sectname, S.segname, S.addr, S.size, S.offset, S.align,
  8286. S.reloff, S.nreloc, S.flags, S.reserved1, S.reserved2,
  8287. SLC.cmd, sg_segname, filetype, Buf.size(), verbose);
  8288. }
  8289. } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
  8290. MachO::segment_command_64 SLC_64 = Obj->getSegment64LoadCommand(Command);
  8291. const char *sg_segname = SLC_64.segname;
  8292. PrintSegmentCommand(SLC_64.cmd, SLC_64.cmdsize, SLC_64.segname,
  8293. SLC_64.vmaddr, SLC_64.vmsize, SLC_64.fileoff,
  8294. SLC_64.filesize, SLC_64.maxprot, SLC_64.initprot,
  8295. SLC_64.nsects, SLC_64.flags, Buf.size(), verbose);
  8296. for (unsigned j = 0; j < SLC_64.nsects; j++) {
  8297. MachO::section_64 S_64 = Obj->getSection64(Command, j);
  8298. PrintSection(S_64.sectname, S_64.segname, S_64.addr, S_64.size,
  8299. S_64.offset, S_64.align, S_64.reloff, S_64.nreloc,
  8300. S_64.flags, S_64.reserved1, S_64.reserved2, SLC_64.cmd,
  8301. sg_segname, filetype, Buf.size(), verbose);
  8302. }
  8303. } else if (Command.C.cmd == MachO::LC_SYMTAB) {
  8304. MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
  8305. PrintSymtabLoadCommand(Symtab, Obj->is64Bit(), Buf.size());
  8306. } else if (Command.C.cmd == MachO::LC_DYSYMTAB) {
  8307. MachO::dysymtab_command Dysymtab = Obj->getDysymtabLoadCommand();
  8308. MachO::symtab_command Symtab = Obj->getSymtabLoadCommand();
  8309. PrintDysymtabLoadCommand(Dysymtab, Symtab.nsyms, Buf.size(),
  8310. Obj->is64Bit());
  8311. } else if (Command.C.cmd == MachO::LC_DYLD_INFO ||
  8312. Command.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
  8313. MachO::dyld_info_command DyldInfo = Obj->getDyldInfoLoadCommand(Command);
  8314. PrintDyldInfoLoadCommand(DyldInfo, Buf.size());
  8315. } else if (Command.C.cmd == MachO::LC_LOAD_DYLINKER ||
  8316. Command.C.cmd == MachO::LC_ID_DYLINKER ||
  8317. Command.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
  8318. MachO::dylinker_command Dyld = Obj->getDylinkerCommand(Command);
  8319. PrintDyldLoadCommand(Dyld, Command.Ptr);
  8320. } else if (Command.C.cmd == MachO::LC_UUID) {
  8321. MachO::uuid_command Uuid = Obj->getUuidCommand(Command);
  8322. PrintUuidLoadCommand(Uuid);
  8323. } else if (Command.C.cmd == MachO::LC_RPATH) {
  8324. MachO::rpath_command Rpath = Obj->getRpathCommand(Command);
  8325. PrintRpathLoadCommand(Rpath, Command.Ptr);
  8326. } else if (Command.C.cmd == MachO::LC_VERSION_MIN_MACOSX ||
  8327. Command.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS ||
  8328. Command.C.cmd == MachO::LC_VERSION_MIN_TVOS ||
  8329. Command.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
  8330. MachO::version_min_command Vd = Obj->getVersionMinLoadCommand(Command);
  8331. PrintVersionMinLoadCommand(Vd);
  8332. } else if (Command.C.cmd == MachO::LC_SOURCE_VERSION) {
  8333. MachO::source_version_command Sd = Obj->getSourceVersionCommand(Command);
  8334. PrintSourceVersionCommand(Sd);
  8335. } else if (Command.C.cmd == MachO::LC_MAIN) {
  8336. MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
  8337. PrintEntryPointCommand(Ep);
  8338. } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO) {
  8339. MachO::encryption_info_command Ei =
  8340. Obj->getEncryptionInfoCommand(Command);
  8341. PrintEncryptionInfoCommand(Ei, Buf.size());
  8342. } else if (Command.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
  8343. MachO::encryption_info_command_64 Ei =
  8344. Obj->getEncryptionInfoCommand64(Command);
  8345. PrintEncryptionInfoCommand64(Ei, Buf.size());
  8346. } else if (Command.C.cmd == MachO::LC_LINKER_OPTION) {
  8347. MachO::linker_option_command Lo =
  8348. Obj->getLinkerOptionLoadCommand(Command);
  8349. PrintLinkerOptionCommand(Lo, Command.Ptr);
  8350. } else if (Command.C.cmd == MachO::LC_SUB_FRAMEWORK) {
  8351. MachO::sub_framework_command Sf = Obj->getSubFrameworkCommand(Command);
  8352. PrintSubFrameworkCommand(Sf, Command.Ptr);
  8353. } else if (Command.C.cmd == MachO::LC_SUB_UMBRELLA) {
  8354. MachO::sub_umbrella_command Sf = Obj->getSubUmbrellaCommand(Command);
  8355. PrintSubUmbrellaCommand(Sf, Command.Ptr);
  8356. } else if (Command.C.cmd == MachO::LC_SUB_LIBRARY) {
  8357. MachO::sub_library_command Sl = Obj->getSubLibraryCommand(Command);
  8358. PrintSubLibraryCommand(Sl, Command.Ptr);
  8359. } else if (Command.C.cmd == MachO::LC_SUB_CLIENT) {
  8360. MachO::sub_client_command Sc = Obj->getSubClientCommand(Command);
  8361. PrintSubClientCommand(Sc, Command.Ptr);
  8362. } else if (Command.C.cmd == MachO::LC_ROUTINES) {
  8363. MachO::routines_command Rc = Obj->getRoutinesCommand(Command);
  8364. PrintRoutinesCommand(Rc);
  8365. } else if (Command.C.cmd == MachO::LC_ROUTINES_64) {
  8366. MachO::routines_command_64 Rc = Obj->getRoutinesCommand64(Command);
  8367. PrintRoutinesCommand64(Rc);
  8368. } else if (Command.C.cmd == MachO::LC_THREAD ||
  8369. Command.C.cmd == MachO::LC_UNIXTHREAD) {
  8370. MachO::thread_command Tc = Obj->getThreadCommand(Command);
  8371. PrintThreadCommand(Tc, Command.Ptr, Obj->isLittleEndian(), cputype);
  8372. } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
  8373. Command.C.cmd == MachO::LC_ID_DYLIB ||
  8374. Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
  8375. Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
  8376. Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
  8377. Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
  8378. MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
  8379. PrintDylibCommand(Dl, Command.Ptr);
  8380. } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
  8381. Command.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO ||
  8382. Command.C.cmd == MachO::LC_FUNCTION_STARTS ||
  8383. Command.C.cmd == MachO::LC_DATA_IN_CODE ||
  8384. Command.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS ||
  8385. Command.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
  8386. MachO::linkedit_data_command Ld =
  8387. Obj->getLinkeditDataLoadCommand(Command);
  8388. PrintLinkEditDataCommand(Ld, Buf.size());
  8389. } else {
  8390. outs() << " cmd ?(" << format("0x%08" PRIx32, Command.C.cmd)
  8391. << ")\n";
  8392. outs() << " cmdsize " << Command.C.cmdsize << "\n";
  8393. // TODO: get and print the raw bytes of the load command.
  8394. }
  8395. // TODO: print all the other kinds of load commands.
  8396. }
  8397. }
  8398. static void PrintMachHeader(const MachOObjectFile *Obj, bool verbose) {
  8399. if (Obj->is64Bit()) {
  8400. MachO::mach_header_64 H_64;
  8401. H_64 = Obj->getHeader64();
  8402. PrintMachHeader(H_64.magic, H_64.cputype, H_64.cpusubtype, H_64.filetype,
  8403. H_64.ncmds, H_64.sizeofcmds, H_64.flags, verbose);
  8404. } else {
  8405. MachO::mach_header H;
  8406. H = Obj->getHeader();
  8407. PrintMachHeader(H.magic, H.cputype, H.cpusubtype, H.filetype, H.ncmds,
  8408. H.sizeofcmds, H.flags, verbose);
  8409. }
  8410. }
  8411. void llvm::printMachOFileHeader(const object::ObjectFile *Obj) {
  8412. const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
  8413. PrintMachHeader(file, !NonVerbose);
  8414. }
  8415. void llvm::printMachOLoadCommands(const object::ObjectFile *Obj) {
  8416. const MachOObjectFile *file = dyn_cast<const MachOObjectFile>(Obj);
  8417. uint32_t filetype = 0;
  8418. uint32_t cputype = 0;
  8419. if (file->is64Bit()) {
  8420. MachO::mach_header_64 H_64;
  8421. H_64 = file->getHeader64();
  8422. filetype = H_64.filetype;
  8423. cputype = H_64.cputype;
  8424. } else {
  8425. MachO::mach_header H;
  8426. H = file->getHeader();
  8427. filetype = H.filetype;
  8428. cputype = H.cputype;
  8429. }
  8430. PrintLoadCommands(file, filetype, cputype, !NonVerbose);
  8431. }
  8432. //===----------------------------------------------------------------------===//
  8433. // export trie dumping
  8434. //===----------------------------------------------------------------------===//
  8435. void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {
  8436. for (const llvm::object::ExportEntry &Entry : Obj->exports()) {
  8437. uint64_t Flags = Entry.flags();
  8438. bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
  8439. bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
  8440. bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
  8441. MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);
  8442. bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
  8443. MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
  8444. bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
  8445. if (ReExport)
  8446. outs() << "[re-export] ";
  8447. else
  8448. outs() << format("0x%08llX ",
  8449. Entry.address()); // FIXME:add in base address
  8450. outs() << Entry.name();
  8451. if (WeakDef || ThreadLocal || Resolver || Abs) {
  8452. bool NeedsComma = false;
  8453. outs() << " [";
  8454. if (WeakDef) {
  8455. outs() << "weak_def";
  8456. NeedsComma = true;
  8457. }
  8458. if (ThreadLocal) {
  8459. if (NeedsComma)
  8460. outs() << ", ";
  8461. outs() << "per-thread";
  8462. NeedsComma = true;
  8463. }
  8464. if (Abs) {
  8465. if (NeedsComma)
  8466. outs() << ", ";
  8467. outs() << "absolute";
  8468. NeedsComma = true;
  8469. }
  8470. if (Resolver) {
  8471. if (NeedsComma)
  8472. outs() << ", ";
  8473. outs() << format("resolver=0x%08llX", Entry.other());
  8474. NeedsComma = true;
  8475. }
  8476. outs() << "]";
  8477. }
  8478. if (ReExport) {
  8479. StringRef DylibName = "unknown";
  8480. int Ordinal = Entry.other() - 1;
  8481. Obj->getLibraryShortNameByIndex(Ordinal, DylibName);
  8482. if (Entry.otherName().empty())
  8483. outs() << " (from " << DylibName << ")";
  8484. else
  8485. outs() << " (" << Entry.otherName() << " from " << DylibName << ")";
  8486. }
  8487. outs() << "\n";
  8488. }
  8489. }
  8490. //===----------------------------------------------------------------------===//
  8491. // rebase table dumping
  8492. //===----------------------------------------------------------------------===//
  8493. namespace {
  8494. class SegInfo {
  8495. public:
  8496. SegInfo(const object::MachOObjectFile *Obj);
  8497. StringRef segmentName(uint32_t SegIndex);
  8498. StringRef sectionName(uint32_t SegIndex, uint64_t SegOffset);
  8499. uint64_t address(uint32_t SegIndex, uint64_t SegOffset);
  8500. bool isValidSegIndexAndOffset(uint32_t SegIndex, uint64_t SegOffset);
  8501. private:
  8502. struct SectionInfo {
  8503. uint64_t Address;
  8504. uint64_t Size;
  8505. StringRef SectionName;
  8506. StringRef SegmentName;
  8507. uint64_t OffsetInSegment;
  8508. uint64_t SegmentStartAddress;
  8509. uint32_t SegmentIndex;
  8510. };
  8511. const SectionInfo &findSection(uint32_t SegIndex, uint64_t SegOffset);
  8512. SmallVector<SectionInfo, 32> Sections;
  8513. };
  8514. }
  8515. SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
  8516. // Build table of sections so segIndex/offset pairs can be translated.
  8517. uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0;
  8518. StringRef CurSegName;
  8519. uint64_t CurSegAddress;
  8520. for (const SectionRef &Section : Obj->sections()) {
  8521. SectionInfo Info;
  8522. error(Section.getName(Info.SectionName));
  8523. Info.Address = Section.getAddress();
  8524. Info.Size = Section.getSize();
  8525. Info.SegmentName =
  8526. Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
  8527. if (!Info.SegmentName.equals(CurSegName)) {
  8528. ++CurSegIndex;
  8529. CurSegName = Info.SegmentName;
  8530. CurSegAddress = Info.Address;
  8531. }
  8532. Info.SegmentIndex = CurSegIndex - 1;
  8533. Info.OffsetInSegment = Info.Address - CurSegAddress;
  8534. Info.SegmentStartAddress = CurSegAddress;
  8535. Sections.push_back(Info);
  8536. }
  8537. }
  8538. StringRef SegInfo::segmentName(uint32_t SegIndex) {
  8539. for (const SectionInfo &SI : Sections) {
  8540. if (SI.SegmentIndex == SegIndex)
  8541. return SI.SegmentName;
  8542. }
  8543. llvm_unreachable("invalid segIndex");
  8544. }
  8545. bool SegInfo::isValidSegIndexAndOffset(uint32_t SegIndex,
  8546. uint64_t OffsetInSeg) {
  8547. for (const SectionInfo &SI : Sections) {
  8548. if (SI.SegmentIndex != SegIndex)
  8549. continue;
  8550. if (SI.OffsetInSegment > OffsetInSeg)
  8551. continue;
  8552. if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
  8553. continue;
  8554. return true;
  8555. }
  8556. return false;
  8557. }
  8558. const SegInfo::SectionInfo &SegInfo::findSection(uint32_t SegIndex,
  8559. uint64_t OffsetInSeg) {
  8560. for (const SectionInfo &SI : Sections) {
  8561. if (SI.SegmentIndex != SegIndex)
  8562. continue;
  8563. if (SI.OffsetInSegment > OffsetInSeg)
  8564. continue;
  8565. if (OffsetInSeg >= (SI.OffsetInSegment + SI.Size))
  8566. continue;
  8567. return SI;
  8568. }
  8569. llvm_unreachable("segIndex and offset not in any section");
  8570. }
  8571. StringRef SegInfo::sectionName(uint32_t SegIndex, uint64_t OffsetInSeg) {
  8572. return findSection(SegIndex, OffsetInSeg).SectionName;
  8573. }
  8574. uint64_t SegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) {
  8575. const SectionInfo &SI = findSection(SegIndex, OffsetInSeg);
  8576. return SI.SegmentStartAddress + OffsetInSeg;
  8577. }
  8578. void llvm::printMachORebaseTable(const object::MachOObjectFile *Obj) {
  8579. // Build table of sections so names can used in final output.
  8580. SegInfo sectionTable(Obj);
  8581. outs() << "segment section address type\n";
  8582. for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) {
  8583. uint32_t SegIndex = Entry.segmentIndex();
  8584. uint64_t OffsetInSeg = Entry.segmentOffset();
  8585. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8586. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8587. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8588. // Table lines look like: __DATA __nl_symbol_ptr 0x0000F00C pointer
  8589. outs() << format("%-8s %-18s 0x%08" PRIX64 " %s\n",
  8590. SegmentName.str().c_str(), SectionName.str().c_str(),
  8591. Address, Entry.typeName().str().c_str());
  8592. }
  8593. }
  8594. static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
  8595. StringRef DylibName;
  8596. switch (Ordinal) {
  8597. case MachO::BIND_SPECIAL_DYLIB_SELF:
  8598. return "this-image";
  8599. case MachO::BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE:
  8600. return "main-executable";
  8601. case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
  8602. return "flat-namespace";
  8603. default:
  8604. if (Ordinal > 0) {
  8605. std::error_code EC =
  8606. Obj->getLibraryShortNameByIndex(Ordinal - 1, DylibName);
  8607. if (EC)
  8608. return "<<bad library ordinal>>";
  8609. return DylibName;
  8610. }
  8611. }
  8612. return "<<unknown special ordinal>>";
  8613. }
  8614. //===----------------------------------------------------------------------===//
  8615. // bind table dumping
  8616. //===----------------------------------------------------------------------===//
  8617. void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
  8618. // Build table of sections so names can used in final output.
  8619. SegInfo sectionTable(Obj);
  8620. outs() << "segment section address type "
  8621. "addend dylib symbol\n";
  8622. for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
  8623. uint32_t SegIndex = Entry.segmentIndex();
  8624. uint64_t OffsetInSeg = Entry.segmentOffset();
  8625. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8626. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8627. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8628. // Table lines look like:
  8629. // __DATA __got 0x00012010 pointer 0 libSystem ___stack_chk_guard
  8630. StringRef Attr;
  8631. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
  8632. Attr = " (weak_import)";
  8633. outs() << left_justify(SegmentName, 8) << " "
  8634. << left_justify(SectionName, 18) << " "
  8635. << format_hex(Address, 10, true) << " "
  8636. << left_justify(Entry.typeName(), 8) << " "
  8637. << format_decimal(Entry.addend(), 8) << " "
  8638. << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
  8639. << Entry.symbolName() << Attr << "\n";
  8640. }
  8641. }
  8642. //===----------------------------------------------------------------------===//
  8643. // lazy bind table dumping
  8644. //===----------------------------------------------------------------------===//
  8645. void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
  8646. // Build table of sections so names can used in final output.
  8647. SegInfo sectionTable(Obj);
  8648. outs() << "segment section address "
  8649. "dylib symbol\n";
  8650. for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) {
  8651. uint32_t SegIndex = Entry.segmentIndex();
  8652. uint64_t OffsetInSeg = Entry.segmentOffset();
  8653. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8654. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8655. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8656. // Table lines look like:
  8657. // __DATA __got 0x00012010 libSystem ___stack_chk_guard
  8658. outs() << left_justify(SegmentName, 8) << " "
  8659. << left_justify(SectionName, 18) << " "
  8660. << format_hex(Address, 10, true) << " "
  8661. << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
  8662. << Entry.symbolName() << "\n";
  8663. }
  8664. }
  8665. //===----------------------------------------------------------------------===//
  8666. // weak bind table dumping
  8667. //===----------------------------------------------------------------------===//
  8668. void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
  8669. // Build table of sections so names can used in final output.
  8670. SegInfo sectionTable(Obj);
  8671. outs() << "segment section address "
  8672. "type addend symbol\n";
  8673. for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) {
  8674. // Strong symbols don't have a location to update.
  8675. if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
  8676. outs() << " strong "
  8677. << Entry.symbolName() << "\n";
  8678. continue;
  8679. }
  8680. uint32_t SegIndex = Entry.segmentIndex();
  8681. uint64_t OffsetInSeg = Entry.segmentOffset();
  8682. StringRef SegmentName = sectionTable.segmentName(SegIndex);
  8683. StringRef SectionName = sectionTable.sectionName(SegIndex, OffsetInSeg);
  8684. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8685. // Table lines look like:
  8686. // __DATA __data 0x00001000 pointer 0 _foo
  8687. outs() << left_justify(SegmentName, 8) << " "
  8688. << left_justify(SectionName, 18) << " "
  8689. << format_hex(Address, 10, true) << " "
  8690. << left_justify(Entry.typeName(), 8) << " "
  8691. << format_decimal(Entry.addend(), 8) << " " << Entry.symbolName()
  8692. << "\n";
  8693. }
  8694. }
  8695. // get_dyld_bind_info_symbolname() is used for disassembly and passed an
  8696. // address, ReferenceValue, in the Mach-O file and looks in the dyld bind
  8697. // information for that address. If the address is found its binding symbol
  8698. // name is returned. If not nullptr is returned.
  8699. static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
  8700. struct DisassembleInfo *info) {
  8701. if (info->bindtable == nullptr) {
  8702. info->bindtable = new (BindTable);
  8703. SegInfo sectionTable(info->O);
  8704. for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
  8705. uint32_t SegIndex = Entry.segmentIndex();
  8706. uint64_t OffsetInSeg = Entry.segmentOffset();
  8707. if (!sectionTable.isValidSegIndexAndOffset(SegIndex, OffsetInSeg))
  8708. continue;
  8709. uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
  8710. const char *SymbolName = nullptr;
  8711. StringRef name = Entry.symbolName();
  8712. if (!name.empty())
  8713. SymbolName = name.data();
  8714. info->bindtable->push_back(std::make_pair(Address, SymbolName));
  8715. }
  8716. }
  8717. for (bind_table_iterator BI = info->bindtable->begin(),
  8718. BE = info->bindtable->end();
  8719. BI != BE; ++BI) {
  8720. uint64_t Address = BI->first;
  8721. if (ReferenceValue == Address) {
  8722. const char *SymbolName = BI->second;
  8723. return SymbolName;
  8724. }
  8725. }
  8726. return nullptr;
  8727. }