12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093 |
- /* vms.c -- BFD back-end for EVAX (openVMS/Alpha) files.
- Copyright (C) 1996-2022 Free Software Foundation, Inc.
- Initial version written by Klaus Kaempf (kkaempf@rmi.de)
- Major rewrite by Adacore.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
- MA 02110-1301, USA. */
- /* TODO:
- o overlayed sections
- o PIC
- o Generation of shared image
- o Relocation optimizations
- o EISD for the stack
- o Vectors isect
- o 64 bits sections
- o Entry point
- o LIB$INITIALIZE
- o protected sections (for messages)
- ...
- */
- #include "sysdep.h"
- #include <limits.h>
- #include "bfd.h"
- #include "bfdlink.h"
- #include "libbfd.h"
- #include "bfdver.h"
- #include "vms.h"
- #include "vms/eihd.h"
- #include "vms/eiha.h"
- #include "vms/eihi.h"
- #include "vms/eihs.h"
- #include "vms/eisd.h"
- #include "vms/dmt.h"
- #include "vms/dst.h"
- #include "vms/eihvn.h"
- #include "vms/eobjrec.h"
- #include "vms/egsd.h"
- #include "vms/egps.h"
- #include "vms/esgps.h"
- #include "vms/eeom.h"
- #include "vms/emh.h"
- #include "vms/eiaf.h"
- #include "vms/shl.h"
- #include "vms/eicp.h"
- #include "vms/etir.h"
- #include "vms/egsy.h"
- #include "vms/esdf.h"
- #include "vms/esdfm.h"
- #include "vms/esdfv.h"
- #include "vms/esrf.h"
- #include "vms/egst.h"
- #include "vms/eidc.h"
- #include "vms/dsc.h"
- #include "vms/prt.h"
- #include "vms/internal.h"
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #ifndef CHAR_BIT
- #define CHAR_BIT 8
- #endif
- /* The r_type field in a reloc is one of the following values. */
- #define ALPHA_R_IGNORE 0
- #define ALPHA_R_REFQUAD 1
- #define ALPHA_R_BRADDR 2
- #define ALPHA_R_HINT 3
- #define ALPHA_R_SREL16 4
- #define ALPHA_R_SREL32 5
- #define ALPHA_R_SREL64 6
- #define ALPHA_R_OP_PUSH 7
- #define ALPHA_R_OP_STORE 8
- #define ALPHA_R_OP_PSUB 9
- #define ALPHA_R_OP_PRSHIFT 10
- #define ALPHA_R_LINKAGE 11
- #define ALPHA_R_REFLONG 12
- #define ALPHA_R_CODEADDR 13
- #define ALPHA_R_NOP 14
- #define ALPHA_R_BSR 15
- #define ALPHA_R_LDA 16
- #define ALPHA_R_BOH 17
- /* These are used with DST_S_C_LINE_NUM. */
- #define DST_S_C_LINE_NUM_HEADER_SIZE 4
- /* These are used with DST_S_C_SOURCE */
- #define DST_S_B_PCLINE_UNSBYTE 1
- #define DST_S_W_PCLINE_UNSWORD 1
- #define DST_S_L_PCLINE_UNSLONG 1
- #define DST_S_B_MODBEG_NAME 14
- #define DST_S_L_RTNBEG_ADDRESS 5
- #define DST_S_B_RTNBEG_NAME 13
- #define DST_S_L_RTNEND_SIZE 5
- /* These are used with DST_S_C_SOURCE. */
- #define DST_S_C_SOURCE_HEADER_SIZE 4
- #define DST_S_B_SRC_DF_LENGTH 1
- #define DST_S_W_SRC_DF_FILEID 3
- #define DST_S_B_SRC_DF_FILENAME 20
- #define DST_S_B_SRC_UNSBYTE 1
- #define DST_S_W_SRC_UNSWORD 1
- #define DST_S_L_SRC_UNSLONG 1
- /* Debugger symbol definitions. */
- #define DBG_S_L_DMT_MODBEG 0
- #define DBG_S_L_DST_SIZE 4
- #define DBG_S_W_DMT_PSECT_COUNT 8
- #define DBG_S_C_DMT_HEADER_SIZE 12
- #define DBG_S_L_DMT_PSECT_START 0
- #define DBG_S_L_DMT_PSECT_LENGTH 4
- #define DBG_S_C_DMT_PSECT_SIZE 8
- /* VMS module header. */
- struct hdr_struct
- {
- char hdr_b_strlvl;
- int hdr_l_arch1;
- int hdr_l_arch2;
- int hdr_l_recsiz;
- char *hdr_t_name;
- char *hdr_t_version;
- char *hdr_t_date;
- char *hdr_c_lnm;
- char *hdr_c_src;
- char *hdr_c_ttl;
- };
- #define EMH_DATE_LENGTH 17
- /* VMS End-Of-Module records (EOM/EEOM). */
- struct eom_struct
- {
- unsigned int eom_l_total_lps;
- unsigned short eom_w_comcod;
- bool eom_has_transfer;
- unsigned char eom_b_tfrflg;
- unsigned int eom_l_psindx;
- unsigned int eom_l_tfradr;
- };
- struct vms_symbol_entry
- {
- bfd *owner;
- /* Common fields. */
- unsigned char typ;
- unsigned char data_type;
- unsigned short flags;
- /* Section and offset/value of the symbol. */
- unsigned int value;
- asection *section;
- /* Section and offset/value for the entry point (only for subprg). */
- asection *code_section;
- unsigned int code_value;
- /* Symbol vector offset. */
- unsigned int symbol_vector;
- /* Length of the name. */
- unsigned char namelen;
- char name[1];
- };
- /* Stack value for push/pop commands. */
- struct stack_struct
- {
- bfd_vma value;
- unsigned int reloc;
- };
- #define STACKSIZE 128
- /* A minimal decoding of DST compilation units. We only decode
- what's needed to get to the line number information. */
- struct fileinfo
- {
- char *name;
- unsigned int srec;
- };
- struct srecinfo
- {
- struct srecinfo *next;
- unsigned int line;
- unsigned int sfile;
- unsigned int srec;
- };
- struct lineinfo
- {
- struct lineinfo *next;
- bfd_vma address;
- unsigned int line;
- };
- struct funcinfo
- {
- struct funcinfo *next;
- char *name;
- bfd_vma low;
- bfd_vma high;
- };
- struct module
- {
- /* Chain the previously read compilation unit. */
- struct module *next;
- /* The module name. */
- char *name;
- /* The start offset and size of debug info in the DST section. */
- unsigned int modbeg;
- unsigned int size;
- /* The lowest and highest addresses contained in this compilation
- unit as specified in the compilation unit header. */
- bfd_vma low;
- bfd_vma high;
- /* The listing line table. */
- struct lineinfo *line_table;
- /* The source record table. */
- struct srecinfo *srec_table;
- /* A list of the functions found in this module. */
- struct funcinfo *func_table;
- /* Current allocation of file_table. */
- unsigned int file_table_count;
- /* An array of the files making up this module. */
- struct fileinfo *file_table;
- };
- /* BFD private data for alpha-vms. */
- struct vms_private_data_struct
- {
- /* If true, relocs have been read. */
- bool reloc_done;
- /* Record input buffer. */
- struct vms_rec_rd recrd;
- struct vms_rec_wr recwr;
- struct hdr_struct hdr_data; /* data from HDR/EMH record */
- struct eom_struct eom_data; /* data from EOM/EEOM record */
- /* Transfer addresses (entry points). */
- bfd_vma transfer_address[4];
- /* Array of GSD sections to get the correspond BFD one. */
- unsigned int section_max; /* Size of the sections array. */
- unsigned int section_count; /* Number of GSD sections. */
- asection **sections;
- /* Array of raw symbols. */
- struct vms_symbol_entry **syms;
- /* Canonicalized symbols. */
- asymbol **csymbols;
- /* Number of symbols. */
- unsigned int gsd_sym_count;
- /* Size of the syms array. */
- unsigned int max_sym_count;
- /* Number of procedure symbols. */
- unsigned int norm_sym_count;
- /* Stack used to evaluate TIR/ETIR commands. */
- struct stack_struct *stack;
- int stackptr;
- /* Content reading. */
- asection *image_section; /* section for image_ptr */
- file_ptr image_offset; /* Offset for image_ptr. */
- struct module *modules; /* list of all compilation units */
- /* The DST section. */
- asection *dst_section;
- unsigned int dst_ptr_offsets_count; /* # of offsets in following array */
- unsigned int *dst_ptr_offsets; /* array of saved image_ptr offsets */
- /* Shared library support */
- bfd_vma symvva; /* relative virtual address of symbol vector */
- unsigned int ident;
- unsigned char matchctl;
- /* Shared library index. This is used for input bfd while linking. */
- unsigned int shr_index;
- /* Used to place structures in the file. */
- file_ptr file_pos;
- /* Simply linked list of eisd. */
- struct vms_internal_eisd_map *eisd_head;
- struct vms_internal_eisd_map *eisd_tail;
- /* Simply linked list of eisd for shared libraries. */
- struct vms_internal_eisd_map *gbl_eisd_head;
- struct vms_internal_eisd_map *gbl_eisd_tail;
- /* linkage index counter used by conditional store commands */
- unsigned int vms_linkage_index;
- };
- #define PRIV2(abfd, name) \
- (((struct vms_private_data_struct *)(abfd)->tdata.any)->name)
- #define PRIV(name) PRIV2(abfd,name)
- /* Used to keep extra VMS specific information for a given section.
- reloc_size holds the size of the relocation stream, note this
- is very different from the number of relocations as VMS relocations
- are variable length.
- reloc_stream is the actual stream of relocation entries. */
- struct vms_section_data_struct
- {
- /* Maximnum number of entries in sec->relocation. */
- unsigned reloc_max;
- /* Corresponding eisd. Used only while generating executables. */
- struct vms_internal_eisd_map *eisd;
- /* PSC flags to be clear. */
- flagword no_flags;
- /* PSC flags to be set. */
- flagword flags;
- };
- #define vms_section_data(sec) \
- ((struct vms_section_data_struct *)sec->used_by_bfd)
- /* To be called from the debugger. */
- struct vms_private_data_struct *bfd_vms_get_data (bfd *);
- static int vms_get_remaining_object_record (bfd *, unsigned int);
- static bool _bfd_vms_slurp_object_records (bfd * abfd);
- static bool alpha_vms_add_fixup_lp (struct bfd_link_info *, bfd *, bfd *);
- static bool alpha_vms_add_fixup_ca (struct bfd_link_info *, bfd *, bfd *);
- static bool alpha_vms_add_fixup_qr (struct bfd_link_info *, bfd *, bfd *,
- bfd_vma);
- static bool alpha_vms_add_fixup_lr (struct bfd_link_info *, unsigned int,
- bfd_vma);
- static bool alpha_vms_add_lw_reloc (struct bfd_link_info *);
- static bool alpha_vms_add_qw_reloc (struct bfd_link_info *);
- struct vector_type
- {
- unsigned int max_el;
- unsigned int nbr_el;
- void *els;
- };
- /* Number of elements in VEC. */
- #define VEC_COUNT(VEC) ((VEC).nbr_el)
- /* Get the address of the Nth element. */
- #define VEC_EL(VEC, TYPE, N) (((TYPE *)((VEC).els))[N])
- #define VEC_INIT(VEC) \
- do { \
- (VEC).max_el = 0; \
- (VEC).nbr_el = 0; \
- (VEC).els = NULL; \
- } while (0)
- /* Be sure there is room for a new element. */
- static void *vector_grow1 (struct vector_type *vec, size_t elsz);
- /* Allocate room for a new element and return its address. */
- #define VEC_APPEND(VEC, TYPE) \
- ((TYPE *) vector_grow1 (&VEC, sizeof (TYPE)))
- struct alpha_vms_vma_ref
- {
- bfd_vma vma; /* Vma in the output. */
- bfd_vma ref; /* Reference in the input. */
- };
- struct alpha_vms_shlib_el
- {
- bfd *abfd;
- bool has_fixups;
- struct vector_type lp; /* Vector of bfd_vma. */
- struct vector_type ca; /* Vector of bfd_vma. */
- struct vector_type qr; /* Vector of struct alpha_vms_vma_ref. */
- };
- /* Alpha VMS linker hash table. */
- struct alpha_vms_link_hash_table
- {
- struct bfd_link_hash_table root;
- /* Vector of shared libraries. */
- struct vector_type shrlibs;
- /* Fixup section. */
- asection *fixup;
- /* Base address. Used by fixups. */
- bfd_vma base_addr;
- };
- #define alpha_vms_link_hash(INFO) \
- ((struct alpha_vms_link_hash_table *)(INFO->hash))
- /* Alpha VMS linker hash table entry. */
- struct alpha_vms_link_hash_entry
- {
- struct bfd_link_hash_entry root;
- /* Pointer to the original vms symbol. */
- struct vms_symbol_entry *sym;
- };
- /* Image reading. */
- /* Read & process EIHD record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_eihd (bfd *abfd, unsigned int *eisd_offset,
- unsigned int *eihs_offset)
- {
- unsigned int imgtype, size;
- bfd_vma symvva;
- struct vms_eihd *eihd = (struct vms_eihd *)PRIV (recrd.rec);
- vms_debug2 ((8, "_bfd_vms_slurp_eihd\n"));
- /* PR 21813: Check for an undersized record. */
- if (PRIV (recrd.buf_size) < sizeof (* eihd))
- {
- _bfd_error_handler (_("corrupt EIHD record - size is too small"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- size = bfd_getl32 (eihd->size);
- imgtype = bfd_getl32 (eihd->imgtype);
- if (imgtype == EIHD__K_EXE || imgtype == EIHD__K_LIM)
- abfd->flags |= EXEC_P;
- symvva = bfd_getl64 (eihd->symvva);
- if (symvva != 0)
- {
- PRIV (symvva) = symvva;
- abfd->flags |= DYNAMIC;
- }
- PRIV (ident) = bfd_getl32 (eihd->ident);
- PRIV (matchctl) = eihd->matchctl;
- *eisd_offset = bfd_getl32 (eihd->isdoff);
- *eihs_offset = bfd_getl32 (eihd->symdbgoff);
- vms_debug2 ((4, "EIHD size %d imgtype %d symvva 0x%lx eisd %d eihs %d\n",
- size, imgtype, (unsigned long)symvva,
- *eisd_offset, *eihs_offset));
- (void) size;
- return true;
- }
- /* Read & process EISD record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_eisd (bfd *abfd, unsigned int offset)
- {
- int section_count = 0;
- vms_debug2 ((8, "_bfd_vms_slurp_eisd\n"));
- while (1)
- {
- struct vms_eisd *eisd;
- unsigned int rec_size;
- unsigned int size;
- bfd_uint64_t vaddr;
- unsigned int flags;
- unsigned int vbn;
- char *name = NULL;
- asection *section;
- flagword bfd_flags;
- /* PR 17512: file: 3d9e9fe9. */
- if (offset > PRIV (recrd.rec_size)
- || (PRIV (recrd.rec_size) - offset
- < offsetof (struct vms_eisd, eisdsize) + 4))
- return false;
- eisd = (struct vms_eisd *) (PRIV (recrd.rec) + offset);
- rec_size = bfd_getl32 (eisd->eisdsize);
- if (rec_size == 0)
- break;
- /* Skip to next block if pad. */
- if (rec_size == 0xffffffff)
- {
- offset = (offset + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
- continue;
- }
- /* Make sure that there is enough data present in the record. */
- if (rec_size < offsetof (struct vms_eisd, type) + 1)
- return false;
- /* Make sure that the record is not too big either. */
- if (rec_size > PRIV (recrd.rec_size) - offset)
- return false;
- offset += rec_size;
- size = bfd_getl32 (eisd->secsize);
- vaddr = bfd_getl64 (eisd->virt_addr);
- flags = bfd_getl32 (eisd->flags);
- vbn = bfd_getl32 (eisd->vbn);
- vms_debug2 ((4, "EISD at 0x%x size 0x%x addr 0x%lx flags 0x%x blk %d\n",
- offset, size, (unsigned long)vaddr, flags, vbn));
- /* VMS combines psects from .obj files into isects in the .exe. This
- process doesn't preserve enough information to reliably determine
- what's in each section without examining the data. This is
- especially true of DWARF debug sections. */
- bfd_flags = SEC_ALLOC;
- if (vbn != 0)
- bfd_flags |= SEC_HAS_CONTENTS | SEC_LOAD;
- if (flags & EISD__M_EXE)
- bfd_flags |= SEC_CODE;
- if (flags & EISD__M_NONSHRADR)
- bfd_flags |= SEC_DATA;
- if (!(flags & EISD__M_WRT))
- bfd_flags |= SEC_READONLY;
- if (flags & EISD__M_DZRO)
- bfd_flags |= SEC_DATA;
- if (flags & EISD__M_FIXUPVEC)
- bfd_flags |= SEC_DATA;
- if (flags & EISD__M_CRF)
- bfd_flags |= SEC_DATA;
- if (flags & EISD__M_GBL)
- {
- if (rec_size <= offsetof (struct vms_eisd, gblnam))
- return false;
- else if (rec_size < sizeof (struct vms_eisd))
- name = _bfd_vms_save_counted_string (abfd, eisd->gblnam,
- rec_size - offsetof (struct vms_eisd, gblnam));
- else
- name = _bfd_vms_save_counted_string (abfd, eisd->gblnam,
- EISD__K_GBLNAMLEN);
- if (name == NULL || name[0] == 0)
- return false;
- bfd_flags |= SEC_COFF_SHARED_LIBRARY;
- bfd_flags &= ~(SEC_ALLOC | SEC_LOAD);
- }
- else if (flags & EISD__M_FIXUPVEC)
- name = "$FIXUPVEC$";
- else if (eisd->type == EISD__K_USRSTACK)
- name = "$STACK$";
- else
- {
- const char *pfx;
- name = (char *) bfd_alloc (abfd, 32);
- if (name == NULL)
- return false;
- if (flags & EISD__M_DZRO)
- pfx = "BSS";
- else if (flags & EISD__M_EXE)
- pfx = "CODE";
- else if (!(flags & EISD__M_WRT))
- pfx = "RO";
- else
- pfx = "LOCAL";
- BFD_ASSERT (section_count < 999);
- sprintf (name, "$%s_%03d$", pfx, section_count++);
- }
- section = bfd_make_section (abfd, name);
- if (!section)
- return false;
- section->filepos = vbn ? VMS_BLOCK_SIZE * (vbn - 1) : 0;
- section->size = size;
- section->vma = vaddr;
- if (!bfd_set_section_flags (section, bfd_flags))
- return false;
- }
- return true;
- }
- /* Read & process EIHS record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_eihs (bfd *abfd, unsigned int offset)
- {
- unsigned char *p = PRIV (recrd.rec) + offset;
- unsigned int gstvbn;
- unsigned int gstsize ATTRIBUTE_UNUSED;
- unsigned int dstvbn;
- unsigned int dstsize;
- unsigned int dmtvbn;
- unsigned int dmtbytes;
- asection *section;
- /* PR 21611: Check that offset is valid. */
- if (offset > PRIV (recrd.rec_size) - (EIHS__L_DMTBYTES + 4))
- {
- _bfd_error_handler (_("unable to read EIHS record at offset %#x"),
- offset);
- bfd_set_error (bfd_error_file_truncated);
- return false;
- }
- gstvbn = bfd_getl32 (p + EIHS__L_GSTVBN);
- gstsize = bfd_getl32 (p + EIHS__L_GSTSIZE);
- dstvbn = bfd_getl32 (p + EIHS__L_DSTVBN);
- dstsize = bfd_getl32 (p + EIHS__L_DSTSIZE);
- dmtvbn = bfd_getl32 (p + EIHS__L_DMTVBN);
- dmtbytes = bfd_getl32 (p + EIHS__L_DMTBYTES);
- #if VMS_DEBUG
- vms_debug (8, "_bfd_vms_slurp_ihs\n");
- vms_debug (4, "EIHS record gstvbn %d gstsize %d dstvbn %d dstsize %d dmtvbn %d dmtbytes %d\n",
- gstvbn, gstsize, dstvbn, dstsize, dmtvbn, dmtbytes);
- #endif
- if (dstvbn)
- {
- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
- section = bfd_make_section (abfd, "$DST$");
- if (!section)
- return false;
- section->size = dstsize;
- section->filepos = VMS_BLOCK_SIZE * (dstvbn - 1);
- if (!bfd_set_section_flags (section, bfd_flags))
- return false;
- PRIV (dst_section) = section;
- abfd->flags |= (HAS_DEBUG | HAS_LINENO);
- }
- if (dmtvbn)
- {
- flagword bfd_flags = SEC_HAS_CONTENTS | SEC_DEBUGGING;
- section = bfd_make_section (abfd, "$DMT$");
- if (!section)
- return false;
- section->size = dmtbytes;
- section->filepos = VMS_BLOCK_SIZE * (dmtvbn - 1);
- if (!bfd_set_section_flags (section, bfd_flags))
- return false;
- }
- if (gstvbn)
- {
- if (bfd_seek (abfd, VMS_BLOCK_SIZE * (gstvbn - 1), SEEK_SET))
- {
- bfd_set_error (bfd_error_file_truncated);
- return false;
- }
- if (!_bfd_vms_slurp_object_records (abfd))
- return false;
- abfd->flags |= HAS_SYMS;
- }
- return true;
- }
- /* Object file reading. */
- /* Object file input functions. */
- /* Get next record from object file to vms_buf.
- Set PRIV(buf_size) and return it
- This is a little tricky since it should be portable.
- The openVMS object file has 'variable length' which means that
- read() returns data in chunks of (hopefully) correct and expected
- size. The linker (and other tools on VMS) depend on that. Unix
- doesn't know about 'formatted' files, so reading and writing such
- an object file in a Unix environment is not trivial.
- With the tool 'file' (available on all VMS FTP sites), one
- can view and change the attributes of a file. Changing from
- 'variable length' to 'fixed length, 512 bytes' reveals the
- record size at the first 2 bytes of every record. The same
- may happen during the transfer of object files from VMS to Unix,
- at least with UCX, the DEC implementation of TCP/IP.
- The VMS format repeats the size at bytes 2 & 3 of every record.
- On the first call (file_format == FF_UNKNOWN) we check if
- the first and the third byte pair (!) of the record match.
- If they do it's an object file in an Unix environment or with
- wrong attributes (FF_FOREIGN), else we should be in a VMS
- environment where read() returns the record size (FF_NATIVE).
- Reading is always done in 2 steps:
- 1. first just the record header is read and the size extracted,
- 2. then the read buffer is adjusted and the remaining bytes are
- read in.
- All file I/O is done on even file positions. */
- #define VMS_OBJECT_ADJUSTMENT 2
- static void
- maybe_adjust_record_pointer_for_object (bfd *abfd)
- {
- /* Set the file format once for all on the first invocation. */
- if (PRIV (recrd.file_format) == FF_UNKNOWN)
- {
- if (PRIV (recrd.rec)[0] == PRIV (recrd.rec)[4]
- && PRIV (recrd.rec)[1] == PRIV (recrd.rec)[5])
- PRIV (recrd.file_format) = FF_FOREIGN;
- else
- PRIV (recrd.file_format) = FF_NATIVE;
- }
- /* The adjustment is needed only in an Unix environment. */
- if (PRIV (recrd.file_format) == FF_FOREIGN)
- PRIV (recrd.rec) += VMS_OBJECT_ADJUSTMENT;
- }
- /* Implement step #1 of the object record reading procedure.
- Return the record type or -1 on failure. */
- static int
- _bfd_vms_get_object_record (bfd *abfd)
- {
- unsigned int test_len = 6;
- int type;
- vms_debug2 ((8, "_bfd_vms_get_obj_record\n"));
- /* Skip alignment byte if the current position is odd. */
- if (PRIV (recrd.file_format) == FF_FOREIGN && (bfd_tell (abfd) & 1))
- {
- if (bfd_bread (PRIV (recrd.buf), 1, abfd) != 1)
- {
- bfd_set_error (bfd_error_file_truncated);
- return -1;
- }
- }
- /* Read the record header */
- if (bfd_bread (PRIV (recrd.buf), test_len, abfd) != test_len)
- {
- bfd_set_error (bfd_error_file_truncated);
- return -1;
- }
- /* Reset the record pointer. */
- PRIV (recrd.rec) = PRIV (recrd.buf);
- maybe_adjust_record_pointer_for_object (abfd);
- if (vms_get_remaining_object_record (abfd, test_len) <= 0)
- return -1;
- type = bfd_getl16 (PRIV (recrd.rec));
- vms_debug2 ((8, "_bfd_vms_get_obj_record: rec %p, size %d, type %d\n",
- PRIV (recrd.rec), PRIV (recrd.rec_size), type));
- return type;
- }
- /* Implement step #2 of the object record reading procedure.
- Return the size of the record or 0 on failure. */
- static int
- vms_get_remaining_object_record (bfd *abfd, unsigned int read_so_far)
- {
- unsigned int to_read;
- vms_debug2 ((8, "vms_get_remaining_obj_record\n"));
- /* Extract record size. */
- PRIV (recrd.rec_size) = bfd_getl16 (PRIV (recrd.rec) + 2);
- if (PRIV (recrd.rec_size) == 0)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- /* That's what the linker manual says. */
- if (PRIV (recrd.rec_size) > EOBJ__C_MAXRECSIZ)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- /* Take into account object adjustment. */
- to_read = PRIV (recrd.rec_size);
- if (PRIV (recrd.file_format) == FF_FOREIGN)
- to_read += VMS_OBJECT_ADJUSTMENT;
- /* Adjust the buffer. */
- if (to_read > PRIV (recrd.buf_size))
- {
- PRIV (recrd.buf)
- = (unsigned char *) bfd_realloc_or_free (PRIV (recrd.buf), to_read);
- if (PRIV (recrd.buf) == NULL)
- return 0;
- PRIV (recrd.buf_size) = to_read;
- }
- /* PR 17512: file: 025-1974-0.004. */
- else if (to_read <= read_so_far)
- return 0;
- /* Read the remaining record. */
- to_read -= read_so_far;
- vms_debug2 ((8, "vms_get_remaining_obj_record: to_read %d\n", to_read));
- if (bfd_bread (PRIV (recrd.buf) + read_so_far, to_read, abfd) != to_read)
- {
- bfd_set_error (bfd_error_file_truncated);
- return 0;
- }
- /* Reset the record pointer. */
- PRIV (recrd.rec) = PRIV (recrd.buf);
- maybe_adjust_record_pointer_for_object (abfd);
- vms_debug2 ((8, "vms_get_remaining_obj_record: size %d\n",
- PRIV (recrd.rec_size)));
- return PRIV (recrd.rec_size);
- }
- /* Read and process emh record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_ehdr (bfd *abfd)
- {
- unsigned char *ptr;
- unsigned char *vms_rec;
- unsigned char *end;
- int subtype;
- vms_rec = PRIV (recrd.rec);
- /* PR 17512: file: 62736583. */
- end = PRIV (recrd.buf) + PRIV (recrd.buf_size);
- vms_debug2 ((2, "HDR/EMH\n"));
- subtype = bfd_getl16 (vms_rec + 4);
- vms_debug2 ((3, "subtype %d\n", subtype));
- switch (subtype)
- {
- case EMH__C_MHD:
- /* Module header. */
- if (vms_rec + 21 >= end)
- goto fail;
- PRIV (hdr_data).hdr_b_strlvl = vms_rec[6];
- PRIV (hdr_data).hdr_l_arch1 = bfd_getl32 (vms_rec + 8);
- PRIV (hdr_data).hdr_l_arch2 = bfd_getl32 (vms_rec + 12);
- PRIV (hdr_data).hdr_l_recsiz = bfd_getl32 (vms_rec + 16);
- if ((vms_rec + 20 + vms_rec[20] + 1) >= end)
- goto fail;
- PRIV (hdr_data).hdr_t_name
- = _bfd_vms_save_counted_string (abfd, vms_rec + 20, vms_rec[20]);
- ptr = vms_rec + 20 + vms_rec[20] + 1;
- if ((ptr + *ptr + 1) >= end)
- goto fail;
- PRIV (hdr_data).hdr_t_version
- = _bfd_vms_save_counted_string (abfd, ptr, *ptr);
- ptr += *ptr + 1;
- if (ptr + 17 >= end)
- goto fail;
- PRIV (hdr_data).hdr_t_date
- = _bfd_vms_save_sized_string (abfd, ptr, 17);
- break;
- case EMH__C_LNM:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
- PRIV (hdr_data).hdr_c_lnm
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
- break;
- case EMH__C_SRC:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
- PRIV (hdr_data).hdr_c_src
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
- break;
- case EMH__C_TTL:
- if (vms_rec + PRIV (recrd.rec_size - 6) > end)
- goto fail;
- PRIV (hdr_data).hdr_c_ttl
- = _bfd_vms_save_sized_string (abfd, vms_rec, PRIV (recrd.rec_size - 6));
- break;
- case EMH__C_CPR:
- case EMH__C_MTC:
- case EMH__C_GTX:
- break;
- default:
- fail:
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
- return true;
- }
- /* Typical sections for evax object files. */
- #define EVAX_ABS_NAME "$ABS$"
- #define EVAX_CODE_NAME "$CODE$"
- #define EVAX_LINK_NAME "$LINK$"
- #define EVAX_DATA_NAME "$DATA$"
- #define EVAX_BSS_NAME "$BSS$"
- #define EVAX_READONLYADDR_NAME "$READONLY_ADDR$"
- #define EVAX_READONLY_NAME "$READONLY$"
- #define EVAX_LITERAL_NAME "$LITERAL$"
- #define EVAX_LITERALS_NAME "$LITERALS"
- #define EVAX_COMMON_NAME "$COMMON$"
- #define EVAX_LOCAL_NAME "$LOCAL$"
- struct sec_flags_struct
- {
- const char *name; /* Name of section. */
- int vflags_always;
- flagword flags_always; /* Flags we set always. */
- int vflags_hassize;
- flagword flags_hassize; /* Flags we set if the section has a size > 0. */
- };
- /* These flags are deccrtl/vaxcrtl (openVMS 6.2 Alpha) compatible. */
- static const struct sec_flags_struct evax_section_flags[] =
- {
- { EVAX_ABS_NAME,
- EGPS__V_SHR,
- 0,
- EGPS__V_SHR,
- 0 },
- { EVAX_CODE_NAME,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
- SEC_CODE | SEC_READONLY,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_EXE,
- SEC_CODE | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_LITERAL_NAME,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD,
- SEC_DATA | SEC_READONLY,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD,
- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_LINK_NAME,
- EGPS__V_REL | EGPS__V_RD,
- SEC_DATA | SEC_READONLY,
- EGPS__V_REL | EGPS__V_RD,
- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_DATA_NAME,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD,
- SEC_DATA,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_BSS_NAME,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD,
- SEC_NO_FLAGS,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT | EGPS__V_NOMOD,
- SEC_ALLOC },
- { EVAX_READONLYADDR_NAME,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD,
- SEC_DATA | SEC_READONLY,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_RD,
- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_READONLY_NAME,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD | EGPS__V_NOMOD,
- SEC_DATA | SEC_READONLY,
- EGPS__V_PIC | EGPS__V_REL | EGPS__V_SHR | EGPS__V_RD,
- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_LOCAL_NAME,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
- SEC_DATA,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { EVAX_LITERALS_NAME,
- EGPS__V_PIC | EGPS__V_OVR,
- SEC_DATA | SEC_READONLY,
- EGPS__V_PIC | EGPS__V_OVR,
- SEC_DATA | SEC_READONLY | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD },
- { NULL,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
- SEC_DATA,
- EGPS__V_REL | EGPS__V_RD | EGPS__V_WRT,
- SEC_DATA | SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD }
- };
- /* Retrieve BFD section flags by name and size. */
- static flagword
- vms_secflag_by_name (const struct sec_flags_struct *section_flags,
- const char *name,
- int hassize)
- {
- int i = 0;
- while (section_flags[i].name != NULL)
- {
- if (strcmp (name, section_flags[i].name) == 0)
- {
- if (hassize)
- return section_flags[i].flags_hassize;
- else
- return section_flags[i].flags_always;
- }
- i++;
- }
- if (hassize)
- return section_flags[i].flags_hassize;
- return section_flags[i].flags_always;
- }
- /* Retrieve VMS section flags by name and size. */
- static flagword
- vms_esecflag_by_name (const struct sec_flags_struct *section_flags,
- const char *name,
- int hassize)
- {
- int i = 0;
- while (section_flags[i].name != NULL)
- {
- if (strcmp (name, section_flags[i].name) == 0)
- {
- if (hassize)
- return section_flags[i].vflags_hassize;
- else
- return section_flags[i].vflags_always;
- }
- i++;
- }
- if (hassize)
- return section_flags[i].vflags_hassize;
- return section_flags[i].vflags_always;
- }
- /* Add SYM to the symbol table of ABFD.
- Return FALSE in case of error. */
- static bool
- add_symbol_entry (bfd *abfd, struct vms_symbol_entry *sym)
- {
- if (PRIV (gsd_sym_count) >= PRIV (max_sym_count))
- {
- if (PRIV (max_sym_count) == 0)
- {
- PRIV (max_sym_count) = 128;
- PRIV (syms) = bfd_malloc
- (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *));
- }
- else
- {
- PRIV (max_sym_count) *= 2;
- PRIV (syms) = bfd_realloc_or_free
- (PRIV (syms),
- (PRIV (max_sym_count) * sizeof (struct vms_symbol_entry *)));
- }
- if (PRIV (syms) == NULL)
- return false;
- }
- PRIV (syms)[PRIV (gsd_sym_count)++] = sym;
- return true;
- }
- /* Create a symbol whose name is ASCIC and add it to ABFD.
- Return NULL in case of error. */
- static struct vms_symbol_entry *
- add_symbol (bfd *abfd, const unsigned char *ascic, unsigned int max)
- {
- struct vms_symbol_entry *entry;
- unsigned int len;
- len = *ascic++;
- max -= 1;
- if (len > max)
- {
- _bfd_error_handler (_("record is too small for symbol name length"));
- bfd_set_error (bfd_error_bad_value);
- return NULL;
- }
- entry = (struct vms_symbol_entry *)bfd_zalloc (abfd, sizeof (*entry) + len);
- if (entry == NULL)
- return NULL;
- entry->namelen = len;
- memcpy (entry->name, ascic, len);
- entry->name[len] = 0;
- entry->owner = abfd;
- if (!add_symbol_entry (abfd, entry))
- return NULL;
- return entry;
- }
- /* Read and process EGSD. Return FALSE on failure. */
- static bool
- _bfd_vms_slurp_egsd (bfd *abfd)
- {
- int gsd_type;
- unsigned int gsd_size;
- unsigned char *vms_rec;
- bfd_vma base_addr;
- long psindx;
- vms_debug2 ((2, "EGSD\n"));
- if (PRIV (recrd.rec_size) < 8)
- {
- _bfd_error_handler (_("corrupt EGSD record: its size (%#x) is too small"),
- PRIV (recrd.rec_size));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- PRIV (recrd.rec) += 8; /* Skip type, size, align pad. */
- PRIV (recrd.rec_size) -= 8;
- /* Calculate base address for each section. */
- base_addr = 0;
- while (PRIV (recrd.rec_size) > 4)
- {
- vms_rec = PRIV (recrd.rec);
- gsd_type = bfd_getl16 (vms_rec);
- gsd_size = bfd_getl16 (vms_rec + 2);
- vms_debug2 ((3, "egsd_type %d\n", gsd_type));
- /* PR 21615: Check for size overflow. */
- if (PRIV (recrd.rec_size) < gsd_size)
- {
- _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) "
- "is larger than remaining space (%#x)"),
- gsd_type, gsd_size, PRIV (recrd.rec_size));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- if (gsd_size < 4)
- {
- too_small:
- _bfd_error_handler (_("corrupt EGSD record type %d: size (%#x) "
- "is too small"),
- gsd_type, gsd_size);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- switch (gsd_type)
- {
- case EGSD__C_PSC:
- /* Program section definition. */
- {
- struct vms_egps *egps = (struct vms_egps *) vms_rec;
- flagword new_flags, vms_flags;
- asection *section;
- if (offsetof (struct vms_egps, flags) + 2 > gsd_size)
- goto too_small;
- vms_flags = bfd_getl16 (egps->flags);
- if ((vms_flags & EGPS__V_REL) == 0)
- {
- /* Use the global absolute section for all
- absolute sections. */
- section = bfd_abs_section_ptr;
- }
- else
- {
- char *name;
- bfd_vma align_addr;
- size_t left;
- if (offsetof (struct vms_egps, namlng) >= gsd_size)
- goto too_small;
- left = gsd_size - offsetof (struct vms_egps, namlng);
- name = _bfd_vms_save_counted_string (abfd, &egps->namlng, left);
- if (name == NULL || name[0] == 0)
- return false;
- section = bfd_make_section (abfd, name);
- if (!section)
- return false;
- section->filepos = 0;
- section->size = bfd_getl32 (egps->alloc);
- section->alignment_power = egps->align & 31;
- vms_section_data (section)->flags = vms_flags;
- vms_section_data (section)->no_flags = 0;
- new_flags = vms_secflag_by_name (evax_section_flags,
- section->name,
- section->size > 0);
- if (section->size > 0)
- new_flags |= SEC_LOAD;
- if (!(vms_flags & EGPS__V_NOMOD) && section->size > 0)
- {
- /* Set RELOC and HAS_CONTENTS if the section is not
- demand-zero and not empty. */
- new_flags |= SEC_HAS_CONTENTS;
- if (vms_flags & EGPS__V_REL)
- new_flags |= SEC_RELOC;
- }
- if (vms_flags & EGPS__V_EXE)
- {
- /* Set CODE if section is executable. */
- new_flags |= SEC_CODE;
- new_flags &= ~SEC_DATA;
- }
- if (!bfd_set_section_flags (section, new_flags))
- return false;
- /* Give a non-overlapping vma to non absolute sections. */
- align_addr = (bfd_vma) 1 << section->alignment_power;
- base_addr = (base_addr + align_addr - 1) & -align_addr;
- section->vma = base_addr;
- base_addr += section->size;
- }
- /* Append it to the section array. */
- if (PRIV (section_count) >= PRIV (section_max))
- {
- if (PRIV (section_max) == 0)
- PRIV (section_max) = 16;
- else
- PRIV (section_max) *= 2;
- PRIV (sections) = bfd_realloc_or_free
- (PRIV (sections), PRIV (section_max) * sizeof (asection *));
- if (PRIV (sections) == NULL)
- return false;
- }
- PRIV (sections)[PRIV (section_count)] = section;
- PRIV (section_count)++;
- }
- break;
- case EGSD__C_SYM:
- {
- unsigned int nameoff;
- struct vms_symbol_entry *entry;
- struct vms_egsy *egsy = (struct vms_egsy *) vms_rec;
- flagword old_flags;
- if (offsetof (struct vms_egsy, flags) + 2 > gsd_size)
- goto too_small;
- old_flags = bfd_getl16 (egsy->flags);
- if (old_flags & EGSY__V_DEF)
- nameoff = ESDF__B_NAMLNG;
- else
- nameoff = ESRF__B_NAMLNG;
- if (nameoff >= gsd_size)
- goto too_small;
- entry = add_symbol (abfd, vms_rec + nameoff, gsd_size - nameoff);
- if (entry == NULL)
- return false;
- /* Allow only duplicate reference. */
- if ((entry->flags & EGSY__V_DEF) && (old_flags & EGSY__V_DEF))
- abort ();
- if (entry->typ == 0)
- {
- entry->typ = gsd_type;
- entry->data_type = egsy->datyp;
- entry->flags = old_flags;
- }
- if (old_flags & EGSY__V_DEF)
- {
- struct vms_esdf *esdf = (struct vms_esdf *) vms_rec;
- entry->value = bfd_getl64 (esdf->value);
- if (PRIV (sections) == NULL)
- return false;
- psindx = bfd_getl32 (esdf->psindx);
- /* PR 21813: Check for an out of range index. */
- if (psindx < 0 || psindx >= (int) PRIV (section_count))
- {
- bad_psindx:
- _bfd_error_handler (_("corrupt EGSD record: its psindx "
- "field is too big (%#lx)"),
- psindx);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- entry->section = PRIV (sections)[psindx];
- if (old_flags & EGSY__V_NORM)
- {
- PRIV (norm_sym_count)++;
- entry->code_value = bfd_getl64 (esdf->code_address);
- psindx = bfd_getl32 (esdf->ca_psindx);
- /* PR 21813: Check for an out of range index. */
- if (psindx < 0 || psindx >= (int) PRIV (section_count))
- goto bad_psindx;
- entry->code_section = PRIV (sections)[psindx];
- }
- }
- }
- break;
- case EGSD__C_SYMG:
- {
- struct vms_symbol_entry *entry;
- struct vms_egst *egst = (struct vms_egst *)vms_rec;
- flagword old_flags;
- unsigned int nameoff = offsetof (struct vms_egst, namlng);
- if (nameoff >= gsd_size)
- goto too_small;
- entry = add_symbol (abfd, &egst->namlng, gsd_size - nameoff);
- if (entry == NULL)
- return false;
- old_flags = bfd_getl16 (egst->header.flags);
- entry->typ = gsd_type;
- entry->data_type = egst->header.datyp;
- entry->flags = old_flags;
- entry->symbol_vector = bfd_getl32 (egst->value);
- if (old_flags & EGSY__V_REL)
- {
- if (PRIV (sections) == NULL)
- return false;
- psindx = bfd_getl32 (egst->psindx);
- /* PR 21813: Check for an out of range index. */
- if (psindx < 0 || psindx >= (int) PRIV (section_count))
- goto bad_psindx;
- entry->section = PRIV (sections)[psindx];
- }
- else
- entry->section = bfd_abs_section_ptr;
- entry->value = bfd_getl64 (egst->lp_2);
- if (old_flags & EGSY__V_NORM)
- {
- PRIV (norm_sym_count)++;
- entry->code_value = bfd_getl64 (egst->lp_1);
- entry->code_section = bfd_abs_section_ptr;
- }
- }
- break;
- case EGSD__C_SPSC:
- case EGSD__C_IDC:
- /* Currently ignored. */
- break;
- case EGSD__C_SYMM:
- case EGSD__C_SYMV:
- default:
- _bfd_error_handler (_("unknown EGSD subtype %d"), gsd_type);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- PRIV (recrd.rec_size) -= gsd_size;
- PRIV (recrd.rec) += gsd_size;
- }
- /* FIXME: Should we complain if PRIV (recrd.rec_size) is not zero ? */
- if (PRIV (gsd_sym_count) > 0)
- abfd->flags |= HAS_SYMS;
- return true;
- }
- /* Stack routines for vms ETIR commands. */
- /* Push value and section index. */
- static bool
- _bfd_vms_push (bfd *abfd, bfd_vma val, unsigned int reloc)
- {
- vms_debug2 ((4, "<push %08lx (0x%08x) at %d>\n",
- (unsigned long)val, reloc, PRIV (stackptr)));
- PRIV (stack[PRIV (stackptr)]).value = val;
- PRIV (stack[PRIV (stackptr)]).reloc = reloc;
- PRIV (stackptr)++;
- if (PRIV (stackptr) >= STACKSIZE)
- {
- bfd_set_error (bfd_error_bad_value);
- _bfd_error_handler (_("stack overflow (%d) in _bfd_vms_push"), PRIV (stackptr));
- return false;
- }
- return true;
- }
- /* Pop value and section index. */
- static bool
- _bfd_vms_pop (bfd *abfd, bfd_vma *val, unsigned int *rel)
- {
- if (PRIV (stackptr) == 0)
- {
- bfd_set_error (bfd_error_bad_value);
- _bfd_error_handler (_("stack underflow in _bfd_vms_pop"));
- return false;
- }
- PRIV (stackptr)--;
- *val = PRIV (stack[PRIV (stackptr)]).value;
- *rel = PRIV (stack[PRIV (stackptr)]).reloc;
- vms_debug2 ((4, "<pop %08lx (0x%08x)>\n", (unsigned long)*val, *rel));
- return true;
- }
- /* Routines to fill sections contents during tir/etir read. */
- /* Initialize image buffer pointer to be filled. */
- static void
- image_set_ptr (bfd *abfd, bfd_vma vma, int sect, struct bfd_link_info *info)
- {
- asection *sec;
- vms_debug2 ((4, "image_set_ptr (0x%08x, sect=%d)\n", (unsigned)vma, sect));
- if (PRIV (sections) == NULL)
- return;
- if (sect < 0 || sect >= (int) PRIV (section_count))
- return;
- sec = PRIV (sections)[sect];
- if (info)
- {
- /* Reading contents to an output bfd. */
- if (sec->output_section == NULL)
- {
- /* Section discarded. */
- vms_debug2 ((5, " section %s discarded\n", sec->name));
- /* This is not used. */
- PRIV (image_section) = NULL;
- PRIV (image_offset) = 0;
- return;
- }
- PRIV (image_offset) = sec->output_offset + vma;
- PRIV (image_section) = sec->output_section;
- }
- else
- {
- PRIV (image_offset) = vma;
- PRIV (image_section) = sec;
- }
- }
- /* Increment image buffer pointer by offset. */
- static void
- image_inc_ptr (bfd *abfd, bfd_vma offset)
- {
- vms_debug2 ((4, "image_inc_ptr (%u)\n", (unsigned)offset));
- PRIV (image_offset) += offset;
- }
- /* Save current DST location counter under specified index. */
- static bool
- dst_define_location (bfd *abfd, unsigned int loc)
- {
- vms_debug2 ((4, "dst_define_location (%d)\n", (int)loc));
- if (loc > 1 << 24)
- {
- /* 16M entries ought to be plenty. */
- bfd_set_error (bfd_error_bad_value);
- _bfd_error_handler (_("dst_define_location %u too large"), loc);
- return false;
- }
- /* Grow the ptr offset table if necessary. */
- if (loc + 1 > PRIV (dst_ptr_offsets_count))
- {
- PRIV (dst_ptr_offsets)
- = bfd_realloc_or_free (PRIV (dst_ptr_offsets),
- (loc + 1) * sizeof (unsigned int));
- if (PRIV (dst_ptr_offsets) == NULL)
- return false;
- PRIV (dst_ptr_offsets_count) = loc + 1;
- }
- PRIV (dst_ptr_offsets)[loc] = PRIV (image_offset);
- return true;
- }
- /* Restore saved DST location counter from specified index. */
- static bool
- dst_restore_location (bfd *abfd, unsigned int loc)
- {
- vms_debug2 ((4, "dst_restore_location (%d)\n", (int)loc));
- if (loc < PRIV (dst_ptr_offsets_count))
- {
- PRIV (image_offset) = PRIV (dst_ptr_offsets)[loc];
- return true;
- }
- return false;
- }
- /* Retrieve saved DST location counter from specified index. */
- static bool
- dst_retrieve_location (bfd *abfd, bfd_vma *loc)
- {
- vms_debug2 ((4, "dst_retrieve_location (%d)\n", (int) *loc));
- if (*loc < PRIV (dst_ptr_offsets_count))
- {
- *loc = PRIV (dst_ptr_offsets)[*loc];
- return true;
- }
- return false;
- }
- /* Write multiple bytes to section image. */
- static bool
- image_write (bfd *abfd, unsigned char *ptr, unsigned int size)
- {
- asection *sec = PRIV (image_section);
- size_t off = PRIV (image_offset);
- /* Check bounds. */
- if (off > sec->size
- || size > sec->size - off)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- #if VMS_DEBUG
- _bfd_vms_debug (8, "image_write from (%p, %d) to (%ld)\n", ptr, size,
- (long) off));
- #endif
- if (PRIV (image_section)->contents != NULL)
- memcpy (sec->contents + off, ptr, size);
- else
- {
- unsigned int i;
- for (i = 0; i < size; i++)
- if (ptr[i] != 0)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- }
- #if VMS_DEBUG
- _bfd_hexdump (9, ptr, size, 0);
- #endif
- PRIV (image_offset) += size;
- return true;
- }
- /* Write byte to section image. */
- static bool
- image_write_b (bfd * abfd, unsigned int value)
- {
- unsigned char data[1];
- vms_debug2 ((6, "image_write_b (%02x)\n", (int) value));
- *data = value;
- return image_write (abfd, data, sizeof (data));
- }
- /* Write 2-byte word to image. */
- static bool
- image_write_w (bfd * abfd, unsigned int value)
- {
- unsigned char data[2];
- vms_debug2 ((6, "image_write_w (%04x)\n", (int) value));
- bfd_putl16 (value, data);
- return image_write (abfd, data, sizeof (data));
- }
- /* Write 4-byte long to image. */
- static bool
- image_write_l (bfd * abfd, unsigned long value)
- {
- unsigned char data[4];
- vms_debug2 ((6, "image_write_l (%08lx)\n", value));
- bfd_putl32 (value, data);
- return image_write (abfd, data, sizeof (data));
- }
- /* Write 8-byte quad to image. */
- static bool
- image_write_q (bfd * abfd, bfd_vma value)
- {
- unsigned char data[8];
- vms_debug2 ((6, "image_write_q (%08lx)\n", (unsigned long)value));
- bfd_putl64 (value, data);
- return image_write (abfd, data, sizeof (data));
- }
- static const char *
- _bfd_vms_etir_name (int cmd)
- {
- switch (cmd)
- {
- case ETIR__C_STA_GBL: return "ETIR__C_STA_GBL";
- case ETIR__C_STA_LW: return "ETIR__C_STA_LW";
- case ETIR__C_STA_QW: return "ETIR__C_STA_QW";
- case ETIR__C_STA_PQ: return "ETIR__C_STA_PQ";
- case ETIR__C_STA_LI: return "ETIR__C_STA_LI";
- case ETIR__C_STA_MOD: return "ETIR__C_STA_MOD";
- case ETIR__C_STA_CKARG: return "ETIR__C_STA_CKARG";
- case ETIR__C_STO_B: return "ETIR__C_STO_B";
- case ETIR__C_STO_W: return "ETIR__C_STO_W";
- case ETIR__C_STO_GBL: return "ETIR__C_STO_GBL";
- case ETIR__C_STO_CA: return "ETIR__C_STO_CA";
- case ETIR__C_STO_RB: return "ETIR__C_STO_RB";
- case ETIR__C_STO_AB: return "ETIR__C_STO_AB";
- case ETIR__C_STO_OFF: return "ETIR__C_STO_OFF";
- case ETIR__C_STO_IMM: return "ETIR__C_STO_IMM";
- case ETIR__C_STO_IMMR: return "ETIR__C_STO_IMMR";
- case ETIR__C_STO_LW: return "ETIR__C_STO_LW";
- case ETIR__C_STO_QW: return "ETIR__C_STO_QW";
- case ETIR__C_STO_GBL_LW: return "ETIR__C_STO_GBL_LW";
- case ETIR__C_STO_LP_PSB: return "ETIR__C_STO_LP_PSB";
- case ETIR__C_STO_HINT_GBL: return "ETIR__C_STO_HINT_GBL";
- case ETIR__C_STO_HINT_PS: return "ETIR__C_STO_HINT_PS";
- case ETIR__C_OPR_ADD: return "ETIR__C_OPR_ADD";
- case ETIR__C_OPR_SUB: return "ETIR__C_OPR_SUB";
- case ETIR__C_OPR_INSV: return "ETIR__C_OPR_INSV";
- case ETIR__C_OPR_USH: return "ETIR__C_OPR_USH";
- case ETIR__C_OPR_ROT: return "ETIR__C_OPR_ROT";
- case ETIR__C_OPR_REDEF: return "ETIR__C_OPR_REDEF";
- case ETIR__C_OPR_DFLIT: return "ETIR__C_OPR_DFLIT";
- case ETIR__C_STC_LP: return "ETIR__C_STC_LP";
- case ETIR__C_STC_GBL: return "ETIR__C_STC_GBL";
- case ETIR__C_STC_GCA: return "ETIR__C_STC_GCA";
- case ETIR__C_STC_PS: return "ETIR__C_STC_PS";
- case ETIR__C_STC_NBH_PS: return "ETIR__C_STC_NBH_PS";
- case ETIR__C_STC_NOP_GBL: return "ETIR__C_STC_NOP_GBL";
- case ETIR__C_STC_NOP_PS: return "ETIR__C_STC_NOP_PS";
- case ETIR__C_STC_BSR_GBL: return "ETIR__C_STC_BSR_GBL";
- case ETIR__C_STC_BSR_PS: return "ETIR__C_STC_BSR_PS";
- case ETIR__C_STC_LDA_GBL: return "ETIR__C_STC_LDA_GBL";
- case ETIR__C_STC_LDA_PS: return "ETIR__C_STC_LDA_PS";
- case ETIR__C_STC_BOH_GBL: return "ETIR__C_STC_BOH_GBL";
- case ETIR__C_STC_BOH_PS: return "ETIR__C_STC_BOH_PS";
- case ETIR__C_STC_NBH_GBL: return "ETIR__C_STC_NBH_GBL";
- case ETIR__C_STC_LP_PSB: return "ETIR__C_STC_LP_PSB";
- case ETIR__C_CTL_SETRB: return "ETIR__C_CTL_SETRB";
- case ETIR__C_CTL_AUGRB: return "ETIR__C_CTL_AUGRB";
- case ETIR__C_CTL_DFLOC: return "ETIR__C_CTL_DFLOC";
- case ETIR__C_CTL_STLOC: return "ETIR__C_CTL_STLOC";
- case ETIR__C_CTL_STKDL: return "ETIR__C_CTL_STKDL";
- default:
- /* These names have not yet been added to this switch statement. */
- _bfd_error_handler (_("unknown ETIR command %d"), cmd);
- }
- return NULL;
- }
- #define HIGHBIT(op) ((op & 0x80000000L) == 0x80000000L)
- static void
- _bfd_vms_get_value (bfd *abfd,
- const unsigned char *ascic,
- const unsigned char *max_ascic,
- struct bfd_link_info *info,
- bfd_vma *vma,
- struct alpha_vms_link_hash_entry **hp)
- {
- char name[257];
- unsigned int len;
- unsigned int i;
- struct alpha_vms_link_hash_entry *h;
- /* Not linking. Do not try to resolve the symbol. */
- if (info == NULL)
- {
- *vma = 0;
- *hp = NULL;
- return;
- }
- len = *ascic;
- if (ascic + len >= max_ascic)
- {
- _bfd_error_handler (_("corrupt vms value"));
- *vma = 0;
- *hp = NULL;
- return;
- }
- for (i = 0; i < len; i++)
- name[i] = ascic[i + 1];
- name[i] = 0;
- h = (struct alpha_vms_link_hash_entry *)
- bfd_link_hash_lookup (info->hash, name, false, false, true);
- *hp = h;
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- *vma = h->root.u.def.value
- + h->root.u.def.section->output_offset
- + h->root.u.def.section->output_section->vma;
- else if (h && h->root.type == bfd_link_hash_undefweak)
- *vma = 0;
- else
- {
- (*info->callbacks->undefined_symbol)
- (info, name, abfd, PRIV (image_section), PRIV (image_offset), true);
- *vma = 0;
- }
- }
- #define RELC_NONE 0
- #define RELC_REL 1
- #define RELC_SHR_BASE 0x10000
- #define RELC_SEC_BASE 0x20000
- #define RELC_MASK 0x0ffff
- static unsigned int
- alpha_vms_sym_to_ctxt (struct alpha_vms_link_hash_entry *h)
- {
- /* Handle undefined symbols. */
- if (h == NULL || h->sym == NULL)
- return RELC_NONE;
- if (h->sym->typ == EGSD__C_SYMG)
- {
- if (h->sym->flags & EGSY__V_REL)
- return RELC_SHR_BASE + PRIV2 (h->sym->owner, shr_index);
- else
- {
- /* Can this happen (non-relocatable symg) ? I'd like to see
- an example. */
- abort ();
- }
- }
- if (h->sym->typ == EGSD__C_SYM)
- {
- if (h->sym->flags & EGSY__V_REL)
- return RELC_REL;
- else
- return RELC_NONE;
- }
- abort ();
- }
- static bfd_vma
- alpha_vms_get_sym_value (asection *sect, bfd_vma addr)
- {
- return sect->output_section->vma + sect->output_offset + addr;
- }
- static bfd_vma
- alpha_vms_fix_sec_rel (bfd *abfd, struct bfd_link_info *info,
- unsigned int rel, bfd_vma vma)
- {
- asection *sec;
- if (PRIV (sections) == NULL)
- return 0;
- sec = PRIV (sections)[rel & RELC_MASK];
- if (info)
- {
- if (sec->output_section == NULL)
- abort ();
- return vma + sec->output_section->vma + sec->output_offset;
- }
- else
- return vma + sec->vma;
- }
- /* Read an ETIR record from ABFD. If INFO is not null, put the content into
- the output section (used during linking).
- Return FALSE in case of error. */
- static bool
- _bfd_vms_slurp_etir (bfd *abfd, struct bfd_link_info *info)
- {
- unsigned char *ptr;
- unsigned int length;
- unsigned char *maxptr;
- bfd_vma op1 = 0;
- bfd_vma op2 = 0;
- unsigned int rel1 = RELC_NONE;
- unsigned int rel2 = RELC_NONE;
- struct alpha_vms_link_hash_entry *h;
- PRIV (recrd.rec) += ETIR__C_HEADER_SIZE;
- PRIV (recrd.rec_size) -= ETIR__C_HEADER_SIZE;
- ptr = PRIV (recrd.rec);
- length = PRIV (recrd.rec_size);
- maxptr = ptr + length;
- vms_debug2 ((2, "ETIR: %d bytes\n", length));
- while (ptr < maxptr)
- {
- int cmd, cmd_length;
- if (ptr + 4 > maxptr)
- goto corrupt_etir;
- cmd = bfd_getl16 (ptr);
- cmd_length = bfd_getl16 (ptr + 2);
- /* PR 21589 and 21579: Check for a corrupt ETIR record. */
- if (cmd_length < 4 || ptr + cmd_length > maxptr)
- {
- corrupt_etir:
- _bfd_error_handler (_("corrupt ETIR record encountered"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- ptr += 4;
- cmd_length -= 4;
- #if VMS_DEBUG
- _bfd_vms_debug (4, "etir: %s(%d)\n",
- _bfd_vms_etir_name (cmd), cmd);
- _bfd_hexdump (8, ptr, cmd_length, 0);
- #endif
- switch (cmd)
- {
- /* Stack global
- arg: cs symbol name
- stack 32 bit value of symbol (high bits set to 0). */
- case ETIR__C_STA_GBL:
- _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h);
- if (!_bfd_vms_push (abfd, op1, alpha_vms_sym_to_ctxt (h)))
- return false;
- break;
- /* Stack longword
- arg: lw value
- stack 32 bit value, sign extend to 64 bit. */
- case ETIR__C_STA_LW:
- if (cmd_length < 4)
- goto corrupt_etir;
- if (!_bfd_vms_push (abfd, bfd_getl32 (ptr), RELC_NONE))
- return false;
- break;
- /* Stack quadword
- arg: qw value
- stack 64 bit value of symbol. */
- case ETIR__C_STA_QW:
- if (cmd_length < 8)
- goto corrupt_etir;
- if (!_bfd_vms_push (abfd, bfd_getl64 (ptr), RELC_NONE))
- return false;
- break;
- /* Stack psect base plus quadword offset
- arg: lw section index
- qw signed quadword offset (low 32 bits)
- Stack qw argument and section index
- (see ETIR__C_STO_OFF, ETIR__C_CTL_SETRB). */
- case ETIR__C_STA_PQ:
- {
- int psect;
- if (cmd_length < 12)
- goto corrupt_etir;
- psect = bfd_getl32 (ptr);
- if ((unsigned int) psect >= PRIV (section_count))
- {
- _bfd_error_handler (_("bad section index in %s"),
- _bfd_vms_etir_name (cmd));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- op1 = bfd_getl64 (ptr + 4);
- if (!_bfd_vms_push (abfd, op1, psect | RELC_SEC_BASE))
- return false;
- }
- break;
- case ETIR__C_STA_LI:
- case ETIR__C_STA_MOD:
- case ETIR__C_STA_CKARG:
- _bfd_error_handler (_("unsupported STA cmd %s"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- /* Store byte: pop stack, write byte
- arg: -. */
- case ETIR__C_STO_B:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!image_write_b (abfd, (unsigned int) op1 & 0xff))
- return false;
- break;
- /* Store word: pop stack, write word
- arg: -. */
- case ETIR__C_STO_W:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!image_write_w (abfd, (unsigned int) op1 & 0xffff))
- return false;
- break;
- /* Store longword: pop stack, write longword
- arg: -. */
- case ETIR__C_STO_LW:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 & RELC_SEC_BASE)
- {
- op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
- rel1 = RELC_REL;
- }
- else if (rel1 & RELC_SHR_BASE)
- {
- if (!alpha_vms_add_fixup_lr (info, rel1 & RELC_MASK, op1))
- return false;
- rel1 = RELC_NONE;
- }
- if (rel1 != RELC_NONE)
- {
- if (rel1 != RELC_REL)
- abort ();
- if (!alpha_vms_add_lw_reloc (info))
- return false;
- }
- if (!image_write_l (abfd, op1))
- return false;
- break;
- /* Store quadword: pop stack, write quadword
- arg: -. */
- case ETIR__C_STO_QW:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 & RELC_SEC_BASE)
- {
- op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
- rel1 = RELC_REL;
- }
- else if (rel1 & RELC_SHR_BASE)
- abort ();
- if (rel1 != RELC_NONE)
- {
- if (rel1 != RELC_REL)
- abort ();
- if (!alpha_vms_add_qw_reloc (info))
- return false;
- }
- if (!image_write_q (abfd, op1))
- return false;
- break;
- /* Store immediate repeated: pop stack for repeat count
- arg: lw byte count
- da data. */
- case ETIR__C_STO_IMMR:
- {
- int size;
- if (cmd_length < 4)
- goto corrupt_etir;
- size = bfd_getl32 (ptr);
- if (size > cmd_length - 4)
- goto corrupt_etir;
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (size == 0)
- break;
- op1 &= 0xffffffff;
- while (op1-- > 0)
- if (!image_write (abfd, ptr + 4, size))
- return false;
- }
- break;
- /* Store global: write symbol value
- arg: cs global symbol name. */
- case ETIR__C_STO_GBL:
- _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h);
- if (h && h->sym)
- {
- if (h->sym->typ == EGSD__C_SYMG)
- {
- if (!alpha_vms_add_fixup_qr (info, abfd, h->sym->owner,
- h->sym->symbol_vector))
- return false;
- op1 = 0;
- }
- else
- {
- op1 = alpha_vms_get_sym_value (h->sym->section,
- h->sym->value);
- if (!alpha_vms_add_qw_reloc (info))
- return false;
- }
- }
- if (!image_write_q (abfd, op1))
- return false;
- break;
- /* Store code address: write address of entry point
- arg: cs global symbol name (procedure). */
- case ETIR__C_STO_CA:
- _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h);
- if (h && h->sym)
- {
- if (h->sym->flags & EGSY__V_NORM)
- {
- /* That's really a procedure. */
- if (h->sym->typ == EGSD__C_SYMG)
- {
- if (!alpha_vms_add_fixup_ca (info, abfd, h->sym->owner))
- return false;
- op1 = h->sym->symbol_vector;
- }
- else
- {
- op1 = alpha_vms_get_sym_value (h->sym->code_section,
- h->sym->code_value);
- if (!alpha_vms_add_qw_reloc (info))
- return false;
- }
- }
- else
- {
- /* Symbol is not a procedure. */
- abort ();
- }
- }
- if (!image_write_q (abfd, op1))
- return false;
- break;
- /* Store offset to psect: pop stack, add low 32 bits to base of psect
- arg: none. */
- case ETIR__C_STO_OFF:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (!(rel1 & RELC_SEC_BASE))
- abort ();
- op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
- rel1 = RELC_REL;
- if (!image_write_q (abfd, op1))
- return false;
- break;
- /* Store immediate
- arg: lw count of bytes
- da data. */
- case ETIR__C_STO_IMM:
- {
- unsigned int size;
- if (cmd_length < 4)
- goto corrupt_etir;
- size = bfd_getl32 (ptr);
- if (!image_write (abfd, ptr + 4, size))
- return false;
- }
- break;
- /* This code is 'reserved to digital' according to the openVMS
- linker manual, however it is generated by the DEC C compiler
- and defined in the include file.
- FIXME, since the following is just a guess
- store global longword: store 32bit value of symbol
- arg: cs symbol name. */
- case ETIR__C_STO_GBL_LW:
- _bfd_vms_get_value (abfd, ptr, ptr + cmd_length, info, &op1, &h);
- #if 0
- abort ();
- #endif
- if (!image_write_l (abfd, op1))
- return false;
- break;
- case ETIR__C_STO_RB:
- case ETIR__C_STO_AB:
- case ETIR__C_STO_LP_PSB:
- _bfd_error_handler (_("%s: not supported"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- case ETIR__C_STO_HINT_GBL:
- case ETIR__C_STO_HINT_PS:
- _bfd_error_handler (_("%s: not implemented"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- /* 200 Store-conditional Linkage Pair
- arg: none. */
- case ETIR__C_STC_LP:
- /* 202 Store-conditional Address at global address
- lw linkage index
- cs global name. */
- case ETIR__C_STC_GBL:
- /* 203 Store-conditional Code Address at global address
- lw linkage index
- cs procedure name. */
- case ETIR__C_STC_GCA:
- /* 204 Store-conditional Address at psect + offset
- lw linkage index
- lw psect index
- qw offset. */
- case ETIR__C_STC_PS:
- _bfd_error_handler (_("%s: not supported"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- /* 201 Store-conditional Linkage Pair with Procedure Signature
- lw linkage index
- cs procedure name
- by signature length
- da signature. */
- case ETIR__C_STC_LP_PSB:
- if (cmd_length < 4)
- goto corrupt_etir;
- _bfd_vms_get_value (abfd, ptr + 4, ptr + cmd_length, info, &op1, &h);
- if (h && h->sym)
- {
- if (h->sym->typ == EGSD__C_SYMG)
- {
- if (!alpha_vms_add_fixup_lp (info, abfd, h->sym->owner))
- return false;
- op1 = h->sym->symbol_vector;
- op2 = 0;
- }
- else
- {
- op1 = alpha_vms_get_sym_value (h->sym->code_section,
- h->sym->code_value);
- op2 = alpha_vms_get_sym_value (h->sym->section,
- h->sym->value);
- }
- }
- else
- {
- /* Undefined symbol. */
- op1 = 0;
- op2 = 0;
- }
- if (!image_write_q (abfd, op1)
- || !image_write_q (abfd, op2))
- return false;
- break;
- /* 205 Store-conditional NOP at address of global
- arg: none. */
- case ETIR__C_STC_NOP_GBL:
- /* ALPHA_R_NOP */
- /* 207 Store-conditional BSR at global address
- arg: none. */
- case ETIR__C_STC_BSR_GBL:
- /* ALPHA_R_BSR */
- /* 209 Store-conditional LDA at global address
- arg: none. */
- case ETIR__C_STC_LDA_GBL:
- /* ALPHA_R_LDA */
- /* 211 Store-conditional BSR or Hint at global address
- arg: none. */
- case ETIR__C_STC_BOH_GBL:
- /* Currentl ignored. */
- break;
- /* 213 Store-conditional NOP,BSR or HINT at global address
- arg: none. */
- case ETIR__C_STC_NBH_GBL:
- /* 206 Store-conditional NOP at pect + offset
- arg: none. */
- case ETIR__C_STC_NOP_PS:
- /* 208 Store-conditional BSR at pect + offset
- arg: none. */
- case ETIR__C_STC_BSR_PS:
- /* 210 Store-conditional LDA at psect + offset
- arg: none. */
- case ETIR__C_STC_LDA_PS:
- /* 212 Store-conditional BSR or Hint at pect + offset
- arg: none. */
- case ETIR__C_STC_BOH_PS:
- /* 214 Store-conditional NOP, BSR or HINT at psect + offset
- arg: none. */
- case ETIR__C_STC_NBH_PS:
- _bfd_error_handler (_("%s: not supported"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- /* Det relocation base: pop stack, set image location counter
- arg: none. */
- case ETIR__C_CTL_SETRB:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (!(rel1 & RELC_SEC_BASE))
- abort ();
- image_set_ptr (abfd, op1, rel1 & RELC_MASK, info);
- break;
- /* Augment relocation base: increment image location counter by offset
- arg: lw offset value. */
- case ETIR__C_CTL_AUGRB:
- if (cmd_length < 4)
- goto corrupt_etir;
- op1 = bfd_getl32 (ptr);
- image_inc_ptr (abfd, op1);
- break;
- /* Define location: pop index, save location counter under index
- arg: none. */
- case ETIR__C_CTL_DFLOC:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!dst_define_location (abfd, op1))
- return false;
- break;
- /* Set location: pop index, restore location counter from index
- arg: none. */
- case ETIR__C_CTL_STLOC:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!dst_restore_location (abfd, op1))
- {
- bfd_set_error (bfd_error_bad_value);
- _bfd_error_handler (_("invalid %s"), "ETIR__C_CTL_STLOC");
- return false;
- }
- break;
- /* Stack defined location: pop index, push location counter from index
- arg: none. */
- case ETIR__C_CTL_STKDL:
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!dst_retrieve_location (abfd, &op1))
- {
- bfd_set_error (bfd_error_bad_value);
- _bfd_error_handler (_("invalid %s"), "ETIR__C_CTL_STKDL");
- return false;
- }
- if (!_bfd_vms_push (abfd, op1, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_NOP: /* No-op. */
- break;
- case ETIR__C_OPR_ADD: /* Add. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 == RELC_NONE && rel2 != RELC_NONE)
- rel1 = rel2;
- else if (rel1 != RELC_NONE && rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op1 + op2, rel1))
- return false;
- break;
- case ETIR__C_OPR_SUB: /* Subtract. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 == RELC_NONE && rel2 != RELC_NONE)
- rel1 = rel2;
- else if ((rel1 & RELC_SEC_BASE) && (rel2 & RELC_SEC_BASE))
- {
- op1 = alpha_vms_fix_sec_rel (abfd, info, rel1, op1);
- op2 = alpha_vms_fix_sec_rel (abfd, info, rel2, op2);
- rel1 = RELC_NONE;
- }
- else if (rel1 != RELC_NONE && rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op2 - op1, rel1))
- return false;
- break;
- case ETIR__C_OPR_MUL: /* Multiply. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op1 * op2, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_DIV: /* Divide. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- goto bad_context;
- if (op1 == 0)
- {
- /* Divide by zero is supposed to give a result of zero,
- and a non-fatal warning message. */
- _bfd_error_handler (_("%s divide by zero"), "ETIR__C_OPR_DIV");
- if (!_bfd_vms_push (abfd, 0, RELC_NONE))
- return false;
- }
- else
- {
- if (!_bfd_vms_push (abfd, op2 / op1, RELC_NONE))
- return false;
- }
- break;
- case ETIR__C_OPR_AND: /* Logical AND. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op1 & op2, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_IOR: /* Logical inclusive OR. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op1 | op2, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_EOR: /* Logical exclusive OR. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, op1 ^ op2, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_NEG: /* Negate. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, -op1, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_COM: /* Complement. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (rel1 != RELC_NONE)
- goto bad_context;
- if (!_bfd_vms_push (abfd, ~op1, RELC_NONE))
- return false;
- break;
- case ETIR__C_OPR_ASH: /* Arithmetic shift. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (rel1 != RELC_NONE || rel2 != RELC_NONE)
- {
- bad_context:
- _bfd_error_handler (_("invalid use of %s with contexts"),
- _bfd_vms_etir_name (cmd));
- return false;
- }
- if ((bfd_signed_vma) op2 < 0)
- {
- /* Shift right. */
- bfd_vma sign;
- op2 = -op2;
- if (op2 >= CHAR_BIT * sizeof (op1))
- op2 = CHAR_BIT * sizeof (op1) - 1;
- /* op1 = (bfd_signed_vma) op1 >> op2; */
- sign = op1 & ((bfd_vma) 1 << (CHAR_BIT * sizeof (op1) - 1));
- op1 >>= op2;
- sign >>= op2;
- op1 = (op1 ^ sign) - sign;
- }
- else
- {
- /* Shift left. */
- if (op2 >= CHAR_BIT * sizeof (op1))
- op1 = 0;
- else
- op1 <<= op2;
- }
- if (!_bfd_vms_push (abfd, op1, RELC_NONE)) /* FIXME: sym. */
- return false;
- break;
- case ETIR__C_OPR_INSV: /* Insert field. */
- case ETIR__C_OPR_USH: /* Unsigned shift. */
- case ETIR__C_OPR_ROT: /* Rotate. */
- case ETIR__C_OPR_REDEF: /* Redefine symbol to current location. */
- case ETIR__C_OPR_DFLIT: /* Define a literal. */
- _bfd_error_handler (_("%s: not supported"),
- _bfd_vms_etir_name (cmd));
- return false;
- break;
- case ETIR__C_OPR_SEL: /* Select. */
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- if (op1 & 0x01L)
- {
- if (!_bfd_vms_pop (abfd, &op1, &rel1))
- return false;
- }
- else
- {
- if (!_bfd_vms_pop (abfd, &op1, &rel1)
- || !_bfd_vms_pop (abfd, &op2, &rel2))
- return false;
- if (!_bfd_vms_push (abfd, op1, rel1))
- return false;
- }
- break;
- default:
- _bfd_error_handler (_("reserved cmd %d"), cmd);
- return false;
- break;
- }
- ptr += cmd_length;
- }
- return true;
- }
- /* Process EDBG/ETBT record.
- Return TRUE on success, FALSE on error */
- static bool
- vms_slurp_debug (bfd *abfd)
- {
- asection *section = PRIV (dst_section);
- if (section == NULL)
- {
- /* We have no way to find out beforehand how much debug info there
- is in an object file, so pick an initial amount and grow it as
- needed later. */
- flagword flags = SEC_HAS_CONTENTS | SEC_DEBUGGING | SEC_RELOC
- | SEC_IN_MEMORY;
- section = bfd_make_section (abfd, "$DST$");
- if (!section)
- return false;
- if (!bfd_set_section_flags (section, flags))
- return false;
- PRIV (dst_section) = section;
- }
- PRIV (image_section) = section;
- PRIV (image_offset) = section->size;
- if (!_bfd_vms_slurp_etir (abfd, NULL))
- return false;
- section->size = PRIV (image_offset);
- return true;
- }
- /* Process EDBG record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_edbg (bfd *abfd)
- {
- vms_debug2 ((2, "EDBG\n"));
- abfd->flags |= HAS_DEBUG | HAS_LINENO;
- return vms_slurp_debug (abfd);
- }
- /* Process ETBT record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_etbt (bfd *abfd)
- {
- vms_debug2 ((2, "ETBT\n"));
- abfd->flags |= HAS_LINENO;
- return vms_slurp_debug (abfd);
- }
- /* Process EEOM record.
- Return TRUE on success, FALSE on error. */
- static bool
- _bfd_vms_slurp_eeom (bfd *abfd)
- {
- struct vms_eeom *eeom = (struct vms_eeom *) PRIV (recrd.rec);
- vms_debug2 ((2, "EEOM\n"));
- /* PR 21813: Check for an undersized record. */
- if (PRIV (recrd.buf_size) < sizeof (* eeom))
- {
- _bfd_error_handler (_("corrupt EEOM record - size is too small"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- PRIV (eom_data).eom_l_total_lps = bfd_getl32 (eeom->total_lps);
- PRIV (eom_data).eom_w_comcod = bfd_getl16 (eeom->comcod);
- if (PRIV (eom_data).eom_w_comcod > 1)
- {
- _bfd_error_handler (_("object module not error-free !"));
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- PRIV (eom_data).eom_has_transfer = false;
- if (PRIV (recrd.rec_size) > 10)
- {
- PRIV (eom_data).eom_has_transfer = true;
- PRIV (eom_data).eom_b_tfrflg = eeom->tfrflg;
- PRIV (eom_data).eom_l_psindx = bfd_getl32 (eeom->psindx);
- PRIV (eom_data).eom_l_tfradr = bfd_getl32 (eeom->tfradr);
- abfd->start_address = PRIV (eom_data).eom_l_tfradr;
- }
- return true;
- }
- /* Slurp an ordered set of VMS object records. Return FALSE on error. */
- static bool
- _bfd_vms_slurp_object_records (bfd * abfd)
- {
- bool ok;
- int type;
- do
- {
- vms_debug2 ((7, "reading at %08lx\n", (unsigned long)bfd_tell (abfd)));
- type = _bfd_vms_get_object_record (abfd);
- if (type < 0)
- {
- vms_debug2 ((2, "next_record failed\n"));
- return false;
- }
- switch (type)
- {
- case EOBJ__C_EMH:
- ok = _bfd_vms_slurp_ehdr (abfd);
- break;
- case EOBJ__C_EEOM:
- ok = _bfd_vms_slurp_eeom (abfd);
- break;
- case EOBJ__C_EGSD:
- ok = _bfd_vms_slurp_egsd (abfd);
- break;
- case EOBJ__C_ETIR:
- ok = true; /* _bfd_vms_slurp_etir (abfd); */
- break;
- case EOBJ__C_EDBG:
- ok = _bfd_vms_slurp_edbg (abfd);
- break;
- case EOBJ__C_ETBT:
- ok = _bfd_vms_slurp_etbt (abfd);
- break;
- default:
- ok = false;
- }
- if (!ok)
- {
- vms_debug2 ((2, "slurp type %d failed\n", type));
- return false;
- }
- }
- while (type != EOBJ__C_EEOM);
- return true;
- }
- /* Initialize private data */
- static bool
- vms_initialize (bfd * abfd)
- {
- size_t amt;
- amt = sizeof (struct vms_private_data_struct);
- abfd->tdata.any = bfd_zalloc (abfd, amt);
- if (abfd->tdata.any == NULL)
- return false;
- PRIV (recrd.file_format) = FF_UNKNOWN;
- amt = sizeof (struct stack_struct) * STACKSIZE;
- PRIV (stack) = bfd_alloc (abfd, amt);
- if (PRIV (stack) == NULL)
- goto error_ret1;
- return true;
- error_ret1:
- bfd_release (abfd, abfd->tdata.any);
- abfd->tdata.any = NULL;
- return false;
- }
- /* Free malloc'd memory. */
- static void
- alpha_vms_free_private (bfd *abfd)
- {
- struct module *module;
- free (PRIV (recrd.buf));
- free (PRIV (sections));
- free (PRIV (syms));
- free (PRIV (dst_ptr_offsets));
- for (module = PRIV (modules); module; module = module->next)
- free (module->file_table);
- }
- /* Check the format for a file being read.
- Return a (bfd_target *) if it's an object file or zero if not. */
- static bfd_cleanup
- alpha_vms_object_p (bfd *abfd)
- {
- void *tdata_save = abfd->tdata.any;
- unsigned int test_len;
- unsigned char *buf;
- vms_debug2 ((1, "vms_object_p(%p)\n", abfd));
- /* Allocate alpha-vms specific data. */
- if (!vms_initialize (abfd))
- {
- abfd->tdata.any = tdata_save;
- return NULL;
- }
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
- goto error_ret;
- /* The first challenge with VMS is to discover the kind of the file.
- Image files (executable or shared images) are stored as a raw
- stream of bytes (like on UNIX), but there is no magic number.
- Object files are written with RMS (record management service), ie
- each records are preceeded by its length (on a word - 2 bytes), and
- padded for word-alignment. That would be simple but when files
- are transfered to a UNIX filesystem (using ftp), records are lost.
- Only the raw content of the records are transfered. Fortunately,
- the Alpha Object file format also store the length of the record
- in the records. Is that clear ? */
- /* Minimum is 6 bytes for objects (2 bytes size, 2 bytes record id,
- 2 bytes size repeated) and 12 bytes for images (4 bytes major id,
- 4 bytes minor id, 4 bytes length). */
- test_len = 12;
- buf = _bfd_malloc_and_read (abfd, test_len, test_len);
- if (buf == NULL)
- goto error_ret;
- PRIV (recrd.buf) = buf;
- PRIV (recrd.buf_size) = test_len;
- PRIV (recrd.rec) = buf;
- /* Is it an image? */
- if ((bfd_getl32 (buf) == EIHD__K_MAJORID)
- && (bfd_getl32 (buf + 4) == EIHD__K_MINORID))
- {
- unsigned int eisd_offset, eihs_offset;
- /* Extract the header size. */
- PRIV (recrd.rec_size) = bfd_getl32 (buf + EIHD__L_SIZE);
- /* The header size is 0 for DSF files. */
- if (PRIV (recrd.rec_size) == 0)
- PRIV (recrd.rec_size) = sizeof (struct vms_eihd);
- /* PR 21813: Check for a truncated record. */
- /* PR 17512: file: 7d7c57c2. */
- if (PRIV (recrd.rec_size) < sizeof (struct vms_eihd))
- goto err_wrong_format;
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET))
- goto error_ret;
- free (PRIV (recrd.buf));
- PRIV (recrd.buf) = NULL;
- buf = _bfd_malloc_and_read (abfd, PRIV (recrd.rec_size),
- PRIV (recrd.rec_size));
- if (buf == NULL)
- goto error_ret;
- PRIV (recrd.buf) = buf;
- PRIV (recrd.buf_size) = PRIV (recrd.rec_size);
- PRIV (recrd.rec) = buf;
- vms_debug2 ((2, "file type is image\n"));
- if (!_bfd_vms_slurp_eihd (abfd, &eisd_offset, &eihs_offset))
- goto err_wrong_format;
- if (!_bfd_vms_slurp_eisd (abfd, eisd_offset))
- goto err_wrong_format;
- /* EIHS is optional. */
- if (eihs_offset != 0 && !_bfd_vms_slurp_eihs (abfd, eihs_offset))
- goto err_wrong_format;
- }
- else
- {
- int type;
- /* Assume it's a module and adjust record pointer if necessary. */
- maybe_adjust_record_pointer_for_object (abfd);
- /* But is it really a module? */
- if (bfd_getl16 (PRIV (recrd.rec)) <= EOBJ__C_MAXRECTYP
- && bfd_getl16 (PRIV (recrd.rec) + 2) <= EOBJ__C_MAXRECSIZ)
- {
- if (vms_get_remaining_object_record (abfd, test_len) <= 0)
- goto err_wrong_format;
- vms_debug2 ((2, "file type is module\n"));
- type = bfd_getl16 (PRIV (recrd.rec));
- if (type != EOBJ__C_EMH || !_bfd_vms_slurp_ehdr (abfd))
- goto err_wrong_format;
- if (!_bfd_vms_slurp_object_records (abfd))
- goto err_wrong_format;
- }
- else
- goto err_wrong_format;
- }
- /* Set arch_info to alpha. */
- if (! bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0))
- goto err_wrong_format;
- return alpha_vms_free_private;
- err_wrong_format:
- bfd_set_error (bfd_error_wrong_format);
- error_ret:
- alpha_vms_free_private (abfd);
- if (abfd->tdata.any != tdata_save && abfd->tdata.any != NULL)
- bfd_release (abfd, abfd->tdata.any);
- abfd->tdata.any = tdata_save;
- return NULL;
- }
- /* Image write. */
- /* Write an EMH/MHD record. */
- static void
- _bfd_vms_write_emh (bfd *abfd)
- {
- struct vms_rec_wr *recwr = &PRIV (recwr);
- unsigned char tbuf[18];
- _bfd_vms_output_alignment (recwr, 2);
- /* EMH. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
- _bfd_vms_output_short (recwr, EMH__C_MHD);
- _bfd_vms_output_short (recwr, EOBJ__C_STRLVL);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_long (recwr, MAX_OUTREC_SIZE);
- /* Create module name from filename. */
- if (bfd_get_filename (abfd) != 0)
- {
- char *module = vms_get_module_name (bfd_get_filename (abfd), true);
- _bfd_vms_output_counted (recwr, module);
- free (module);
- }
- else
- _bfd_vms_output_counted (recwr, "NONAME");
- _bfd_vms_output_counted (recwr, BFD_VERSION_STRING);
- _bfd_vms_output_dump (recwr, get_vms_time_string (tbuf), EMH_DATE_LENGTH);
- _bfd_vms_output_fill (recwr, 0, EMH_DATE_LENGTH);
- _bfd_vms_output_end (abfd, recwr);
- }
- /* Write an EMH/LMN record. */
- static void
- _bfd_vms_write_lmn (bfd *abfd, const char *name)
- {
- char version [64];
- struct vms_rec_wr *recwr = &PRIV (recwr);
- unsigned int ver = BFD_VERSION / 10000;
- /* LMN. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
- _bfd_vms_output_short (recwr, EMH__C_LNM);
- snprintf (version, sizeof (version), "%s %d.%d.%d", name,
- ver / 10000, (ver / 100) % 100, ver % 100);
- _bfd_vms_output_dump (recwr, (unsigned char *)version, strlen (version));
- _bfd_vms_output_end (abfd, recwr);
- }
- /* Write eom record for bfd abfd. Return FALSE on error. */
- static bool
- _bfd_vms_write_eeom (bfd *abfd)
- {
- struct vms_rec_wr *recwr = &PRIV (recwr);
- vms_debug2 ((2, "vms_write_eeom\n"));
- _bfd_vms_output_alignment (recwr, 2);
- _bfd_vms_output_begin (recwr, EOBJ__C_EEOM);
- _bfd_vms_output_long (recwr, PRIV (vms_linkage_index + 1) >> 1);
- _bfd_vms_output_byte (recwr, 0); /* Completion code. */
- _bfd_vms_output_byte (recwr, 0); /* Fill byte. */
- if ((abfd->flags & EXEC_P) == 0
- && bfd_get_start_address (abfd) != (bfd_vma)-1)
- {
- asection *section;
- section = bfd_get_section_by_name (abfd, ".link");
- if (section == 0)
- {
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
- _bfd_vms_output_short (recwr, 0);
- _bfd_vms_output_long (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_long (recwr,
- (unsigned long) bfd_get_start_address (abfd));
- _bfd_vms_output_long (recwr, 0);
- }
- _bfd_vms_output_end (abfd, recwr);
- return true;
- }
- static void *
- vector_grow1 (struct vector_type *vec, size_t elsz)
- {
- if (vec->nbr_el >= vec->max_el)
- {
- if (vec->max_el == 0)
- {
- vec->max_el = 16;
- vec->els = bfd_malloc (vec->max_el * elsz);
- }
- else
- {
- size_t amt;
- if (vec->max_el > -1u / 2)
- {
- bfd_set_error (bfd_error_file_too_big);
- return NULL;
- }
- vec->max_el *= 2;
- if (_bfd_mul_overflow (vec->max_el, elsz, &amt))
- {
- bfd_set_error (bfd_error_file_too_big);
- return NULL;
- }
- vec->els = bfd_realloc_or_free (vec->els, amt);
- }
- }
- if (vec->els == NULL)
- return NULL;
- return (char *) vec->els + elsz * vec->nbr_el++;
- }
- /* Bump ABFD file position to next block. */
- static void
- alpha_vms_file_position_block (bfd *abfd)
- {
- /* Next block. */
- PRIV (file_pos) += VMS_BLOCK_SIZE - 1;
- PRIV (file_pos) -= (PRIV (file_pos) % VMS_BLOCK_SIZE);
- }
- /* Convert from internal structure SRC to external structure DST. */
- static void
- alpha_vms_swap_eisd_out (struct vms_internal_eisd_map *src,
- struct vms_eisd *dst)
- {
- bfd_putl32 (src->u.eisd.majorid, dst->majorid);
- bfd_putl32 (src->u.eisd.minorid, dst->minorid);
- bfd_putl32 (src->u.eisd.eisdsize, dst->eisdsize);
- if (src->u.eisd.eisdsize <= EISD__K_LENEND)
- return;
- bfd_putl32 (src->u.eisd.secsize, dst->secsize);
- bfd_putl64 (src->u.eisd.virt_addr, dst->virt_addr);
- bfd_putl32 (src->u.eisd.flags, dst->flags);
- bfd_putl32 (src->u.eisd.vbn, dst->vbn);
- dst->pfc = src->u.eisd.pfc;
- dst->matchctl = src->u.eisd.matchctl;
- dst->type = src->u.eisd.type;
- dst->fill_1 = 0;
- if (src->u.eisd.flags & EISD__M_GBL)
- {
- bfd_putl32 (src->u.gbl_eisd.ident, dst->ident);
- memcpy (dst->gblnam, src->u.gbl_eisd.gblnam,
- src->u.gbl_eisd.gblnam[0] + 1);
- }
- }
- /* Append EISD to the list of extra eisd for ABFD. */
- static void
- alpha_vms_append_extra_eisd (bfd *abfd, struct vms_internal_eisd_map *eisd)
- {
- eisd->next = NULL;
- if (PRIV (gbl_eisd_head) == NULL)
- PRIV (gbl_eisd_head) = eisd;
- else
- PRIV (gbl_eisd_tail)->next = eisd;
- PRIV (gbl_eisd_tail) = eisd;
- }
- /* Create an EISD for shared image SHRIMG.
- Return FALSE in case of error. */
- static bool
- alpha_vms_create_eisd_for_shared (bfd *abfd, bfd *shrimg)
- {
- struct vms_internal_eisd_map *eisd;
- int namlen;
- namlen = strlen (PRIV2 (shrimg, hdr_data.hdr_t_name));
- if (namlen + 5 > EISD__K_GBLNAMLEN)
- {
- /* Won't fit. */
- return false;
- }
- eisd = bfd_alloc (abfd, sizeof (*eisd));
- if (eisd == NULL)
- return false;
- /* Fill the fields. */
- eisd->u.gbl_eisd.common.majorid = EISD__K_MAJORID;
- eisd->u.gbl_eisd.common.minorid = EISD__K_MINORID;
- eisd->u.gbl_eisd.common.eisdsize = (EISD__K_LEN + 4 + namlen + 5 + 3) & ~3;
- eisd->u.gbl_eisd.common.secsize = VMS_BLOCK_SIZE; /* Must not be 0. */
- eisd->u.gbl_eisd.common.virt_addr = 0;
- eisd->u.gbl_eisd.common.flags = EISD__M_GBL;
- eisd->u.gbl_eisd.common.vbn = 0;
- eisd->u.gbl_eisd.common.pfc = 0;
- eisd->u.gbl_eisd.common.matchctl = PRIV2 (shrimg, matchctl);
- eisd->u.gbl_eisd.common.type = EISD__K_SHRPIC;
- eisd->u.gbl_eisd.ident = PRIV2 (shrimg, ident);
- eisd->u.gbl_eisd.gblnam[0] = namlen + 4;
- memcpy (eisd->u.gbl_eisd.gblnam + 1, PRIV2 (shrimg, hdr_data.hdr_t_name),
- namlen);
- memcpy (eisd->u.gbl_eisd.gblnam + 1 + namlen, "_001", 4);
- /* Append it to the list. */
- alpha_vms_append_extra_eisd (abfd, eisd);
- return true;
- }
- /* Create an EISD for section SEC.
- Return FALSE in case of failure. */
- static bool
- alpha_vms_create_eisd_for_section (bfd *abfd, asection *sec)
- {
- struct vms_internal_eisd_map *eisd;
- /* Only for allocating section. */
- if (!(sec->flags & SEC_ALLOC))
- return true;
- BFD_ASSERT (vms_section_data (sec)->eisd == NULL);
- eisd = bfd_alloc (abfd, sizeof (*eisd));
- if (eisd == NULL)
- return false;
- vms_section_data (sec)->eisd = eisd;
- /* Fill the fields. */
- eisd->u.eisd.majorid = EISD__K_MAJORID;
- eisd->u.eisd.minorid = EISD__K_MINORID;
- eisd->u.eisd.eisdsize = EISD__K_LEN;
- eisd->u.eisd.secsize =
- (sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1);
- eisd->u.eisd.virt_addr = sec->vma;
- eisd->u.eisd.flags = 0;
- eisd->u.eisd.vbn = 0; /* To be later defined. */
- eisd->u.eisd.pfc = 0; /* Default. */
- eisd->u.eisd.matchctl = EISD__K_MATALL;
- eisd->u.eisd.type = EISD__K_NORMAL;
- if (sec->flags & SEC_CODE)
- eisd->u.eisd.flags |= EISD__M_EXE;
- if (!(sec->flags & SEC_READONLY))
- eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
- /* If relocations or fixup will be applied, make this isect writeable. */
- if (sec->flags & SEC_RELOC)
- eisd->u.eisd.flags |= EISD__M_WRT | EISD__M_CRF;
- if (!(sec->flags & SEC_HAS_CONTENTS))
- {
- eisd->u.eisd.flags |= EISD__M_DZRO;
- eisd->u.eisd.flags &= ~EISD__M_CRF;
- }
- if (sec->flags & SEC_LINKER_CREATED)
- {
- if (strcmp (sec->name, "$FIXUP$") == 0)
- eisd->u.eisd.flags |= EISD__M_FIXUPVEC;
- }
- /* Append it to the list. */
- eisd->next = NULL;
- if (PRIV (eisd_head) == NULL)
- PRIV (eisd_head) = eisd;
- else
- PRIV (eisd_tail)->next = eisd;
- PRIV (eisd_tail) = eisd;
- return true;
- }
- /* Layout executable ABFD and write it to the disk.
- Return FALSE in case of failure. */
- static bool
- alpha_vms_write_exec (bfd *abfd)
- {
- struct vms_eihd eihd;
- struct vms_eiha *eiha;
- struct vms_eihi *eihi;
- struct vms_eihs *eihs = NULL;
- asection *sec;
- struct vms_internal_eisd_map *first_eisd;
- struct vms_internal_eisd_map *eisd;
- asection *dst;
- asection *dmt;
- file_ptr gst_filepos = 0;
- unsigned int lnkflags = 0;
- /* Build the EIHD. */
- PRIV (file_pos) = EIHD__C_LENGTH;
- memset (&eihd, 0, sizeof (eihd));
- memset (eihd.fill_2, 0xff, sizeof (eihd.fill_2));
- bfd_putl32 (EIHD__K_MAJORID, eihd.majorid);
- bfd_putl32 (EIHD__K_MINORID, eihd.minorid);
- bfd_putl32 (sizeof (eihd), eihd.size);
- bfd_putl32 (0, eihd.isdoff);
- bfd_putl32 (0, eihd.activoff);
- bfd_putl32 (0, eihd.symdbgoff);
- bfd_putl32 (0, eihd.imgidoff);
- bfd_putl32 (0, eihd.patchoff);
- bfd_putl64 (0, eihd.iafva);
- bfd_putl32 (0, eihd.version_array_off);
- bfd_putl32 (EIHD__K_EXE, eihd.imgtype);
- bfd_putl32 (0, eihd.subtype);
- bfd_putl32 (0, eihd.imgiocnt);
- bfd_putl32 (-1, eihd.privreqs);
- bfd_putl32 (-1, eihd.privreqs + 4);
- bfd_putl32 ((sizeof (eihd) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE,
- eihd.hdrblkcnt);
- bfd_putl32 (0, eihd.ident);
- bfd_putl32 (0, eihd.sysver);
- eihd.matchctl = 0;
- bfd_putl32 (0, eihd.symvect_size);
- bfd_putl32 (16, eihd.virt_mem_block_size);
- bfd_putl32 (0, eihd.ext_fixup_off);
- bfd_putl32 (0, eihd.noopt_psect_off);
- bfd_putl16 (-1, eihd.alias);
- /* Alloc EIHA. */
- eiha = (struct vms_eiha *)((char *) &eihd + PRIV (file_pos));
- bfd_putl32 (PRIV (file_pos), eihd.activoff);
- PRIV (file_pos) += sizeof (struct vms_eiha);
- bfd_putl32 (sizeof (struct vms_eiha), eiha->size);
- bfd_putl32 (0, eiha->spare);
- bfd_putl64 (PRIV (transfer_address[0]), eiha->tfradr1);
- bfd_putl64 (PRIV (transfer_address[1]), eiha->tfradr2);
- bfd_putl64 (PRIV (transfer_address[2]), eiha->tfradr3);
- bfd_putl64 (PRIV (transfer_address[3]), eiha->tfradr4);
- bfd_putl64 (0, eiha->inishr);
- /* Alloc EIHI. */
- eihi = (struct vms_eihi *)((char *) &eihd + PRIV (file_pos));
- bfd_putl32 (PRIV (file_pos), eihd.imgidoff);
- PRIV (file_pos) += sizeof (struct vms_eihi);
- bfd_putl32 (EIHI__K_MAJORID, eihi->majorid);
- bfd_putl32 (EIHI__K_MINORID, eihi->minorid);
- {
- char *module;
- unsigned int len;
- /* Set module name. */
- module = vms_get_module_name (bfd_get_filename (abfd), true);
- len = strlen (module);
- if (len > sizeof (eihi->imgnam) - 1)
- len = sizeof (eihi->imgnam) - 1;
- eihi->imgnam[0] = len;
- memcpy (eihi->imgnam + 1, module, len);
- free (module);
- }
- {
- unsigned int lo;
- unsigned int hi;
- /* Set time. */
- vms_get_time (&hi, &lo);
- bfd_putl32 (lo, eihi->linktime + 0);
- bfd_putl32 (hi, eihi->linktime + 4);
- }
- eihi->imgid[0] = 0;
- eihi->linkid[0] = 0;
- eihi->imgbid[0] = 0;
- /* Alloc EIHS. */
- dst = PRIV (dst_section);
- dmt = bfd_get_section_by_name (abfd, "$DMT$");
- if (dst != NULL && dst->size != 0)
- {
- eihs = (struct vms_eihs *)((char *) &eihd + PRIV (file_pos));
- bfd_putl32 (PRIV (file_pos), eihd.symdbgoff);
- PRIV (file_pos) += sizeof (struct vms_eihs);
- bfd_putl32 (EIHS__K_MAJORID, eihs->majorid);
- bfd_putl32 (EIHS__K_MINORID, eihs->minorid);
- bfd_putl32 (0, eihs->dstvbn);
- bfd_putl32 (0, eihs->dstsize);
- bfd_putl32 (0, eihs->gstvbn);
- bfd_putl32 (0, eihs->gstsize);
- bfd_putl32 (0, eihs->dmtvbn);
- bfd_putl32 (0, eihs->dmtsize);
- }
- /* One EISD per section. */
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- if (!alpha_vms_create_eisd_for_section (abfd, sec))
- return false;
- }
- /* Merge section EIDS which extra ones. */
- if (PRIV (eisd_tail))
- PRIV (eisd_tail)->next = PRIV (gbl_eisd_head);
- else
- PRIV (eisd_head) = PRIV (gbl_eisd_head);
- if (PRIV (gbl_eisd_tail))
- PRIV (eisd_tail) = PRIV (gbl_eisd_tail);
- first_eisd = PRIV (eisd_head);
- /* Add end of eisd. */
- if (first_eisd)
- {
- eisd = bfd_zalloc (abfd, sizeof (*eisd));
- if (eisd == NULL)
- return false;
- eisd->u.eisd.majorid = 0;
- eisd->u.eisd.minorid = 0;
- eisd->u.eisd.eisdsize = 0;
- alpha_vms_append_extra_eisd (abfd, eisd);
- }
- /* Place EISD in the file. */
- for (eisd = first_eisd; eisd; eisd = eisd->next)
- {
- file_ptr room = VMS_BLOCK_SIZE - (PRIV (file_pos) % VMS_BLOCK_SIZE);
- /* First block is a little bit special: there is a word at the end. */
- if (PRIV (file_pos) < VMS_BLOCK_SIZE && room > 2)
- room -= 2;
- if (room < eisd->u.eisd.eisdsize + EISD__K_LENEND)
- alpha_vms_file_position_block (abfd);
- eisd->file_pos = PRIV (file_pos);
- PRIV (file_pos) += eisd->u.eisd.eisdsize;
- if (eisd->u.eisd.flags & EISD__M_FIXUPVEC)
- bfd_putl64 (eisd->u.eisd.virt_addr, eihd.iafva);
- }
- if (first_eisd != NULL)
- {
- bfd_putl32 (first_eisd->file_pos, eihd.isdoff);
- /* Real size of end of eisd marker. */
- PRIV (file_pos) += EISD__K_LENEND;
- }
- bfd_putl32 (PRIV (file_pos), eihd.size);
- bfd_putl32 ((PRIV (file_pos) + VMS_BLOCK_SIZE - 1) / VMS_BLOCK_SIZE,
- eihd.hdrblkcnt);
- /* Place sections. */
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- if (!(sec->flags & SEC_HAS_CONTENTS))
- continue;
- eisd = vms_section_data (sec)->eisd;
- /* Align on a block. */
- alpha_vms_file_position_block (abfd);
- sec->filepos = PRIV (file_pos);
- if (eisd != NULL)
- eisd->u.eisd.vbn = (sec->filepos / VMS_BLOCK_SIZE) + 1;
- PRIV (file_pos) += sec->size;
- }
- /* Update EIHS. */
- if (eihs != NULL && dst != NULL)
- {
- bfd_putl32 ((dst->filepos / VMS_BLOCK_SIZE) + 1, eihs->dstvbn);
- bfd_putl32 (dst->size, eihs->dstsize);
- if (dmt != NULL)
- {
- lnkflags |= EIHD__M_DBGDMT;
- bfd_putl32 ((dmt->filepos / VMS_BLOCK_SIZE) + 1, eihs->dmtvbn);
- bfd_putl32 (dmt->size, eihs->dmtsize);
- }
- if (PRIV (gsd_sym_count) != 0)
- {
- alpha_vms_file_position_block (abfd);
- gst_filepos = PRIV (file_pos);
- bfd_putl32 ((gst_filepos / VMS_BLOCK_SIZE) + 1, eihs->gstvbn);
- bfd_putl32 ((PRIV (gsd_sym_count) + 4) / 5 + 4, eihs->gstsize);
- }
- }
- /* Write EISD in hdr. */
- for (eisd = first_eisd; eisd && eisd->file_pos < VMS_BLOCK_SIZE;
- eisd = eisd->next)
- alpha_vms_swap_eisd_out
- (eisd, (struct vms_eisd *)((char *)&eihd + eisd->file_pos));
- /* Write first block. */
- bfd_putl32 (lnkflags, eihd.lnkflags);
- if (bfd_bwrite (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
- return false;
- /* Write remaining eisd. */
- if (eisd != NULL)
- {
- unsigned char blk[VMS_BLOCK_SIZE];
- struct vms_internal_eisd_map *next_eisd;
- memset (blk, 0xff, sizeof (blk));
- while (eisd != NULL)
- {
- alpha_vms_swap_eisd_out
- (eisd,
- (struct vms_eisd *)(blk + (eisd->file_pos % VMS_BLOCK_SIZE)));
- next_eisd = eisd->next;
- if (next_eisd == NULL
- || (next_eisd->file_pos / VMS_BLOCK_SIZE
- != eisd->file_pos / VMS_BLOCK_SIZE))
- {
- if (bfd_bwrite (blk, sizeof (blk), abfd) != sizeof (blk))
- return false;
- memset (blk, 0xff, sizeof (blk));
- }
- eisd = next_eisd;
- }
- }
- /* Write sections. */
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- unsigned char blk[VMS_BLOCK_SIZE];
- bfd_size_type len;
- if (sec->size == 0 || !(sec->flags & SEC_HAS_CONTENTS))
- continue;
- if (bfd_bwrite (sec->contents, sec->size, abfd) != sec->size)
- return false;
- /* Pad. */
- len = VMS_BLOCK_SIZE - sec->size % VMS_BLOCK_SIZE;
- if (len != VMS_BLOCK_SIZE)
- {
- memset (blk, 0, len);
- if (bfd_bwrite (blk, len, abfd) != len)
- return false;
- }
- }
- /* Write GST. */
- if (gst_filepos != 0)
- {
- struct vms_rec_wr *recwr = &PRIV (recwr);
- unsigned int i;
- _bfd_vms_write_emh (abfd);
- _bfd_vms_write_lmn (abfd, "GNU LD");
- /* PSC for the absolute section. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
- _bfd_vms_output_short (recwr, 0);
- _bfd_vms_output_short (recwr, EGPS__V_PIC | EGPS__V_LIB | EGPS__V_RD);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_counted (recwr, ".$$ABS$$.");
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_end (abfd, recwr);
- for (i = 0; i < PRIV (gsd_sym_count); i++)
- {
- struct vms_symbol_entry *sym = PRIV (syms)[i];
- bfd_vma val;
- bfd_vma ep;
- if ((i % 5) == 0)
- {
- _bfd_vms_output_alignment (recwr, 8);
- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
- _bfd_vms_output_long (recwr, 0);
- }
- _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYMG);
- _bfd_vms_output_short (recwr, 0); /* Data type, alignment. */
- _bfd_vms_output_short (recwr, sym->flags);
- if (sym->code_section)
- ep = alpha_vms_get_sym_value (sym->code_section, sym->code_value);
- else
- {
- BFD_ASSERT (sym->code_value == 0);
- ep = 0;
- }
- val = alpha_vms_get_sym_value (sym->section, sym->value);
- _bfd_vms_output_quad
- (recwr, sym->typ == EGSD__C_SYMG ? sym->symbol_vector : val);
- _bfd_vms_output_quad (recwr, ep);
- _bfd_vms_output_quad (recwr, val);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- if ((i % 5) == 4)
- _bfd_vms_output_end (abfd, recwr);
- }
- if ((i % 5) != 0)
- _bfd_vms_output_end (abfd, recwr);
- if (!_bfd_vms_write_eeom (abfd))
- return false;
- }
- return true;
- }
- /* Object write. */
- /* Write section and symbol directory of bfd abfd. Return FALSE on error. */
- static bool
- _bfd_vms_write_egsd (bfd *abfd)
- {
- asection *section;
- asymbol *symbol;
- unsigned int symnum;
- const char *sname;
- flagword new_flags, old_flags;
- int abs_section_index = -1;
- unsigned int target_index = 0;
- struct vms_rec_wr *recwr = &PRIV (recwr);
- vms_debug2 ((2, "vms_write_egsd\n"));
- /* Egsd is quadword aligned. */
- _bfd_vms_output_alignment (recwr, 8);
- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
- _bfd_vms_output_long (recwr, 0);
- /* Number sections. */
- for (section = abfd->sections; section != NULL; section = section->next)
- {
- if (section->flags & SEC_DEBUGGING)
- continue;
- if (!strcmp (section->name, ".vmsdebug"))
- {
- section->flags |= SEC_DEBUGGING;
- continue;
- }
- section->target_index = target_index++;
- }
- for (section = abfd->sections; section != NULL; section = section->next)
- {
- vms_debug2 ((3, "Section #%d %s, %d bytes\n",
- section->target_index, section->name, (int)section->size));
- /* Don't write out the VMS debug info section since it is in the
- ETBT and EDBG sections in etir. */
- if (section->flags & SEC_DEBUGGING)
- continue;
- /* 13 bytes egsd, max 31 chars name -> should be 44 bytes. */
- if (_bfd_vms_output_check (recwr, 64) < 0)
- {
- _bfd_vms_output_end (abfd, recwr);
- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
- _bfd_vms_output_long (recwr, 0);
- }
- /* Don't know if this is necessary for the linker but for now it keeps
- vms_slurp_gsd happy. */
- sname = section->name;
- if (*sname == '.')
- {
- /* Remove leading dot. */
- sname++;
- if ((*sname == 't') && (strcmp (sname, "text") == 0))
- sname = EVAX_CODE_NAME;
- else if ((*sname == 'd') && (strcmp (sname, "data") == 0))
- sname = EVAX_DATA_NAME;
- else if ((*sname == 'b') && (strcmp (sname, "bss") == 0))
- sname = EVAX_BSS_NAME;
- else if ((*sname == 'l') && (strcmp (sname, "link") == 0))
- sname = EVAX_LINK_NAME;
- else if ((*sname == 'r') && (strcmp (sname, "rdata") == 0))
- sname = EVAX_READONLY_NAME;
- else if ((*sname == 'l') && (strcmp (sname, "literal") == 0))
- sname = EVAX_LITERAL_NAME;
- else if ((*sname == 'l') && (strcmp (sname, "literals") == 0))
- sname = EVAX_LITERALS_NAME;
- else if ((*sname == 'c') && (strcmp (sname, "comm") == 0))
- sname = EVAX_COMMON_NAME;
- else if ((*sname == 'l') && (strcmp (sname, "lcomm") == 0))
- sname = EVAX_LOCAL_NAME;
- }
- if (bfd_is_com_section (section))
- new_flags = (EGPS__V_OVR | EGPS__V_REL | EGPS__V_GBL | EGPS__V_RD
- | EGPS__V_WRT | EGPS__V_NOMOD | EGPS__V_COM);
- else
- new_flags = vms_esecflag_by_name (evax_section_flags, sname,
- section->size > 0);
- /* Modify them as directed. */
- if (section->flags & SEC_READONLY)
- new_flags &= ~EGPS__V_WRT;
- new_flags &= ~vms_section_data (section)->no_flags;
- new_flags |= vms_section_data (section)->flags;
- vms_debug2 ((3, "sec flags %x\n", section->flags));
- vms_debug2 ((3, "new_flags %x, _raw_size %lu\n",
- new_flags, (unsigned long)section->size));
- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
- _bfd_vms_output_short (recwr, section->alignment_power & 0xff);
- _bfd_vms_output_short (recwr, new_flags);
- _bfd_vms_output_long (recwr, (unsigned long) section->size);
- _bfd_vms_output_counted (recwr, sname);
- _bfd_vms_output_end_subrec (recwr);
- /* If the section is an obsolute one, remind its index as it will be
- used later for absolute symbols. */
- if ((new_flags & EGPS__V_REL) == 0 && abs_section_index < 0)
- abs_section_index = section->target_index;
- }
- /* Output symbols. */
- vms_debug2 ((3, "%d symbols found\n", abfd->symcount));
- bfd_set_start_address (abfd, (bfd_vma) -1);
- for (symnum = 0; symnum < abfd->symcount; symnum++)
- {
- symbol = abfd->outsymbols[symnum];
- old_flags = symbol->flags;
- /* Work-around a missing feature: consider __main as the main entry
- point. */
- if (symbol->name[0] == '_' && strcmp (symbol->name, "__main") == 0)
- bfd_set_start_address (abfd, (bfd_vma)symbol->value);
- /* Only put in the GSD the global and the undefined symbols. */
- if (old_flags & BSF_FILE)
- continue;
- if ((old_flags & BSF_GLOBAL) == 0 && !bfd_is_und_section (symbol->section))
- {
- /* If the LIB$INITIIALIZE section is present, add a reference to
- LIB$INITIALIZE symbol. FIXME: this should be done explicitely
- in the assembly file. */
- if (!((old_flags & BSF_SECTION_SYM) != 0
- && strcmp (symbol->section->name, "LIB$INITIALIZE") == 0))
- continue;
- }
- /* 13 bytes egsd, max 64 chars name -> should be 77 bytes. Add 16 more
- bytes for a possible ABS section. */
- if (_bfd_vms_output_check (recwr, 80 + 16) < 0)
- {
- _bfd_vms_output_end (abfd, recwr);
- _bfd_vms_output_begin (recwr, EOBJ__C_EGSD);
- _bfd_vms_output_long (recwr, 0);
- }
- if ((old_flags & BSF_GLOBAL) != 0
- && bfd_is_abs_section (symbol->section)
- && abs_section_index <= 0)
- {
- /* Create an absolute section if none was defined. It is highly
- unlikely that the name $ABS$ clashes with a user defined
- non-absolute section name. */
- _bfd_vms_output_begin_subrec (recwr, EGSD__C_PSC);
- _bfd_vms_output_short (recwr, 4);
- _bfd_vms_output_short (recwr, EGPS__V_SHR);
- _bfd_vms_output_long (recwr, 0);
- _bfd_vms_output_counted (recwr, "$ABS$");
- _bfd_vms_output_end_subrec (recwr);
- abs_section_index = target_index++;
- }
- _bfd_vms_output_begin_subrec (recwr, EGSD__C_SYM);
- /* Data type, alignment. */
- _bfd_vms_output_short (recwr, 0);
- new_flags = 0;
- if (old_flags & BSF_WEAK)
- new_flags |= EGSY__V_WEAK;
- if (bfd_is_com_section (symbol->section)) /* .comm */
- new_flags |= (EGSY__V_WEAK | EGSY__V_COMM);
- if (old_flags & BSF_FUNCTION)
- {
- new_flags |= EGSY__V_NORM;
- new_flags |= EGSY__V_REL;
- }
- if (old_flags & BSF_GLOBAL)
- {
- new_flags |= EGSY__V_DEF;
- if (!bfd_is_abs_section (symbol->section))
- new_flags |= EGSY__V_REL;
- }
- _bfd_vms_output_short (recwr, new_flags);
- if (old_flags & BSF_GLOBAL)
- {
- /* Symbol definition. */
- bfd_vma code_address = 0;
- unsigned long ca_psindx = 0;
- unsigned long psindx;
- if ((old_flags & BSF_FUNCTION) && symbol->udata.p != NULL)
- {
- asymbol *sym;
- sym =
- ((struct evax_private_udata_struct *)symbol->udata.p)->enbsym;
- code_address = sym->value;
- ca_psindx = sym->section->target_index;
- }
- if (bfd_is_abs_section (symbol->section))
- psindx = abs_section_index;
- else
- psindx = symbol->section->target_index;
- _bfd_vms_output_quad (recwr, symbol->value);
- _bfd_vms_output_quad (recwr, code_address);
- _bfd_vms_output_long (recwr, ca_psindx);
- _bfd_vms_output_long (recwr, psindx);
- }
- _bfd_vms_output_counted (recwr, symbol->name);
- _bfd_vms_output_end_subrec (recwr);
- }
- _bfd_vms_output_alignment (recwr, 8);
- _bfd_vms_output_end (abfd, recwr);
- return true;
- }
- /* Write object header for bfd abfd. Return FALSE on error. */
- static bool
- _bfd_vms_write_ehdr (bfd *abfd)
- {
- asymbol *symbol;
- unsigned int symnum;
- struct vms_rec_wr *recwr = &PRIV (recwr);
- vms_debug2 ((2, "vms_write_ehdr (%p)\n", abfd));
- _bfd_vms_output_alignment (recwr, 2);
- _bfd_vms_write_emh (abfd);
- _bfd_vms_write_lmn (abfd, "GNU AS");
- /* SRC. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
- _bfd_vms_output_short (recwr, EMH__C_SRC);
- for (symnum = 0; symnum < abfd->symcount; symnum++)
- {
- symbol = abfd->outsymbols[symnum];
- if (symbol->flags & BSF_FILE)
- {
- _bfd_vms_output_dump (recwr, (unsigned char *) symbol->name,
- (int) strlen (symbol->name));
- break;
- }
- }
- if (symnum == abfd->symcount)
- _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("noname"));
- _bfd_vms_output_end (abfd, recwr);
- /* TTL. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
- _bfd_vms_output_short (recwr, EMH__C_TTL);
- _bfd_vms_output_dump (recwr, (unsigned char *) STRING_COMMA_LEN ("TTL"));
- _bfd_vms_output_end (abfd, recwr);
- /* CPR. */
- _bfd_vms_output_begin (recwr, EOBJ__C_EMH);
- _bfd_vms_output_short (recwr, EMH__C_CPR);
- _bfd_vms_output_dump (recwr,
- (unsigned char *)"GNU BFD ported by Klaus Kämpf 1994-1996",
- 39);
- _bfd_vms_output_end (abfd, recwr);
- return true;
- }
- /* Part 4.6, relocations. */
- /* WRITE ETIR SECTION
- This is still under construction and therefore not documented. */
- /* Close the etir/etbt record. */
- static void
- end_etir_record (bfd * abfd)
- {
- struct vms_rec_wr *recwr = &PRIV (recwr);
- _bfd_vms_output_end (abfd, recwr);
- }
- static void
- start_etir_or_etbt_record (bfd *abfd, asection *section, bfd_vma offset)
- {
- struct vms_rec_wr *recwr = &PRIV (recwr);
- if (section->flags & SEC_DEBUGGING)
- {
- _bfd_vms_output_begin (recwr, EOBJ__C_ETBT);
- if (offset == 0)
- {
- /* Push start offset. */
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
- _bfd_vms_output_long (recwr, (unsigned long) 0);
- _bfd_vms_output_end_subrec (recwr);
- /* Set location. */
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_DFLOC);
- _bfd_vms_output_end_subrec (recwr);
- }
- }
- else
- {
- _bfd_vms_output_begin (recwr, EOBJ__C_ETIR);
- if (offset == 0)
- {
- /* Push start offset. */
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
- _bfd_vms_output_long (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, offset);
- _bfd_vms_output_end_subrec (recwr);
- /* Start = pop (). */
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_CTL_SETRB);
- _bfd_vms_output_end_subrec (recwr);
- }
- }
- }
- /* Output a STO_IMM command for SSIZE bytes of data from CPR at virtual
- address VADDR in section specified by SEC_INDEX and NAME. */
- static void
- sto_imm (bfd *abfd, asection *section,
- bfd_size_type ssize, unsigned char *cptr, bfd_vma vaddr)
- {
- bfd_size_type size;
- struct vms_rec_wr *recwr = &PRIV (recwr);
- #if VMS_DEBUG
- _bfd_vms_debug (8, "sto_imm %d bytes\n", (int) ssize);
- _bfd_hexdump (9, cptr, (int) ssize, (int) vaddr);
- #endif
- while (ssize > 0)
- {
- /* Try all the rest. */
- size = ssize;
- if (_bfd_vms_output_check (recwr, size) < 0)
- {
- /* Doesn't fit, split ! */
- end_etir_record (abfd);
- start_etir_or_etbt_record (abfd, section, vaddr);
- size = _bfd_vms_output_check (recwr, 0); /* get max size */
- if (size > ssize) /* more than what's left ? */
- size = ssize;
- }
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_IMM);
- _bfd_vms_output_long (recwr, (unsigned long) (size));
- _bfd_vms_output_dump (recwr, cptr, size);
- _bfd_vms_output_end_subrec (recwr);
- #if VMS_DEBUG
- _bfd_vms_debug (10, "dumped %d bytes\n", (int) size);
- _bfd_hexdump (10, cptr, (int) size, (int) vaddr);
- #endif
- vaddr += size;
- cptr += size;
- ssize -= size;
- }
- }
- static void
- etir_output_check (bfd *abfd, asection *section, bfd_vma vaddr, int checklen)
- {
- if (_bfd_vms_output_check (&PRIV (recwr), checklen) < 0)
- {
- /* Not enough room in this record. Close it and open a new one. */
- end_etir_record (abfd);
- start_etir_or_etbt_record (abfd, section, vaddr);
- }
- }
- /* Return whether RELOC must be deferred till the end. */
- static bool
- defer_reloc_p (arelent *reloc)
- {
- switch (reloc->howto->type)
- {
- case ALPHA_R_NOP:
- case ALPHA_R_LDA:
- case ALPHA_R_BSR:
- case ALPHA_R_BOH:
- return true;
- default:
- return false;
- }
- }
- /* Write section contents for bfd abfd. Return FALSE on error. */
- static bool
- _bfd_vms_write_etir (bfd * abfd, int objtype ATTRIBUTE_UNUSED)
- {
- asection *section;
- struct vms_rec_wr *recwr = &PRIV (recwr);
- vms_debug2 ((2, "vms_write_tir (%p, %d)\n", abfd, objtype));
- _bfd_vms_output_alignment (recwr, 4);
- PRIV (vms_linkage_index) = 0;
- for (section = abfd->sections; section; section = section->next)
- {
- vms_debug2 ((4, "writing %d. section '%s' (%d bytes)\n",
- section->target_index, section->name, (int) (section->size)));
- if (!(section->flags & SEC_HAS_CONTENTS)
- || bfd_is_com_section (section))
- continue;
- if (!section->contents)
- {
- bfd_set_error (bfd_error_no_contents);
- return false;
- }
- start_etir_or_etbt_record (abfd, section, 0);
- if (section->flags & SEC_RELOC)
- {
- bfd_vma curr_addr = 0;
- unsigned char *curr_data = section->contents;
- bfd_size_type size;
- int pass2_needed = 0;
- int pass2_in_progress = 0;
- unsigned int irel;
- if (section->reloc_count == 0)
- _bfd_error_handler
- (_("SEC_RELOC with no relocs in section %pA"), section);
- #if VMS_DEBUG
- else
- {
- int i = section->reloc_count;
- arelent **rptr = section->orelocation;
- _bfd_vms_debug (4, "%d relocations:\n", i);
- while (i-- > 0)
- {
- _bfd_vms_debug (4, "sym %s in sec %s, value %08lx, "
- "addr %08lx, off %08lx, len %d: %s\n",
- (*(*rptr)->sym_ptr_ptr)->name,
- (*(*rptr)->sym_ptr_ptr)->section->name,
- (long) (*(*rptr)->sym_ptr_ptr)->value,
- (unsigned long)(*rptr)->address,
- (unsigned long)(*rptr)->addend,
- bfd_get_reloc_size ((*rptr)->howto),
- ( *rptr)->howto->name);
- rptr++;
- }
- }
- #endif
- new_pass:
- for (irel = 0; irel < section->reloc_count; irel++)
- {
- struct evax_private_udata_struct *udata;
- arelent *rptr = section->orelocation [irel];
- bfd_vma addr = rptr->address;
- asymbol *sym = *rptr->sym_ptr_ptr;
- asection *sec = sym->section;
- bool defer = defer_reloc_p (rptr);
- unsigned int slen;
- if (pass2_in_progress)
- {
- /* Non-deferred relocs have already been output. */
- if (!defer)
- continue;
- }
- else
- {
- /* Deferred relocs must be output at the very end. */
- if (defer)
- {
- pass2_needed = 1;
- continue;
- }
- /* Regular relocs are intertwined with binary data. */
- if (curr_addr > addr)
- _bfd_error_handler (_("size error in section %pA"),
- section);
- size = addr - curr_addr;
- sto_imm (abfd, section, size, curr_data, curr_addr);
- curr_data += size;
- curr_addr += size;
- }
- size = bfd_get_reloc_size (rptr->howto);
- switch (rptr->howto->type)
- {
- case ALPHA_R_IGNORE:
- break;
- case ALPHA_R_REFLONG:
- if (bfd_is_und_section (sym->section))
- {
- bfd_vma addend = rptr->addend;
- slen = strlen ((char *) sym->name);
- etir_output_check (abfd, section, curr_addr, slen);
- if (addend)
- {
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
- _bfd_vms_output_long (recwr, (unsigned long) addend);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
- _bfd_vms_output_end_subrec (recwr);
- }
- else
- {
- _bfd_vms_output_begin_subrec
- (recwr, ETIR__C_STO_GBL_LW);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- }
- }
- else if (bfd_is_abs_section (sym->section))
- {
- etir_output_check (abfd, section, curr_addr, 16);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_LW);
- _bfd_vms_output_long (recwr, (unsigned long) sym->value);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
- _bfd_vms_output_end_subrec (recwr);
- }
- else
- {
- etir_output_check (abfd, section, curr_addr, 32);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
- _bfd_vms_output_long (recwr,
- (unsigned long) sec->target_index);
- _bfd_vms_output_quad (recwr, rptr->addend + sym->value);
- _bfd_vms_output_end_subrec (recwr);
- /* ??? Table B-8 of the OpenVMS Linker Utilily Manual
- says that we should have a ETIR__C_STO_OFF here.
- But the relocation would not be BFD_RELOC_32 then.
- This case is very likely unreachable. */
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_LW);
- _bfd_vms_output_end_subrec (recwr);
- }
- break;
- case ALPHA_R_REFQUAD:
- if (bfd_is_und_section (sym->section))
- {
- bfd_vma addend = rptr->addend;
- slen = strlen ((char *) sym->name);
- etir_output_check (abfd, section, curr_addr, slen);
- if (addend)
- {
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_GBL);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW);
- _bfd_vms_output_quad (recwr, addend);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_OPR_ADD);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW);
- _bfd_vms_output_end_subrec (recwr);
- }
- else
- {
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_GBL);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- }
- }
- else if (bfd_is_abs_section (sym->section))
- {
- etir_output_check (abfd, section, curr_addr, 16);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_QW);
- _bfd_vms_output_quad (recwr, sym->value);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_QW);
- _bfd_vms_output_end_subrec (recwr);
- }
- else
- {
- etir_output_check (abfd, section, curr_addr, 32);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STA_PQ);
- _bfd_vms_output_long (recwr,
- (unsigned long) sec->target_index);
- _bfd_vms_output_quad (recwr, rptr->addend + sym->value);
- _bfd_vms_output_end_subrec (recwr);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_OFF);
- _bfd_vms_output_end_subrec (recwr);
- }
- break;
- case ALPHA_R_HINT:
- sto_imm (abfd, section, size, curr_data, curr_addr);
- break;
- case ALPHA_R_LINKAGE:
- size = 16;
- etir_output_check (abfd, section, curr_addr, 64);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LP_PSB);
- _bfd_vms_output_long
- (recwr, (unsigned long) rptr->addend);
- if (rptr->addend > PRIV (vms_linkage_index))
- PRIV (vms_linkage_index) = rptr->addend;
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_byte (recwr, 0);
- _bfd_vms_output_end_subrec (recwr);
- break;
- case ALPHA_R_CODEADDR:
- slen = strlen ((char *) sym->name);
- etir_output_check (abfd, section, curr_addr, slen);
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STO_CA);
- _bfd_vms_output_counted (recwr, sym->name);
- _bfd_vms_output_end_subrec (recwr);
- break;
- case ALPHA_R_NOP:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_NOP_GBL);
- _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex);
- _bfd_vms_output_long
- (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, rptr->address);
- _bfd_vms_output_long (recwr, (unsigned long) 0x47ff041f);
- _bfd_vms_output_long
- (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, rptr->addend);
- _bfd_vms_output_counted (recwr, udata->origname);
- _bfd_vms_output_end_subrec (recwr);
- break;
- case ALPHA_R_BSR:
- _bfd_error_handler (_("spurious ALPHA_R_BSR reloc"));
- break;
- case ALPHA_R_LDA:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_LDA_GBL);
- _bfd_vms_output_long
- (recwr, (unsigned long) udata->lkindex + 1);
- _bfd_vms_output_long
- (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, rptr->address);
- _bfd_vms_output_long (recwr, (unsigned long) 0x237B0000);
- _bfd_vms_output_long
- (recwr, (unsigned long) udata->bsym->section->target_index);
- _bfd_vms_output_quad (recwr, rptr->addend);
- _bfd_vms_output_counted (recwr, udata->origname);
- _bfd_vms_output_end_subrec (recwr);
- break;
- case ALPHA_R_BOH:
- udata
- = (struct evax_private_udata_struct *) rptr->sym_ptr_ptr;
- etir_output_check (abfd, section, curr_addr,
- 32 + 1 + strlen (udata->origname));
- _bfd_vms_output_begin_subrec (recwr, ETIR__C_STC_BOH_GBL);
- _bfd_vms_output_long (recwr, (unsigned long) udata->lkindex);
- _bfd_vms_output_long
- (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, rptr->address);
- _bfd_vms_output_long (recwr, (unsigned long) 0xD3400000);
- _bfd_vms_output_long
- (recwr, (unsigned long) section->target_index);
- _bfd_vms_output_quad (recwr, rptr->addend);
- _bfd_vms_output_counted (recwr, udata->origname);
- _bfd_vms_output_end_subrec (recwr);
- break;
- default:
- _bfd_error_handler (_("unhandled relocation %s"),
- rptr->howto->name);
- break;
- }
- curr_data += size;
- curr_addr += size;
- } /* End of relocs loop. */
- if (!pass2_in_progress)
- {
- /* Output rest of section. */
- if (curr_addr > section->size)
- {
- _bfd_error_handler (_("size error in section %pA"), section);
- return false;
- }
- size = section->size - curr_addr;
- sto_imm (abfd, section, size, curr_data, curr_addr);
- curr_data += size;
- curr_addr += size;
- if (pass2_needed)
- {
- pass2_in_progress = 1;
- goto new_pass;
- }
- }
- }
- else /* (section->flags & SEC_RELOC) */
- sto_imm (abfd, section, section->size, section->contents, 0);
- end_etir_record (abfd);
- }
- _bfd_vms_output_alignment (recwr, 2);
- return true;
- }
- /* Write cached information into a file being written, at bfd_close. */
- static bool
- alpha_vms_write_object_contents (bfd *abfd)
- {
- vms_debug2 ((1, "vms_write_object_contents (%p)\n", abfd));
- if (abfd->flags & (EXEC_P | DYNAMIC))
- {
- return alpha_vms_write_exec (abfd);
- }
- else
- {
- if (abfd->section_count > 0) /* we have sections */
- {
- if (!_bfd_vms_write_ehdr (abfd))
- return false;
- if (!_bfd_vms_write_egsd (abfd))
- return false;
- if (!_bfd_vms_write_etir (abfd, EOBJ__C_ETIR))
- return false;
- if (!_bfd_vms_write_eeom (abfd))
- return false;
- }
- }
- return true;
- }
- /* Debug stuff: nearest line. */
- #define SET_MODULE_PARSED(m) \
- do { if ((m)->name == NULL) (m)->name = ""; } while (0)
- #define IS_MODULE_PARSED(m) ((m)->name != NULL)
- /* Build a new module for the specified BFD. */
- static struct module *
- new_module (bfd *abfd)
- {
- struct module *module
- = (struct module *) bfd_zalloc (abfd, sizeof (struct module));
- module->file_table_count = 16; /* Arbitrary. */
- module->file_table
- = bfd_malloc (module->file_table_count * sizeof (struct fileinfo));
- return module;
- }
- /* Parse debug info for a module and internalize it. */
- static bool
- parse_module (bfd *abfd, struct module *module, unsigned char *ptr,
- int length)
- {
- unsigned char *maxptr = ptr + length;
- unsigned char *src_ptr, *pcl_ptr;
- unsigned int prev_linum = 0, curr_linenum = 0;
- bfd_vma prev_pc = 0, curr_pc = 0;
- struct srecinfo *curr_srec, *srec;
- struct lineinfo *curr_line, *line;
- struct funcinfo *funcinfo;
- /* Initialize tables with zero element. */
- curr_srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
- if (!curr_srec)
- return false;
- module->srec_table = curr_srec;
- curr_line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
- if (!curr_line)
- return false;
- module->line_table = curr_line;
- while (length == -1 || ptr < maxptr)
- {
- /* The first byte is not counted in the recorded length. */
- int rec_length = bfd_getl16 (ptr) + 1;
- int rec_type = bfd_getl16 (ptr + 2);
- vms_debug2 ((2, "DST record: leng %d, type %d\n", rec_length, rec_type));
- if (length == -1 && rec_type == DST__K_MODEND)
- break;
- switch (rec_type)
- {
- case DST__K_MODBEG:
- module->name
- = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_MODBEG_NAME,
- maxptr - (ptr + DST_S_B_MODBEG_NAME));
- curr_pc = 0;
- prev_pc = 0;
- curr_linenum = 0;
- prev_linum = 0;
- vms_debug2 ((3, "module: %s\n", module->name));
- break;
- case DST__K_MODEND:
- break;
- case DST__K_RTNBEG:
- funcinfo = (struct funcinfo *)
- bfd_zalloc (abfd, sizeof (struct funcinfo));
- if (!funcinfo)
- return false;
- funcinfo->name
- = _bfd_vms_save_counted_string (abfd, ptr + DST_S_B_RTNBEG_NAME,
- maxptr - (ptr + DST_S_B_RTNBEG_NAME));
- funcinfo->low = bfd_getl32 (ptr + DST_S_L_RTNBEG_ADDRESS);
- funcinfo->next = module->func_table;
- module->func_table = funcinfo;
- vms_debug2 ((3, "routine: %s at 0x%lx\n",
- funcinfo->name, (unsigned long) funcinfo->low));
- break;
- case DST__K_RTNEND:
- if (!module->func_table)
- return false;
- module->func_table->high = module->func_table->low
- + bfd_getl32 (ptr + DST_S_L_RTNEND_SIZE) - 1;
- if (module->func_table->high > module->high)
- module->high = module->func_table->high;
- vms_debug2 ((3, "end routine\n"));
- break;
- case DST__K_PROLOG:
- vms_debug2 ((3, "prologue\n"));
- break;
- case DST__K_EPILOG:
- vms_debug2 ((3, "epilog\n"));
- break;
- case DST__K_BLKBEG:
- vms_debug2 ((3, "block\n"));
- break;
- case DST__K_BLKEND:
- vms_debug2 ((3, "end block\n"));
- break;
- case DST__K_SOURCE:
- src_ptr = ptr + DST_S_C_SOURCE_HEADER_SIZE;
- vms_debug2 ((3, "source info\n"));
- while (src_ptr < ptr + rec_length)
- {
- int cmd = src_ptr[0], cmd_length, data;
- switch (cmd)
- {
- case DST__K_SRC_DECLFILE:
- {
- unsigned int fileid
- = bfd_getl16 (src_ptr + DST_S_W_SRC_DF_FILEID);
- char *filename = _bfd_vms_save_counted_string
- (abfd,
- src_ptr + DST_S_B_SRC_DF_FILENAME,
- ptr + rec_length - (src_ptr + DST_S_B_SRC_DF_FILENAME));
- while (fileid >= module->file_table_count)
- {
- module->file_table_count *= 2;
- module->file_table
- = bfd_realloc_or_free (module->file_table,
- module->file_table_count
- * sizeof (struct fileinfo));
- if (module->file_table == NULL)
- return false;
- }
- module->file_table [fileid].name = filename;
- module->file_table [fileid].srec = 1;
- cmd_length = src_ptr[DST_S_B_SRC_DF_LENGTH] + 2;
- vms_debug2 ((4, "DST_S_C_SRC_DECLFILE: %d, %s\n",
- fileid, module->file_table [fileid].name));
- }
- break;
- case DST__K_SRC_DEFLINES_B:
- /* Perform the association and set the next higher index
- to the limit. */
- data = src_ptr[DST_S_B_SRC_UNSBYTE];
- srec = (struct srecinfo *)
- bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = curr_srec->line + data;
- srec->srec = curr_srec->srec + data;
- srec->sfile = curr_srec->sfile;
- curr_srec->next = srec;
- curr_srec = srec;
- cmd_length = 2;
- vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_B: %d\n", data));
- break;
- case DST__K_SRC_DEFLINES_W:
- /* Perform the association and set the next higher index
- to the limit. */
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- srec = (struct srecinfo *)
- bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = curr_srec->line + data;
- srec->srec = curr_srec->srec + data,
- srec->sfile = curr_srec->sfile;
- curr_srec->next = srec;
- curr_srec = srec;
- cmd_length = 3;
- vms_debug2 ((4, "DST_S_C_SRC_DEFLINES_W: %d\n", data));
- break;
- case DST__K_SRC_INCRLNUM_B:
- data = src_ptr[DST_S_B_SRC_UNSBYTE];
- curr_srec->line += data;
- cmd_length = 2;
- vms_debug2 ((4, "DST_S_C_SRC_INCRLNUM_B: %d\n", data));
- break;
- case DST__K_SRC_SETFILE:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->sfile = data;
- curr_srec->srec = module->file_table[data].srec;
- cmd_length = 3;
- vms_debug2 ((4, "DST_S_C_SRC_SETFILE: %d\n", data));
- break;
- case DST__K_SRC_SETLNUM_L:
- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
- curr_srec->line = data;
- cmd_length = 5;
- vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_L: %d\n", data));
- break;
- case DST__K_SRC_SETLNUM_W:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->line = data;
- cmd_length = 3;
- vms_debug2 ((4, "DST_S_C_SRC_SETLNUM_W: %d\n", data));
- break;
- case DST__K_SRC_SETREC_L:
- data = bfd_getl32 (src_ptr + DST_S_L_SRC_UNSLONG);
- curr_srec->srec = data;
- module->file_table[curr_srec->sfile].srec = data;
- cmd_length = 5;
- vms_debug2 ((4, "DST_S_C_SRC_SETREC_L: %d\n", data));
- break;
- case DST__K_SRC_SETREC_W:
- data = bfd_getl16 (src_ptr + DST_S_W_SRC_UNSWORD);
- curr_srec->srec = data;
- module->file_table[curr_srec->sfile].srec = data;
- cmd_length = 3;
- vms_debug2 ((4, "DST_S_C_SRC_SETREC_W: %d\n", data));
- break;
- case DST__K_SRC_FORMFEED:
- cmd_length = 1;
- vms_debug2 ((4, "DST_S_C_SRC_FORMFEED\n"));
- break;
- default:
- _bfd_error_handler (_("unknown source command %d"),
- cmd);
- cmd_length = 2;
- break;
- }
- src_ptr += cmd_length;
- }
- break;
- case DST__K_LINE_NUM:
- pcl_ptr = ptr + DST_S_C_LINE_NUM_HEADER_SIZE;
- vms_debug2 ((3, "line info\n"));
- while (pcl_ptr < ptr + rec_length)
- {
- /* The command byte is signed so we must sign-extend it. */
- int cmd = ((signed char *)pcl_ptr)[0], cmd_length, data;
- switch (cmd)
- {
- case DST__K_DELTA_PC_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_pc += data;
- curr_linenum += 1;
- cmd_length = 3;
- vms_debug2 ((4, "DST__K_DELTA_PC_W: %d\n", data));
- break;
- case DST__K_DELTA_PC_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc += data;
- curr_linenum += 1;
- cmd_length = 5;
- vms_debug2 ((4, "DST__K_DELTA_PC_L: %d\n", data));
- break;
- case DST__K_INCR_LINUM:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_linenum += data;
- cmd_length = 2;
- vms_debug2 ((4, "DST__K_INCR_LINUM: %d\n", data));
- break;
- case DST__K_INCR_LINUM_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_linenum += data;
- cmd_length = 3;
- vms_debug2 ((4, "DST__K_INCR_LINUM_W: %d\n", data));
- break;
- case DST__K_INCR_LINUM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_linenum += data;
- cmd_length = 5;
- vms_debug2 ((4, "DST__K_INCR_LINUM_L: %d\n", data));
- break;
- case DST__K_SET_LINUM_INCR:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_LINUM_INCR");
- cmd_length = 2;
- break;
- case DST__K_SET_LINUM_INCR_W:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_LINUM_INCR_W");
- cmd_length = 3;
- break;
- case DST__K_RESET_LINUM_INCR:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_RESET_LINUM_INCR");
- cmd_length = 1;
- break;
- case DST__K_BEG_STMT_MODE:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_BEG_STMT_MODE");
- cmd_length = 1;
- break;
- case DST__K_END_STMT_MODE:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_END_STMT_MODE");
- cmd_length = 1;
- break;
- case DST__K_SET_LINUM_B:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_linenum = data;
- cmd_length = 2;
- vms_debug2 ((4, "DST__K_SET_LINUM_B: %d\n", data));
- break;
- case DST__K_SET_LINUM:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_linenum = data;
- cmd_length = 3;
- vms_debug2 ((4, "DST__K_SET_LINE_NUM: %d\n", data));
- break;
- case DST__K_SET_LINUM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_linenum = data;
- cmd_length = 5;
- vms_debug2 ((4, "DST__K_SET_LINUM_L: %d\n", data));
- break;
- case DST__K_SET_PC:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_PC");
- cmd_length = 2;
- break;
- case DST__K_SET_PC_W:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_PC_W");
- cmd_length = 3;
- break;
- case DST__K_SET_PC_L:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_PC_L");
- cmd_length = 5;
- break;
- case DST__K_SET_STMTNUM:
- _bfd_error_handler
- (_("%s not implemented"), "DST__K_SET_STMTNUM");
- cmd_length = 2;
- break;
- case DST__K_TERM:
- data = pcl_ptr[DST_S_B_PCLINE_UNSBYTE];
- curr_pc += data;
- cmd_length = 2;
- vms_debug2 ((4, "DST__K_TERM: %d\n", data));
- break;
- case DST__K_TERM_W:
- data = bfd_getl16 (pcl_ptr + DST_S_W_PCLINE_UNSWORD);
- curr_pc += data;
- cmd_length = 3;
- vms_debug2 ((4, "DST__K_TERM_W: %d\n", data));
- break;
- case DST__K_TERM_L:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc += data;
- cmd_length = 5;
- vms_debug2 ((4, "DST__K_TERM_L: %d\n", data));
- break;
- case DST__K_SET_ABS_PC:
- data = bfd_getl32 (pcl_ptr + DST_S_L_PCLINE_UNSLONG);
- curr_pc = data;
- cmd_length = 5;
- vms_debug2 ((4, "DST__K_SET_ABS_PC: 0x%x\n", data));
- break;
- default:
- if (cmd <= 0)
- {
- curr_pc -= cmd;
- curr_linenum += 1;
- cmd_length = 1;
- vms_debug2 ((4, "bump pc to 0x%lx and line to %d\n",
- (unsigned long)curr_pc, curr_linenum));
- }
- else
- {
- _bfd_error_handler (_("unknown line command %d"), cmd);
- cmd_length = 2;
- }
- break;
- }
- if ((curr_linenum != prev_linum && curr_pc != prev_pc)
- || cmd <= 0
- || cmd == DST__K_DELTA_PC_L
- || cmd == DST__K_DELTA_PC_W)
- {
- line = (struct lineinfo *)
- bfd_zalloc (abfd, sizeof (struct lineinfo));
- line->address = curr_pc;
- line->line = curr_linenum;
- curr_line->next = line;
- curr_line = line;
- prev_linum = curr_linenum;
- prev_pc = curr_pc;
- vms_debug2 ((4, "-> correlate pc 0x%lx with line %d\n",
- (unsigned long)curr_pc, curr_linenum));
- }
- pcl_ptr += cmd_length;
- }
- break;
- case 0x17: /* Undocumented type used by DEC C to declare equates. */
- vms_debug2 ((3, "undocumented type 0x17\n"));
- break;
- default:
- vms_debug2 ((3, "ignoring record\n"));
- break;
- }
- ptr += rec_length;
- }
- /* Finalize tables with EOL marker. */
- srec = (struct srecinfo *) bfd_zalloc (abfd, sizeof (struct srecinfo));
- srec->line = (unsigned int) -1;
- srec->srec = (unsigned int) -1;
- curr_srec->next = srec;
- line = (struct lineinfo *) bfd_zalloc (abfd, sizeof (struct lineinfo));
- line->line = (unsigned int) -1;
- line->address = (bfd_vma) -1;
- curr_line->next = line;
- /* Advertise that this module has been parsed. This is needed
- because parsing can be either performed at module creation
- or deferred until debug info is consumed. */
- SET_MODULE_PARSED (module);
- return true;
- }
- /* Build the list of modules for the specified BFD. */
- static struct module *
- build_module_list (bfd *abfd)
- {
- struct module *module, *list = NULL;
- asection *dmt;
- if ((dmt = bfd_get_section_by_name (abfd, "$DMT$")))
- {
- /* We have a DMT section so this must be an image. Parse the
- section and build the list of modules. This is sufficient
- since we can compute the start address and the end address
- of every module from the section contents. */
- bfd_size_type size = bfd_section_size (dmt);
- unsigned char *buf, *ptr, *end;
- if (! bfd_malloc_and_get_section (abfd, dmt, &buf))
- return NULL;
- vms_debug2 ((2, "DMT\n"));
- ptr = buf;
- end = ptr + size;
- while (end - ptr >= DBG_S_C_DMT_HEADER_SIZE)
- {
- /* Each header declares a module with its start offset and size
- of debug info in the DST section, as well as the count of
- program sections (i.e. address spans) it contains. */
- unsigned int modbeg = bfd_getl32 (ptr + DBG_S_L_DMT_MODBEG);
- unsigned int msize = bfd_getl32 (ptr + DBG_S_L_DST_SIZE);
- int count = bfd_getl16 (ptr + DBG_S_W_DMT_PSECT_COUNT);
- ptr += DBG_S_C_DMT_HEADER_SIZE;
- vms_debug2 ((3, "module: modbeg = %u, size = %u, count = %d\n",
- modbeg, msize, count));
- /* We create a 'module' structure for each program section since
- we only support contiguous addresses in a 'module' structure.
- As a consequence, the actual debug info in the DST section is
- shared and can be parsed multiple times; that doesn't seem to
- cause problems in practice. */
- while (count-- > 0 && end - ptr >= DBG_S_C_DMT_PSECT_SIZE)
- {
- unsigned int start = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_START);
- unsigned int length = bfd_getl32 (ptr + DBG_S_L_DMT_PSECT_LENGTH);
- module = new_module (abfd);
- module->modbeg = modbeg;
- module->size = msize;
- module->low = start;
- module->high = start + length;
- module->next = list;
- list = module;
- ptr += DBG_S_C_DMT_PSECT_SIZE;
- vms_debug2 ((4, "section: start = 0x%x, length = %u\n",
- start, length));
- }
- }
- free (buf);
- }
- else
- {
- /* We don't have a DMT section so this must be an object. Parse
- the module right now in order to compute its start address and
- end address. */
- void *dst = PRIV (dst_section)->contents;
- if (dst == NULL)
- return NULL;
- module = new_module (abfd);
- if (!parse_module (abfd, module, PRIV (dst_section)->contents, -1))
- return NULL;
- list = module;
- }
- return list;
- }
- /* Calculate and return the name of the source file and the line nearest
- to the wanted location in the specified module. */
- static bool
- module_find_nearest_line (bfd *abfd, struct module *module, bfd_vma addr,
- const char **file, const char **func,
- unsigned int *line)
- {
- struct funcinfo *funcinfo;
- struct lineinfo *lineinfo;
- struct srecinfo *srecinfo;
- bool ret = false;
- /* Parse this module if that was not done at module creation. */
- if (! IS_MODULE_PARSED (module))
- {
- unsigned int size = module->size;
- unsigned int modbeg = PRIV (dst_section)->filepos + module->modbeg;
- unsigned char *buffer;
- if (bfd_seek (abfd, modbeg, SEEK_SET) != 0
- || (buffer = _bfd_malloc_and_read (abfd, size, size)) == NULL)
- {
- bfd_set_error (bfd_error_no_debug_section);
- return false;
- }
- ret = parse_module (abfd, module, buffer, size);
- free (buffer);
- if (!ret)
- return ret;
- }
- /* Find out the function (if any) that contains the address. */
- for (funcinfo = module->func_table; funcinfo; funcinfo = funcinfo->next)
- if (addr >= funcinfo->low && addr <= funcinfo->high)
- {
- *func = funcinfo->name;
- ret = true;
- break;
- }
- /* Find out the source file and the line nearest to the address. */
- for (lineinfo = module->line_table; lineinfo; lineinfo = lineinfo->next)
- if (lineinfo->next && addr < lineinfo->next->address)
- {
- for (srecinfo = module->srec_table; srecinfo; srecinfo = srecinfo->next)
- if (srecinfo->next && lineinfo->line < srecinfo->next->line)
- {
- if (srecinfo->sfile > 0)
- {
- *file = module->file_table[srecinfo->sfile].name;
- *line = srecinfo->srec + lineinfo->line - srecinfo->line;
- }
- else
- {
- *file = module->name;
- *line = lineinfo->line;
- }
- return true;
- }
- break;
- }
- return ret;
- }
- /* Provided a BFD, a section and an offset into the section, calculate and
- return the name of the source file and the line nearest to the wanted
- location. */
- static bool
- _bfd_vms_find_nearest_line (bfd *abfd,
- asymbol **symbols ATTRIBUTE_UNUSED,
- asection *section,
- bfd_vma offset,
- const char **file,
- const char **func,
- unsigned int *line,
- unsigned int *discriminator)
- {
- struct module *module;
- /* What address are we looking for? */
- bfd_vma addr = section->vma + offset;
- *file = NULL;
- *func = NULL;
- *line = 0;
- if (discriminator)
- *discriminator = 0;
- /* We can't do anything if there is no DST (debug symbol table). */
- if (PRIV (dst_section) == NULL)
- return false;
- /* Create the module list - if not already done. */
- if (PRIV (modules) == NULL)
- {
- PRIV (modules) = build_module_list (abfd);
- if (PRIV (modules) == NULL)
- return false;
- }
- for (module = PRIV (modules); module; module = module->next)
- if (addr >= module->low && addr <= module->high)
- return module_find_nearest_line (abfd, module, addr, file, func, line);
- return false;
- }
- /* Canonicalizations. */
- /* Set name, value, section and flags of SYM from E. */
- static bool
- alpha_vms_convert_symbol (bfd *abfd, struct vms_symbol_entry *e, asymbol *sym)
- {
- flagword flags;
- symvalue value;
- asection *sec;
- const char *name;
- name = e->name;
- value = 0;
- flags = BSF_NO_FLAGS;
- sec = NULL;
- switch (e->typ)
- {
- case EGSD__C_SYM:
- if (e->flags & EGSY__V_WEAK)
- flags |= BSF_WEAK;
- if (e->flags & EGSY__V_DEF)
- {
- /* Symbol definition. */
- flags |= BSF_GLOBAL;
- if (e->flags & EGSY__V_NORM)
- flags |= BSF_FUNCTION;
- value = e->value;
- sec = e->section;
- }
- else
- {
- /* Symbol reference. */
- sec = bfd_und_section_ptr;
- }
- break;
- case EGSD__C_SYMG:
- /* A universal symbol is by definition global... */
- flags |= BSF_GLOBAL;
- /* ...and dynamic in shared libraries. */
- if (abfd->flags & DYNAMIC)
- flags |= BSF_DYNAMIC;
- if (e->flags & EGSY__V_WEAK)
- flags |= BSF_WEAK;
- if (!(e->flags & EGSY__V_DEF))
- abort ();
- if (e->flags & EGSY__V_NORM)
- flags |= BSF_FUNCTION;
- value = e->value;
- /* sec = e->section; */
- sec = bfd_abs_section_ptr;
- break;
- default:
- return false;
- }
- sym->name = name;
- sym->section = sec;
- sym->flags = flags;
- sym->value = value;
- return true;
- }
- /* Return the number of bytes required to store a vector of pointers
- to asymbols for all the symbols in the BFD abfd, including a
- terminal NULL pointer. If there are no symbols in the BFD,
- then return 0. If an error occurs, return -1. */
- static long
- alpha_vms_get_symtab_upper_bound (bfd *abfd)
- {
- vms_debug2 ((1, "alpha_vms_get_symtab_upper_bound (%p), %d symbols\n",
- abfd, PRIV (gsd_sym_count)));
- return (PRIV (gsd_sym_count) + 1) * sizeof (asymbol *);
- }
- /* Read the symbols from the BFD abfd, and fills in the vector
- location with pointers to the symbols and a trailing NULL.
- Return number of symbols read. */
- static long
- alpha_vms_canonicalize_symtab (bfd *abfd, asymbol **symbols)
- {
- unsigned int i;
- vms_debug2 ((1, "alpha_vms_canonicalize_symtab (%p, <ret>)\n", abfd));
- if (PRIV (csymbols) == NULL)
- {
- PRIV (csymbols) = (asymbol **) bfd_alloc
- (abfd, PRIV (gsd_sym_count) * sizeof (asymbol *));
- /* Traverse table and fill symbols vector. */
- for (i = 0; i < PRIV (gsd_sym_count); i++)
- {
- struct vms_symbol_entry *e = PRIV (syms)[i];
- asymbol *sym;
- sym = bfd_make_empty_symbol (abfd);
- if (sym == NULL || !alpha_vms_convert_symbol (abfd, e, sym))
- {
- bfd_release (abfd, PRIV (csymbols));
- PRIV (csymbols) = NULL;
- return -1;
- }
- PRIV (csymbols)[i] = sym;
- }
- }
- if (symbols != NULL)
- {
- for (i = 0; i < PRIV (gsd_sym_count); i++)
- symbols[i] = PRIV (csymbols)[i];
- symbols[i] = NULL;
- }
- return PRIV (gsd_sym_count);
- }
- /* Read and convert relocations from ETIR. We do it once for all sections. */
- static bool
- alpha_vms_slurp_relocs (bfd *abfd)
- {
- int cur_psect = -1;
- vms_debug2 ((3, "alpha_vms_slurp_relocs\n"));
- /* We slurp relocs only once, for all sections. */
- if (PRIV (reloc_done))
- return true;
- PRIV (reloc_done) = true;
- if (alpha_vms_canonicalize_symtab (abfd, NULL) < 0)
- return false;
- if (bfd_seek (abfd, 0, SEEK_SET) != 0)
- return false;
- while (1)
- {
- unsigned char *begin;
- unsigned char *end;
- unsigned char *ptr;
- bfd_reloc_code_real_type reloc_code;
- int type;
- bfd_vma vaddr = 0;
- int length;
- bfd_vma cur_address;
- int cur_psidx = -1;
- unsigned char *cur_sym = NULL;
- int prev_cmd = -1;
- bfd_vma cur_addend = 0;
- /* Skip non-ETIR records. */
- type = _bfd_vms_get_object_record (abfd);
- if (type == EOBJ__C_EEOM)
- break;
- if (type != EOBJ__C_ETIR)
- continue;
- begin = PRIV (recrd.rec) + 4;
- end = PRIV (recrd.rec) + PRIV (recrd.rec_size);
- for (ptr = begin; ptr < end; ptr += length)
- {
- int cmd;
- cmd = bfd_getl16 (ptr);
- length = bfd_getl16 (ptr + 2);
- cur_address = vaddr;
- vms_debug2 ((4, "alpha_vms_slurp_relocs: etir %s\n",
- _bfd_vms_etir_name (cmd)));
- switch (cmd)
- {
- case ETIR__C_STA_GBL: /* ALPHA_R_REFLONG und_section, step 1 */
- /* ALPHA_R_REFQUAD und_section, step 1 */
- cur_sym = ptr + 4;
- prev_cmd = cmd;
- continue;
- case ETIR__C_STA_PQ: /* ALPHA_R_REF{LONG|QUAD}, others part 1 */
- cur_psidx = bfd_getl32 (ptr + 4);
- cur_addend = bfd_getl64 (ptr + 8);
- prev_cmd = cmd;
- continue;
- case ETIR__C_CTL_SETRB:
- if (prev_cmd != ETIR__C_STA_PQ)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (prev_cmd),
- _bfd_vms_etir_name (cmd));
- return false;
- }
- cur_psect = cur_psidx;
- vaddr = cur_addend;
- cur_psidx = -1;
- cur_addend = 0;
- continue;
- case ETIR__C_STA_LW: /* ALPHA_R_REFLONG abs_section, step 1 */
- /* ALPHA_R_REFLONG und_section, step 2 */
- if (prev_cmd != -1)
- {
- if (prev_cmd != ETIR__C_STA_GBL)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
- _bfd_vms_etir_name (ETIR__C_STA_LW));
- return false;
- }
- }
- cur_addend = bfd_getl32 (ptr + 4);
- prev_cmd = cmd;
- continue;
- case ETIR__C_STA_QW: /* ALPHA_R_REFQUAD abs_section, step 1 */
- /* ALPHA_R_REFQUAD und_section, step 2 */
- if (prev_cmd != -1 && prev_cmd != ETIR__C_STA_GBL)
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("unknown reloc %s + %s"), _bfd_vms_etir_name (cmd),
- _bfd_vms_etir_name (ETIR__C_STA_QW));
- return false;
- }
- cur_addend = bfd_getl64 (ptr + 4);
- prev_cmd = cmd;
- continue;
- case ETIR__C_STO_LW: /* ALPHA_R_REFLONG und_section, step 4 */
- /* ALPHA_R_REFLONG abs_section, step 2 */
- /* ALPHA_R_REFLONG others, step 2 */
- if (prev_cmd != ETIR__C_OPR_ADD
- && prev_cmd != ETIR__C_STA_LW
- && prev_cmd != ETIR__C_STA_PQ)
- {
- /* xgettext:c-format */
- _bfd_error_handler (_("unknown reloc %s + %s"),
- _bfd_vms_etir_name (prev_cmd),
- _bfd_vms_etir_name (ETIR__C_STO_LW));
- return false;
- }
- reloc_code = BFD_RELOC_32;
- break;
- case ETIR__C_STO_QW: /* ALPHA_R_REFQUAD und_section, step 4 */
- /* ALPHA_R_REFQUAD abs_section, step 2 */
- if (prev_cmd != ETIR__C_OPR_ADD && prev_cmd != ETIR__C_STA_QW)
- {
- /* xgettext:c-format */
- _bfd_error_handler (_("unknown reloc %s + %s"),
- _bfd_vms_etir_name (prev_cmd),
- _bfd_vms_etir_name (ETIR__C_STO_QW));
- return false;
- }
- reloc_code = BFD_RELOC_64;
- break;
- case ETIR__C_STO_OFF: /* ALPHA_R_REFQUAD others, step 2 */
- if (prev_cmd != ETIR__C_STA_PQ)
- {
- /* xgettext:c-format */
- _bfd_error_handler (_("unknown reloc %s + %s"),
- _bfd_vms_etir_name (prev_cmd),
- _bfd_vms_etir_name (ETIR__C_STO_OFF));
- return false;
- }
- reloc_code = BFD_RELOC_64;
- break;
- case ETIR__C_OPR_ADD: /* ALPHA_R_REFLONG und_section, step 3 */
- /* ALPHA_R_REFQUAD und_section, step 3 */
- if (prev_cmd != ETIR__C_STA_LW && prev_cmd != ETIR__C_STA_QW)
- {
- /* xgettext:c-format */
- _bfd_error_handler (_("unknown reloc %s + %s"),
- _bfd_vms_etir_name (prev_cmd),
- _bfd_vms_etir_name (ETIR__C_OPR_ADD));
- return false;
- }
- prev_cmd = ETIR__C_OPR_ADD;
- continue;
- case ETIR__C_STO_CA: /* ALPHA_R_CODEADDR */
- reloc_code = BFD_RELOC_ALPHA_CODEADDR;
- cur_sym = ptr + 4;
- break;
- case ETIR__C_STO_GBL: /* ALPHA_R_REFQUAD und_section */
- reloc_code = BFD_RELOC_64;
- cur_sym = ptr + 4;
- break;
- case ETIR__C_STO_GBL_LW: /* ALPHA_R_REFLONG und_section */
- reloc_code = BFD_RELOC_32;
- cur_sym = ptr + 4;
- break;
- case ETIR__C_STC_LP_PSB: /* ALPHA_R_LINKAGE */
- reloc_code = BFD_RELOC_ALPHA_LINKAGE;
- cur_sym = ptr + 8;
- break;
- case ETIR__C_STC_NOP_GBL: /* ALPHA_R_NOP */
- reloc_code = BFD_RELOC_ALPHA_NOP;
- goto call_reloc;
- case ETIR__C_STC_BSR_GBL: /* ALPHA_R_BSR */
- reloc_code = BFD_RELOC_ALPHA_BSR;
- goto call_reloc;
- case ETIR__C_STC_LDA_GBL: /* ALPHA_R_LDA */
- reloc_code = BFD_RELOC_ALPHA_LDA;
- goto call_reloc;
- case ETIR__C_STC_BOH_GBL: /* ALPHA_R_BOH */
- reloc_code = BFD_RELOC_ALPHA_BOH;
- goto call_reloc;
- call_reloc:
- cur_sym = ptr + 4 + 32;
- cur_address = bfd_getl64 (ptr + 4 + 8);
- cur_addend = bfd_getl64 (ptr + 4 + 24);
- break;
- case ETIR__C_STO_IMM:
- vaddr += bfd_getl32 (ptr + 4);
- continue;
- default:
- _bfd_error_handler (_("unknown reloc %s"),
- _bfd_vms_etir_name (cmd));
- return false;
- }
- {
- asection *sec;
- struct vms_section_data_struct *vms_sec;
- arelent *reloc;
- bfd_size_type size;
- /* Get section to which the relocation applies. */
- if (cur_psect < 0 || cur_psect > (int)PRIV (section_count))
- {
- _bfd_error_handler (_("invalid section index in ETIR"));
- return false;
- }
- if (PRIV (sections) == NULL)
- return false;
- sec = PRIV (sections)[cur_psect];
- if (sec == bfd_abs_section_ptr)
- {
- _bfd_error_handler (_("relocation for non-REL psect"));
- return false;
- }
- vms_sec = vms_section_data (sec);
- /* Allocate a reloc entry. */
- if (sec->reloc_count >= vms_sec->reloc_max)
- {
- if (vms_sec->reloc_max == 0)
- {
- vms_sec->reloc_max = 64;
- sec->relocation = bfd_zmalloc
- (vms_sec->reloc_max * sizeof (arelent));
- }
- else
- {
- vms_sec->reloc_max *= 2;
- sec->relocation = bfd_realloc_or_free
- (sec->relocation, vms_sec->reloc_max * sizeof (arelent));
- if (sec->relocation == NULL)
- return false;
- }
- }
- reloc = &sec->relocation[sec->reloc_count];
- sec->reloc_count++;
- reloc->howto = bfd_reloc_type_lookup (abfd, reloc_code);
- if (cur_sym != NULL)
- {
- unsigned int j;
- unsigned int symlen = *cur_sym;
- asymbol **sym;
- /* Linear search. */
- symlen = *cur_sym;
- cur_sym++;
- sym = NULL;
- for (j = 0; j < PRIV (gsd_sym_count); j++)
- if (PRIV (syms)[j]->namelen == symlen
- && memcmp (PRIV (syms)[j]->name, cur_sym, symlen) == 0)
- {
- sym = &PRIV (csymbols)[j];
- break;
- }
- if (sym == NULL)
- {
- _bfd_error_handler (_("unknown symbol in command %s"),
- _bfd_vms_etir_name (cmd));
- reloc->sym_ptr_ptr = NULL;
- }
- else
- reloc->sym_ptr_ptr = sym;
- }
- else if (cur_psidx >= 0)
- {
- if (PRIV (sections) == NULL || cur_psidx >= (int) PRIV (section_count))
- return false;
- reloc->sym_ptr_ptr =
- PRIV (sections)[cur_psidx]->symbol_ptr_ptr;
- }
- else
- reloc->sym_ptr_ptr = NULL;
- reloc->address = cur_address;
- reloc->addend = cur_addend;
- if (reloc_code == ALPHA_R_LINKAGE)
- size = 16;
- else
- size = bfd_get_reloc_size (reloc->howto);
- vaddr += size;
- }
- cur_addend = 0;
- prev_cmd = -1;
- cur_sym = NULL;
- cur_psidx = -1;
- }
- }
- vms_debug2 ((3, "alpha_vms_slurp_relocs: result = true\n"));
- return true;
- }
- /* Return the number of bytes required to store the relocation
- information associated with the given section. */
- static long
- alpha_vms_get_reloc_upper_bound (bfd *abfd ATTRIBUTE_UNUSED, asection *section)
- {
- alpha_vms_slurp_relocs (abfd);
- return (section->reloc_count + 1L) * sizeof (arelent *);
- }
- /* Convert relocations from VMS (external) form into BFD internal
- form. Return the number of relocations. */
- static long
- alpha_vms_canonicalize_reloc (bfd *abfd, asection *section, arelent **relptr,
- asymbol **symbols ATTRIBUTE_UNUSED)
- {
- arelent *tblptr;
- int count;
- if (!alpha_vms_slurp_relocs (abfd))
- return -1;
- count = section->reloc_count;
- tblptr = section->relocation;
- while (count--)
- *relptr++ = tblptr++;
- *relptr = (arelent *) NULL;
- return section->reloc_count;
- }
- /* Install a new set of internal relocs. */
- #define alpha_vms_set_reloc _bfd_generic_set_reloc
- /* This is just copied from ecoff-alpha, needs to be fixed probably. */
- /* How to process the various reloc types. */
- static bfd_reloc_status_type
- reloc_nil (bfd * abfd ATTRIBUTE_UNUSED,
- arelent *reloc ATTRIBUTE_UNUSED,
- asymbol *sym ATTRIBUTE_UNUSED,
- void * data ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- bfd *output_bfd ATTRIBUTE_UNUSED,
- char **error_message ATTRIBUTE_UNUSED)
- {
- #if VMS_DEBUG
- vms_debug (1, "reloc_nil (abfd %p, output_bfd %p)\n", abfd, output_bfd);
- vms_debug (2, "In section %s, symbol %s\n",
- sec->name, sym->name);
- vms_debug (2, "reloc sym %s, addr %08lx, addend %08lx, reloc is a %s\n",
- reloc->sym_ptr_ptr[0]->name,
- (unsigned long)reloc->address,
- (unsigned long)reloc->addend, reloc->howto->name);
- vms_debug (2, "data at %p\n", data);
- /* _bfd_hexdump (2, data, bfd_get_reloc_size (reloc->howto), 0); */
- #endif
- return bfd_reloc_ok;
- }
- /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
- from smaller values. Start with zero, widen, *then* decrement. */
- #define MINUS_ONE (((bfd_vma)0) - 1)
- static reloc_howto_type alpha_howto_table[] =
- {
- HOWTO (ALPHA_R_IGNORE, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 8, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "IGNORE", /* Name. */
- true, /* Partial_inplace. */
- 0, /* Source mask */
- 0, /* Dest mask. */
- true), /* PC rel offset. */
- /* A 64 bit reference to a symbol. */
- HOWTO (ALPHA_R_REFQUAD, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "REFQUAD", /* Name. */
- true, /* Partial_inplace. */
- MINUS_ONE, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- false), /* PC rel offset. */
- /* A 21 bit branch. The native assembler generates these for
- branches within the text segment, and also fills in the PC
- relative offset in the instruction. */
- HOWTO (ALPHA_R_BRADDR, /* Type. */
- 2, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 21, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "BRADDR", /* Name. */
- true, /* Partial_inplace. */
- 0x1fffff, /* Source mask. */
- 0x1fffff, /* Dest mask. */
- false), /* PC rel offset. */
- /* A hint for a jump to a register. */
- HOWTO (ALPHA_R_HINT, /* Type. */
- 2, /* Rightshift. */
- 1, /* Size (0 = byte, 1 = short, 2 = long). */
- 14, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "HINT", /* Name. */
- true, /* Partial_inplace. */
- 0x3fff, /* Source mask. */
- 0x3fff, /* Dest mask. */
- false), /* PC rel offset. */
- /* 16 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL16, /* Type. */
- 0, /* Rightshift. */
- 1, /* Size (0 = byte, 1 = short, 2 = long). */
- 16, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL16", /* Name. */
- true, /* Partial_inplace. */
- 0xffff, /* Source mask. */
- 0xffff, /* Dest mask. */
- false), /* PC rel offset. */
- /* 32 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL32, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL32", /* Name. */
- true, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- /* A 64 bit PC relative offset. */
- HOWTO (ALPHA_R_SREL64, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "SREL64", /* Name. */
- true, /* Partial_inplace. */
- MINUS_ONE, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- false), /* PC rel offset. */
- /* Push a value on the reloc evaluation stack. */
- HOWTO (ALPHA_R_OP_PUSH, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PUSH", /* Name. */
- false, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- false), /* PC rel offset. */
- /* Store the value from the stack at the given address. Store it in
- a bitfield of size r_size starting at bit position r_offset. */
- HOWTO (ALPHA_R_OP_STORE, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_STORE", /* Name. */
- false, /* Partial_inplace. */
- 0, /* Source mask. */
- MINUS_ONE, /* Dest mask. */
- false), /* PC rel offset. */
- /* Subtract the reloc address from the value on the top of the
- relocation stack. */
- HOWTO (ALPHA_R_OP_PSUB, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PSUB", /* Name. */
- false, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- false), /* PC rel offset. */
- /* Shift the value on the top of the relocation stack right by the
- given value. */
- HOWTO (ALPHA_R_OP_PRSHIFT, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "OP_PRSHIFT", /* Name. */
- false, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- false), /* PC rel offset. */
- /* Hack. Linkage is done by linker. */
- HOWTO (ALPHA_R_LINKAGE, /* Type. */
- 0, /* Rightshift. */
- 0, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "LINKAGE", /* Name. */
- false, /* Partial_inplace. */
- 0, /* Source mask. */
- 0, /* Dest mask. */
- false), /* PC rel offset. */
- /* A 32 bit reference to a symbol. */
- HOWTO (ALPHA_R_REFLONG, /* Type. */
- 0, /* Rightshift. */
- 2, /* Size (0 = byte, 1 = short, 2 = long). */
- 32, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_bitfield, /* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "REFLONG", /* Name. */
- true, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- /* A 64 bit reference to a procedure, written as 32 bit value. */
- HOWTO (ALPHA_R_CODEADDR, /* Type. */
- 0, /* Rightshift. */
- 4, /* Size (0 = byte, 1 = short, 2 = long). */
- 64, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_signed,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "CODEADDR", /* Name. */
- false, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- HOWTO (ALPHA_R_NOP, /* Type. */
- 0, /* Rightshift. */
- 3, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- /* The following value must match that of ALPHA_R_BSR/ALPHA_R_BOH
- because the calculations for the 3 relocations are the same.
- See B.4.5.2 of the OpenVMS Linker Utility Manual. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "NOP", /* Name. */
- false, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- HOWTO (ALPHA_R_BSR, /* Type. */
- 0, /* Rightshift. */
- 3, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "BSR", /* Name. */
- false, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- HOWTO (ALPHA_R_LDA, /* Type. */
- 0, /* Rightshift. */
- 3, /* Size (0 = byte, 1 = short, 2 = long). */
- 0, /* Bitsize. */
- false, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "LDA", /* Name. */
- false, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- HOWTO (ALPHA_R_BOH, /* Type. */
- 0, /* Rightshift. */
- 3, /* Size (0 = byte, 1 = short, 2 = long, 3 = nil). */
- 0, /* Bitsize. */
- true, /* PC relative. */
- 0, /* Bitpos. */
- complain_overflow_dont,/* Complain_on_overflow. */
- reloc_nil, /* Special_function. */
- "BOH", /* Name. */
- false, /* Partial_inplace. */
- 0xffffffff, /* Source mask. */
- 0xffffffff, /* Dest mask. */
- false), /* PC rel offset. */
- };
- /* Return a pointer to a howto structure which, when invoked, will perform
- the relocation code on data from the architecture noted. */
- static reloc_howto_type *
- alpha_vms_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
- bfd_reloc_code_real_type code)
- {
- int alpha_type;
- vms_debug2 ((1, "vms_bfd_reloc_type_lookup (%p, %d)\t", abfd, code));
- switch (code)
- {
- case BFD_RELOC_16: alpha_type = ALPHA_R_SREL16; break;
- case BFD_RELOC_32: alpha_type = ALPHA_R_REFLONG; break;
- case BFD_RELOC_64: alpha_type = ALPHA_R_REFQUAD; break;
- case BFD_RELOC_CTOR: alpha_type = ALPHA_R_REFQUAD; break;
- case BFD_RELOC_23_PCREL_S2: alpha_type = ALPHA_R_BRADDR; break;
- case BFD_RELOC_ALPHA_HINT: alpha_type = ALPHA_R_HINT; break;
- case BFD_RELOC_16_PCREL: alpha_type = ALPHA_R_SREL16; break;
- case BFD_RELOC_32_PCREL: alpha_type = ALPHA_R_SREL32; break;
- case BFD_RELOC_64_PCREL: alpha_type = ALPHA_R_SREL64; break;
- case BFD_RELOC_ALPHA_LINKAGE: alpha_type = ALPHA_R_LINKAGE; break;
- case BFD_RELOC_ALPHA_CODEADDR: alpha_type = ALPHA_R_CODEADDR; break;
- case BFD_RELOC_ALPHA_NOP: alpha_type = ALPHA_R_NOP; break;
- case BFD_RELOC_ALPHA_BSR: alpha_type = ALPHA_R_BSR; break;
- case BFD_RELOC_ALPHA_LDA: alpha_type = ALPHA_R_LDA; break;
- case BFD_RELOC_ALPHA_BOH: alpha_type = ALPHA_R_BOH; break;
- default:
- _bfd_error_handler (_("reloc (%d) is *UNKNOWN*"), code);
- return NULL;
- }
- vms_debug2 ((2, "reloc is %s\n", alpha_howto_table[alpha_type].name));
- return & alpha_howto_table[alpha_type];
- }
- static reloc_howto_type *
- alpha_vms_bfd_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
- const char *r_name)
- {
- unsigned int i;
- for (i = 0;
- i < sizeof (alpha_howto_table) / sizeof (alpha_howto_table[0]);
- i++)
- if (alpha_howto_table[i].name != NULL
- && strcasecmp (alpha_howto_table[i].name, r_name) == 0)
- return &alpha_howto_table[i];
- return NULL;
- }
- static long
- alpha_vms_get_synthetic_symtab (bfd *abfd,
- long symcount ATTRIBUTE_UNUSED,
- asymbol **usyms ATTRIBUTE_UNUSED,
- long dynsymcount ATTRIBUTE_UNUSED,
- asymbol **dynsyms ATTRIBUTE_UNUSED,
- asymbol **ret)
- {
- asymbol *syms;
- unsigned int i;
- unsigned int n = 0;
- syms = (asymbol *) bfd_malloc (PRIV (norm_sym_count) * sizeof (asymbol));
- *ret = syms;
- if (syms == NULL)
- return -1;
- for (i = 0; i < PRIV (gsd_sym_count); i++)
- {
- struct vms_symbol_entry *e = PRIV (syms)[i];
- asymbol *sym;
- flagword flags;
- symvalue value;
- asection *sec;
- const char *name;
- char *sname;
- int l;
- name = e->name;
- value = 0;
- flags = BSF_LOCAL | BSF_SYNTHETIC;
- sec = NULL;
- switch (e->typ)
- {
- case EGSD__C_SYM:
- case EGSD__C_SYMG:
- if ((e->flags & EGSY__V_DEF) && (e->flags & EGSY__V_NORM))
- {
- value = e->code_value;
- sec = e->code_section;
- }
- else
- continue;
- break;
- default:
- continue;
- }
- l = strlen (name);
- sname = bfd_alloc (abfd, l + 5);
- if (sname == NULL)
- return false;
- memcpy (sname, name, l);
- memcpy (sname + l, "..en", 5);
- sym = &syms[n++];
- sym->name = sname;
- sym->section = sec;
- sym->flags = flags;
- sym->value = value;
- sym->udata.p = NULL;
- }
- return n;
- }
- /* Private dump. */
- static const char *
- vms_time_to_str (unsigned char *buf)
- {
- time_t t = vms_rawtime_to_time_t (buf);
- char *res = ctime (&t);
- if (!res)
- res = "*invalid time*";
- else
- res[24] = 0;
- return res;
- }
- static void
- evax_bfd_print_emh (FILE *file, unsigned char *rec, unsigned int rec_len)
- {
- struct vms_emh_common *emh = (struct vms_emh_common *)rec;
- unsigned int subtype;
- int extra;
- subtype = (unsigned) bfd_getl16 (emh->subtyp);
- /* xgettext:c-format */
- fprintf (file, _(" EMH %u (len=%u): "), subtype, rec_len);
- /* PR 21618: Check for invalid lengths. */
- if (rec_len < sizeof (* emh))
- {
- fprintf (file, _(" Error: The length is less than the length of an EMH record\n"));
- return;
- }
- extra = rec_len - sizeof (struct vms_emh_common);
- switch (subtype)
- {
- case EMH__C_MHD:
- {
- struct vms_emh_mhd *mhd = (struct vms_emh_mhd *) rec;
- unsigned char *name;
- unsigned char *nextname;
- unsigned char *maxname;
- /* PR 21840: Check for invalid lengths. */
- if (rec_len < sizeof (* mhd))
- {
- fprintf (file, _(" Error: The record length is less than the size of an EMH_MHD record\n"));
- return;
- }
- fprintf (file, _("Module header\n"));
- fprintf (file, _(" structure level: %u\n"), mhd->strlvl);
- fprintf (file, _(" max record size: %u\n"),
- (unsigned) bfd_getl32 (mhd->recsiz));
- name = (unsigned char *) (mhd + 1);
- maxname = (unsigned char *) rec + rec_len;
- if (name > maxname - 2)
- {
- fprintf (file, _(" Error: The module name is missing\n"));
- return;
- }
- nextname = name + name[0] + 1;
- if (nextname >= maxname)
- {
- fprintf (file, _(" Error: The module name is too long\n"));
- return;
- }
- fprintf (file, _(" module name : %.*s\n"), name[0], name + 1);
- name = nextname;
- if (name > maxname - 2)
- {
- fprintf (file, _(" Error: The module version is missing\n"));
- return;
- }
- nextname = name + name[0] + 1;
- if (nextname >= maxname)
- {
- fprintf (file, _(" Error: The module version is too long\n"));
- return;
- }
- fprintf (file, _(" module version : %.*s\n"), name[0], name + 1);
- name = nextname;
- if ((maxname - name) < 17 && maxname[-1] != 0)
- fprintf (file, _(" Error: The compile date is truncated\n"));
- else
- fprintf (file, _(" compile date : %.17s\n"), name);
- }
- break;
- case EMH__C_LNM:
- fprintf (file, _("Language Processor Name\n"));
- fprintf (file, _(" language name: %.*s\n"), extra, (char *)(emh + 1));
- break;
- case EMH__C_SRC:
- fprintf (file, _("Source Files Header\n"));
- fprintf (file, _(" file: %.*s\n"), extra, (char *)(emh + 1));
- break;
- case EMH__C_TTL:
- fprintf (file, _("Title Text Header\n"));
- fprintf (file, _(" title: %.*s\n"), extra, (char *)(emh + 1));
- break;
- case EMH__C_CPR:
- fprintf (file, _("Copyright Header\n"));
- fprintf (file, _(" copyright: %.*s\n"), extra, (char *)(emh + 1));
- break;
- default:
- fprintf (file, _("unhandled emh subtype %u\n"), subtype);
- break;
- }
- }
- static void
- evax_bfd_print_eeom (FILE *file, unsigned char *rec, unsigned int rec_len)
- {
- struct vms_eeom *eeom = (struct vms_eeom *)rec;
- fprintf (file, _(" EEOM (len=%u):\n"), rec_len);
- /* PR 21618: Check for invalid lengths. */
- if (rec_len < sizeof (* eeom))
- {
- fprintf (file, _(" Error: The length is less than the length of an EEOM record\n"));
- return;
- }
- fprintf (file, _(" number of cond linkage pairs: %u\n"),
- (unsigned)bfd_getl32 (eeom->total_lps));
- fprintf (file, _(" completion code: %u\n"),
- (unsigned)bfd_getl16 (eeom->comcod));
- if (rec_len > 10)
- {
- fprintf (file, _(" transfer addr flags: 0x%02x\n"), eeom->tfrflg);
- fprintf (file, _(" transfer addr psect: %u\n"),
- (unsigned)bfd_getl32 (eeom->psindx));
- fprintf (file, _(" transfer address : 0x%08x\n"),
- (unsigned)bfd_getl32 (eeom->tfradr));
- }
- }
- static void
- exav_bfd_print_egsy_flags (unsigned int flags, FILE *file)
- {
- if (flags & EGSY__V_WEAK)
- fputs (_(" WEAK"), file);
- if (flags & EGSY__V_DEF)
- fputs (_(" DEF"), file);
- if (flags & EGSY__V_UNI)
- fputs (_(" UNI"), file);
- if (flags & EGSY__V_REL)
- fputs (_(" REL"), file);
- if (flags & EGSY__V_COMM)
- fputs (_(" COMM"), file);
- if (flags & EGSY__V_VECEP)
- fputs (_(" VECEP"), file);
- if (flags & EGSY__V_NORM)
- fputs (_(" NORM"), file);
- if (flags & EGSY__V_QUAD_VAL)
- fputs (_(" QVAL"), file);
- }
- static void
- evax_bfd_print_egsd_flags (FILE *file, unsigned int flags)
- {
- if (flags & EGPS__V_PIC)
- fputs (_(" PIC"), file);
- if (flags & EGPS__V_LIB)
- fputs (_(" LIB"), file);
- if (flags & EGPS__V_OVR)
- fputs (_(" OVR"), file);
- if (flags & EGPS__V_REL)
- fputs (_(" REL"), file);
- if (flags & EGPS__V_GBL)
- fputs (_(" GBL"), file);
- if (flags & EGPS__V_SHR)
- fputs (_(" SHR"), file);
- if (flags & EGPS__V_EXE)
- fputs (_(" EXE"), file);
- if (flags & EGPS__V_RD)
- fputs (_(" RD"), file);
- if (flags & EGPS__V_WRT)
- fputs (_(" WRT"), file);
- if (flags & EGPS__V_VEC)
- fputs (_(" VEC"), file);
- if (flags & EGPS__V_NOMOD)
- fputs (_(" NOMOD"), file);
- if (flags & EGPS__V_COM)
- fputs (_(" COM"), file);
- if (flags & EGPS__V_ALLOC_64BIT)
- fputs (_(" 64B"), file);
- }
- static void
- evax_bfd_print_egsd (FILE *file, unsigned char *rec, unsigned int rec_len)
- {
- unsigned int off = sizeof (struct vms_egsd);
- unsigned int n = 0;
- fprintf (file, _(" EGSD (len=%u):\n"), rec_len);
- if (rec_len < sizeof (struct vms_egsd) + sizeof (struct vms_egsd_entry))
- return;
- while (off <= rec_len - sizeof (struct vms_egsd_entry))
- {
- struct vms_egsd_entry *e = (struct vms_egsd_entry *)(rec + off);
- unsigned int type;
- unsigned int len;
- unsigned int rest;
- type = (unsigned)bfd_getl16 (e->gsdtyp);
- len = (unsigned)bfd_getl16 (e->gsdsiz);
- /* xgettext:c-format */
- fprintf (file, _(" EGSD entry %2u (type: %u, len: %u): "),
- n, type, len);
- n++;
- if (len < sizeof (struct vms_egsd_entry) || len > rec_len - off)
- {
- fprintf (file, _(" Erroneous length\n"));
- return;
- }
- switch (type)
- {
- case EGSD__C_PSC:
- if (len >= offsetof (struct vms_egps, name))
- {
- struct vms_egps *egps = (struct vms_egps *) e;
- unsigned int flags = bfd_getl16 (egps->flags);
- unsigned int l;
- fprintf (file, _("PSC - Program section definition\n"));
- fprintf (file, _(" alignment : 2**%u\n"), egps->align);
- fprintf (file, _(" flags : 0x%04x"), flags);
- evax_bfd_print_egsd_flags (file, flags);
- fputc ('\n', file);
- l = bfd_getl32 (egps->alloc);
- fprintf (file, _(" alloc (len): %u (0x%08x)\n"), l, l);
- rest = len - offsetof (struct vms_egps, name);
- fprintf (file, _(" name : %.*s\n"),
- egps->namlng > rest ? rest : egps->namlng,
- egps->name);
- }
- break;
- case EGSD__C_SPSC:
- if (len >= offsetof (struct vms_esgps, name))
- {
- struct vms_esgps *esgps = (struct vms_esgps *) e;
- unsigned int flags = bfd_getl16 (esgps->flags);
- unsigned int l;
- fprintf (file, _("SPSC - Shared Image Program section def\n"));
- fprintf (file, _(" alignment : 2**%u\n"), esgps->align);
- fprintf (file, _(" flags : 0x%04x"), flags);
- evax_bfd_print_egsd_flags (file, flags);
- fputc ('\n', file);
- l = bfd_getl32 (esgps->alloc);
- fprintf (file, _(" alloc (len) : %u (0x%08x)\n"), l, l);
- fprintf (file, _(" image offset : 0x%08x\n"),
- (unsigned int) bfd_getl32 (esgps->base));
- fprintf (file, _(" symvec offset : 0x%08x\n"),
- (unsigned int) bfd_getl32 (esgps->value));
- rest = len - offsetof (struct vms_esgps, name);
- fprintf (file, _(" name : %.*s\n"),
- esgps->namlng > rest ? rest : esgps->namlng,
- esgps->name);
- }
- break;
- case EGSD__C_SYM:
- if (len >= sizeof (struct vms_egsy))
- {
- struct vms_egsy *egsy = (struct vms_egsy *) e;
- unsigned int flags = bfd_getl16 (egsy->flags);
- if ((flags & EGSY__V_DEF) != 0
- && len >= offsetof (struct vms_esdf, name))
- {
- struct vms_esdf *esdf = (struct vms_esdf *) e;
- fprintf (file, _("SYM - Global symbol definition\n"));
- fprintf (file, _(" flags: 0x%04x"), flags);
- exav_bfd_print_egsy_flags (flags, file);
- fputc ('\n', file);
- fprintf (file, _(" psect offset: 0x%08x\n"),
- (unsigned) bfd_getl32 (esdf->value));
- if (flags & EGSY__V_NORM)
- {
- fprintf (file, _(" code address: 0x%08x\n"),
- (unsigned) bfd_getl32 (esdf->code_address));
- fprintf (file, _(" psect index for entry point : %u\n"),
- (unsigned) bfd_getl32 (esdf->ca_psindx));
- }
- fprintf (file, _(" psect index : %u\n"),
- (unsigned) bfd_getl32 (esdf->psindx));
- rest = len - offsetof (struct vms_esdf, name);
- fprintf (file, _(" name : %.*s\n"),
- esdf->namlng > rest ? rest : esdf->namlng,
- esdf->name);
- }
- else if (len >= offsetof (struct vms_esrf, name))
- {
- struct vms_esrf *esrf = (struct vms_esrf *)e;
- fprintf (file, _("SYM - Global symbol reference\n"));
- rest = len - offsetof (struct vms_esrf, name);
- fprintf (file, _(" name : %.*s\n"),
- esrf->namlng > rest ? rest : esrf->namlng,
- esrf->name);
- }
- }
- break;
- case EGSD__C_IDC:
- if (len >= sizeof (struct vms_eidc))
- {
- struct vms_eidc *eidc = (struct vms_eidc *) e;
- unsigned int flags = bfd_getl32 (eidc->flags);
- unsigned char *p;
- fprintf (file, _("IDC - Ident Consistency check\n"));
- fprintf (file, _(" flags : 0x%08x"), flags);
- if (flags & EIDC__V_BINIDENT)
- fputs (" BINDENT", file);
- fputc ('\n', file);
- fprintf (file, _(" id match : %x\n"),
- (flags >> EIDC__V_IDMATCH_SH) & EIDC__V_IDMATCH_MASK);
- fprintf (file, _(" error severity: %x\n"),
- (flags >> EIDC__V_ERRSEV_SH) & EIDC__V_ERRSEV_MASK);
- p = eidc->name;
- rest = len - (p - (unsigned char *) e);
- fprintf (file, _(" entity name : %.*s\n"),
- p[0] > rest - 1 ? rest - 1 : p[0], p + 1);
- if (rest > 1u + p[0])
- {
- rest -= 1 + p[0];
- p += 1 + p[0];
- fprintf (file, _(" object name : %.*s\n"),
- p[0] > rest - 1 ? rest - 1 : p[0], p + 1);
- if (rest > 1u + p[0])
- {
- rest -= 1 + p[0];
- p += 1 + p[0];
- if (flags & EIDC__V_BINIDENT)
- {
- if (rest >= 4)
- fprintf (file, _(" binary ident : 0x%08x\n"),
- (unsigned) bfd_getl32 (p));
- }
- else
- fprintf (file, _(" ascii ident : %.*s\n"),
- p[0] > rest - 1 ? rest - 1 : p[0], p + 1);
- }
- }
- }
- break;
- case EGSD__C_SYMG:
- if (len >= offsetof (struct vms_egst, name))
- {
- struct vms_egst *egst = (struct vms_egst *) e;
- unsigned int flags = bfd_getl16 (egst->header.flags);
- fprintf (file, _("SYMG - Universal symbol definition\n"));
- fprintf (file, _(" flags: 0x%04x"), flags);
- exav_bfd_print_egsy_flags (flags, file);
- fputc ('\n', file);
- fprintf (file, _(" symbol vector offset: 0x%08x\n"),
- (unsigned) bfd_getl32 (egst->value));
- fprintf (file, _(" entry point: 0x%08x\n"),
- (unsigned) bfd_getl32 (egst->lp_1));
- fprintf (file, _(" proc descr : 0x%08x\n"),
- (unsigned) bfd_getl32 (egst->lp_2));
- fprintf (file, _(" psect index: %u\n"),
- (unsigned) bfd_getl32 (egst->psindx));
- rest = len - offsetof (struct vms_egst, name);
- fprintf (file, _(" name : %.*s\n"),
- egst->namlng > rest ? rest : egst->namlng,
- egst->name);
- }
- break;
- case EGSD__C_SYMV:
- if (len >= offsetof (struct vms_esdfv, name))
- {
- struct vms_esdfv *esdfv = (struct vms_esdfv *) e;
- unsigned int flags = bfd_getl16 (esdfv->flags);
- fprintf (file, _("SYMV - Vectored symbol definition\n"));
- fprintf (file, _(" flags: 0x%04x"), flags);
- exav_bfd_print_egsy_flags (flags, file);
- fputc ('\n', file);
- fprintf (file, _(" vector : 0x%08x\n"),
- (unsigned) bfd_getl32 (esdfv->vector));
- fprintf (file, _(" psect offset: %u\n"),
- (unsigned) bfd_getl32 (esdfv->value));
- fprintf (file, _(" psect index : %u\n"),
- (unsigned) bfd_getl32 (esdfv->psindx));
- rest = len - offsetof (struct vms_esdfv, name);
- fprintf (file, _(" name : %.*s\n"),
- esdfv->namlng > rest ? rest : esdfv->namlng,
- esdfv->name);
- }
- break;
- case EGSD__C_SYMM:
- if (len >= offsetof (struct vms_esdfm, name))
- {
- struct vms_esdfm *esdfm = (struct vms_esdfm *) e;
- unsigned int flags = bfd_getl16 (esdfm->flags);
- fprintf (file,
- _("SYMM - Global symbol definition with version\n"));
- fprintf (file, _(" flags: 0x%04x"), flags);
- exav_bfd_print_egsy_flags (flags, file);
- fputc ('\n', file);
- fprintf (file, _(" version mask: 0x%08x\n"),
- (unsigned)bfd_getl32 (esdfm->version_mask));
- fprintf (file, _(" psect offset: %u\n"),
- (unsigned)bfd_getl32 (esdfm->value));
- fprintf (file, _(" psect index : %u\n"),
- (unsigned)bfd_getl32 (esdfm->psindx));
- rest = len - offsetof (struct vms_esdfm, name);
- fprintf (file, _(" name : %.*s\n"),
- esdfm->namlng > rest ? rest : esdfm->namlng,
- esdfm->name);
- }
- break;
- default:
- fprintf (file, _("unhandled egsd entry type %u\n"), type);
- break;
- }
- off += len;
- }
- }
- static void
- evax_bfd_print_hex (FILE *file, const char *pfx,
- const unsigned char *buf, unsigned int len)
- {
- unsigned int i;
- unsigned int n;
- n = 0;
- for (i = 0; i < len; i++)
- {
- if (n == 0)
- fputs (pfx, file);
- fprintf (file, " %02x", buf[i]);
- n++;
- if (n == 16)
- {
- n = 0;
- fputc ('\n', file);
- }
- }
- if (n != 0)
- fputc ('\n', file);
- }
- static void
- evax_bfd_print_etir_stc_ir (FILE *file, const unsigned char *buf,
- unsigned int len, int is_ps)
- {
- if (is_ps ? len < 44 : len < 33)
- return;
- /* xgettext:c-format */
- fprintf (file, _(" linkage index: %u, replacement insn: 0x%08x\n"),
- (unsigned)bfd_getl32 (buf),
- (unsigned)bfd_getl32 (buf + 16));
- /* xgettext:c-format */
- fprintf (file, _(" psect idx 1: %u, offset 1: 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (buf + 4),
- (unsigned)bfd_getl32 (buf + 12),
- (unsigned)bfd_getl32 (buf + 8));
- /* xgettext:c-format */
- fprintf (file, _(" psect idx 2: %u, offset 2: 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (buf + 20),
- (unsigned)bfd_getl32 (buf + 28),
- (unsigned)bfd_getl32 (buf + 24));
- if (is_ps)
- /* xgettext:c-format */
- fprintf (file, _(" psect idx 3: %u, offset 3: 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (buf + 32),
- (unsigned)bfd_getl32 (buf + 40),
- (unsigned)bfd_getl32 (buf + 36));
- else
- fprintf (file, _(" global name: %.*s\n"),
- buf[32] > len - 33 ? len - 33 : buf[32],
- buf + 33);
- }
- static void
- evax_bfd_print_etir (FILE *file, const char *name,
- unsigned char *rec, unsigned int rec_len)
- {
- unsigned int off = sizeof (struct vms_eobjrec);
- /* xgettext:c-format */
- fprintf (file, _(" %s (len=%u):\n"), name, (unsigned) rec_len);
- if (rec_len < sizeof (struct vms_eobjrec) + sizeof (struct vms_etir))
- return;
- while (off <= rec_len - sizeof (struct vms_etir))
- {
- struct vms_etir *etir = (struct vms_etir *)(rec + off);
- unsigned char *buf;
- unsigned int type;
- unsigned int size;
- unsigned int rest;
- type = bfd_getl16 (etir->rectyp);
- size = bfd_getl16 (etir->size);
- buf = rec + off + sizeof (struct vms_etir);
- if (size < sizeof (struct vms_etir) || size > rec_len - off)
- {
- fprintf (file, _(" Erroneous length\n"));
- return;
- }
- /* xgettext:c-format */
- fprintf (file, _(" (type: %3u, size: %3u): "), type, size);
- rest = size - sizeof (struct vms_etir);
- switch (type)
- {
- case ETIR__C_STA_GBL:
- if (rest >= 1)
- fprintf (file, _("STA_GBL (stack global) %.*s\n"),
- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1);
- break;
- case ETIR__C_STA_LW:
- fprintf (file, _("STA_LW (stack longword)"));
- if (rest >= 4)
- fprintf (file, " 0x%08x\n",
- (unsigned) bfd_getl32 (buf));
- break;
- case ETIR__C_STA_QW:
- fprintf (file, _("STA_QW (stack quadword)"));
- if (rest >= 8)
- fprintf (file, " 0x%08x %08x\n",
- (unsigned) bfd_getl32 (buf + 4),
- (unsigned) bfd_getl32 (buf + 0));
- break;
- case ETIR__C_STA_PQ:
- fprintf (file, _("STA_PQ (stack psect base + offset)\n"));
- if (rest >= 12)
- /* xgettext:c-format */
- fprintf (file, _(" psect: %u, offset: 0x%08x %08x\n"),
- (unsigned) bfd_getl32 (buf + 0),
- (unsigned) bfd_getl32 (buf + 8),
- (unsigned) bfd_getl32 (buf + 4));
- break;
- case ETIR__C_STA_LI:
- fprintf (file, _("STA_LI (stack literal)\n"));
- break;
- case ETIR__C_STA_MOD:
- fprintf (file, _("STA_MOD (stack module)\n"));
- break;
- case ETIR__C_STA_CKARG:
- fprintf (file, _("STA_CKARG (compare procedure argument)\n"));
- break;
- case ETIR__C_STO_B:
- fprintf (file, _("STO_B (store byte)\n"));
- break;
- case ETIR__C_STO_W:
- fprintf (file, _("STO_W (store word)\n"));
- break;
- case ETIR__C_STO_LW:
- fprintf (file, _("STO_LW (store longword)\n"));
- break;
- case ETIR__C_STO_QW:
- fprintf (file, _("STO_QW (store quadword)\n"));
- break;
- case ETIR__C_STO_IMMR:
- if (rest >= 4)
- {
- unsigned int rpt = bfd_getl32 (buf);
- fprintf (file,
- _("STO_IMMR (store immediate repeat) %u bytes\n"),
- rpt);
- if (rpt > rest - 4)
- rpt = rest - 4;
- evax_bfd_print_hex (file, " ", buf + 4, rpt);
- }
- break;
- case ETIR__C_STO_GBL:
- if (rest >= 1)
- fprintf (file, _("STO_GBL (store global) %.*s\n"),
- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1);
- break;
- case ETIR__C_STO_CA:
- if (rest >= 1)
- fprintf (file, _("STO_CA (store code address) %.*s\n"),
- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1);
- break;
- case ETIR__C_STO_RB:
- fprintf (file, _("STO_RB (store relative branch)\n"));
- break;
- case ETIR__C_STO_AB:
- fprintf (file, _("STO_AB (store absolute branch)\n"));
- break;
- case ETIR__C_STO_OFF:
- fprintf (file, _("STO_OFF (store offset to psect)\n"));
- break;
- case ETIR__C_STO_IMM:
- if (rest >= 4)
- {
- unsigned int rpt = bfd_getl32 (buf);
- fprintf (file,
- _("STO_IMM (store immediate) %u bytes\n"),
- rpt);
- if (rpt > rest - 4)
- rpt = rest - 4;
- evax_bfd_print_hex (file, " ", buf + 4, rpt);
- }
- break;
- case ETIR__C_STO_GBL_LW:
- if (rest >= 1)
- fprintf (file, _("STO_GBL_LW (store global longword) %.*s\n"),
- buf[0] > rest - 1 ? rest - 1 : buf[0], buf + 1);
- break;
- case ETIR__C_STO_LP_PSB:
- fprintf (file, _("STO_OFF (store LP with procedure signature)\n"));
- break;
- case ETIR__C_STO_HINT_GBL:
- fprintf (file, _("STO_BR_GBL (store branch global) *todo*\n"));
- break;
- case ETIR__C_STO_HINT_PS:
- fprintf (file, _("STO_BR_PS (store branch psect + offset) *todo*\n"));
- break;
- case ETIR__C_OPR_NOP:
- fprintf (file, _("OPR_NOP (no-operation)\n"));
- break;
- case ETIR__C_OPR_ADD:
- fprintf (file, _("OPR_ADD (add)\n"));
- break;
- case ETIR__C_OPR_SUB:
- fprintf (file, _("OPR_SUB (subtract)\n"));
- break;
- case ETIR__C_OPR_MUL:
- fprintf (file, _("OPR_MUL (multiply)\n"));
- break;
- case ETIR__C_OPR_DIV:
- fprintf (file, _("OPR_DIV (divide)\n"));
- break;
- case ETIR__C_OPR_AND:
- fprintf (file, _("OPR_AND (logical and)\n"));
- break;
- case ETIR__C_OPR_IOR:
- fprintf (file, _("OPR_IOR (logical inclusive or)\n"));
- break;
- case ETIR__C_OPR_EOR:
- fprintf (file, _("OPR_EOR (logical exclusive or)\n"));
- break;
- case ETIR__C_OPR_NEG:
- fprintf (file, _("OPR_NEG (negate)\n"));
- break;
- case ETIR__C_OPR_COM:
- fprintf (file, _("OPR_COM (complement)\n"));
- break;
- case ETIR__C_OPR_INSV:
- fprintf (file, _("OPR_INSV (insert field)\n"));
- break;
- case ETIR__C_OPR_ASH:
- fprintf (file, _("OPR_ASH (arithmetic shift)\n"));
- break;
- case ETIR__C_OPR_USH:
- fprintf (file, _("OPR_USH (unsigned shift)\n"));
- break;
- case ETIR__C_OPR_ROT:
- fprintf (file, _("OPR_ROT (rotate)\n"));
- break;
- case ETIR__C_OPR_SEL:
- fprintf (file, _("OPR_SEL (select)\n"));
- break;
- case ETIR__C_OPR_REDEF:
- fprintf (file, _("OPR_REDEF (redefine symbol to curr location)\n"));
- break;
- case ETIR__C_OPR_DFLIT:
- fprintf (file, _("OPR_REDEF (define a literal)\n"));
- break;
- case ETIR__C_STC_LP:
- fprintf (file, _("STC_LP (store cond linkage pair)\n"));
- break;
- case ETIR__C_STC_LP_PSB:
- fprintf (file,
- _("STC_LP_PSB (store cond linkage pair + signature)\n"));
- if (rest >= 5)
- {
- /* xgettext:c-format */
- fprintf (file, _(" linkage index: %u, procedure: %.*s\n"),
- (unsigned) bfd_getl32 (buf),
- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5);
- if (rest > 4 + 1u + buf[4])
- {
- rest -= 4 + 1 + buf[4];
- buf += 4 + 1 + buf[4];
- fprintf (file, _(" signature: %.*s\n"),
- buf[0] > rest - 1 ? rest - 1: buf[0], buf + 1);
- }
- }
- break;
- case ETIR__C_STC_GBL:
- fprintf (file, _("STC_GBL (store cond global)\n"));
- if (rest >= 5)
- /* xgettext:c-format */
- fprintf (file, _(" linkage index: %u, global: %.*s\n"),
- (unsigned) bfd_getl32 (buf),
- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5);
- break;
- case ETIR__C_STC_GCA:
- fprintf (file, _("STC_GCA (store cond code address)\n"));
- if (rest >= 5)
- /* xgettext:c-format */
- fprintf (file, _(" linkage index: %u, procedure name: %.*s\n"),
- (unsigned) bfd_getl32 (buf),
- buf[4] > rest - 5 ? rest - 5 : buf[4], buf + 5);
- break;
- case ETIR__C_STC_PS:
- fprintf (file, _("STC_PS (store cond psect + offset)\n"));
- if (rest >= 16)
- fprintf (file,
- /* xgettext:c-format */
- _(" linkage index: %u, psect: %u, offset: 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (buf),
- (unsigned)bfd_getl32 (buf + 4),
- (unsigned)bfd_getl32 (buf + 12),
- (unsigned)bfd_getl32 (buf + 8));
- break;
- case ETIR__C_STC_NOP_GBL:
- fprintf (file, _("STC_NOP_GBL (store cond NOP at global addr)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 0);
- break;
- case ETIR__C_STC_NOP_PS:
- fprintf (file, _("STC_NOP_PS (store cond NOP at psect + offset)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 1);
- break;
- case ETIR__C_STC_BSR_GBL:
- fprintf (file, _("STC_BSR_GBL (store cond BSR at global addr)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 0);
- break;
- case ETIR__C_STC_BSR_PS:
- fprintf (file, _("STC_BSR_PS (store cond BSR at psect + offset)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 1);
- break;
- case ETIR__C_STC_LDA_GBL:
- fprintf (file, _("STC_LDA_GBL (store cond LDA at global addr)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 0);
- break;
- case ETIR__C_STC_LDA_PS:
- fprintf (file, _("STC_LDA_PS (store cond LDA at psect + offset)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 1);
- break;
- case ETIR__C_STC_BOH_GBL:
- fprintf (file, _("STC_BOH_GBL (store cond BOH at global addr)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 0);
- break;
- case ETIR__C_STC_BOH_PS:
- fprintf (file, _("STC_BOH_PS (store cond BOH at psect + offset)\n"));
- evax_bfd_print_etir_stc_ir (file, buf, rest, 1);
- break;
- case ETIR__C_STC_NBH_GBL:
- fprintf (file,
- _("STC_NBH_GBL (store cond or hint at global addr)\n"));
- break;
- case ETIR__C_STC_NBH_PS:
- fprintf (file,
- _("STC_NBH_PS (store cond or hint at psect + offset)\n"));
- break;
- case ETIR__C_CTL_SETRB:
- fprintf (file, _("CTL_SETRB (set relocation base)\n"));
- break;
- case ETIR__C_CTL_AUGRB:
- if (rest >= 4)
- {
- unsigned int val = bfd_getl32 (buf);
- fprintf (file, _("CTL_AUGRB (augment relocation base) %u\n"),
- val);
- }
- break;
- case ETIR__C_CTL_DFLOC:
- fprintf (file, _("CTL_DFLOC (define location)\n"));
- break;
- case ETIR__C_CTL_STLOC:
- fprintf (file, _("CTL_STLOC (set location)\n"));
- break;
- case ETIR__C_CTL_STKDL:
- fprintf (file, _("CTL_STKDL (stack defined location)\n"));
- break;
- default:
- fprintf (file, _("*unhandled*\n"));
- break;
- }
- off += size;
- }
- }
- static void
- evax_bfd_print_eobj (struct bfd *abfd, FILE *file)
- {
- bool is_first = true;
- bool has_records = false;
- while (1)
- {
- unsigned int rec_len;
- unsigned int pad_len;
- unsigned char *rec;
- unsigned int hdr_size;
- unsigned int type;
- if (is_first)
- {
- unsigned char buf[6];
- is_first = false;
- /* Read 6 bytes. */
- if (bfd_bread (buf, sizeof (buf), abfd) != sizeof (buf))
- {
- fprintf (file, _("cannot read GST record length\n"));
- return;
- }
- rec_len = bfd_getl16 (buf + 0);
- if (rec_len == bfd_getl16 (buf + 4)
- && bfd_getl16 (buf + 2) == EOBJ__C_EMH)
- {
- /* The format is raw: record-size, type, record-size. */
- has_records = true;
- pad_len = (rec_len + 1) & ~1U;
- hdr_size = 4;
- }
- else if (rec_len == EOBJ__C_EMH)
- {
- has_records = false;
- pad_len = bfd_getl16 (buf + 2);
- hdr_size = 6;
- }
- else
- {
- /* Ill-formed. */
- fprintf (file, _("cannot find EMH in first GST record\n"));
- return;
- }
- rec = bfd_malloc (pad_len);
- memcpy (rec, buf + sizeof (buf) - hdr_size, hdr_size);
- }
- else
- {
- unsigned int rec_len2 = 0;
- unsigned char hdr[4];
- if (has_records)
- {
- unsigned char buf_len[2];
- if (bfd_bread (buf_len, sizeof (buf_len), abfd)
- != sizeof (buf_len))
- {
- fprintf (file, _("cannot read GST record length\n"));
- return;
- }
- rec_len2 = (unsigned)bfd_getl16 (buf_len);
- }
- if (bfd_bread (hdr, sizeof (hdr), abfd) != sizeof (hdr))
- {
- fprintf (file, _("cannot read GST record header\n"));
- return;
- }
- rec_len = (unsigned)bfd_getl16 (hdr + 2);
- if (has_records)
- pad_len = (rec_len + 1) & ~1U;
- else
- pad_len = rec_len;
- rec = bfd_malloc (pad_len);
- memcpy (rec, hdr, sizeof (hdr));
- hdr_size = sizeof (hdr);
- if (has_records && rec_len2 != rec_len)
- {
- fprintf (file, _(" corrupted GST\n"));
- break;
- }
- }
- if (bfd_bread (rec + hdr_size, pad_len - hdr_size, abfd)
- != pad_len - hdr_size)
- {
- fprintf (file, _("cannot read GST record\n"));
- return;
- }
- type = (unsigned)bfd_getl16 (rec);
- switch (type)
- {
- case EOBJ__C_EMH:
- evax_bfd_print_emh (file, rec, rec_len);
- break;
- case EOBJ__C_EGSD:
- evax_bfd_print_egsd (file, rec, rec_len);
- break;
- case EOBJ__C_EEOM:
- evax_bfd_print_eeom (file, rec, rec_len);
- free (rec);
- return;
- break;
- case EOBJ__C_ETIR:
- evax_bfd_print_etir (file, "ETIR", rec, rec_len);
- break;
- case EOBJ__C_EDBG:
- evax_bfd_print_etir (file, "EDBG", rec, rec_len);
- break;
- case EOBJ__C_ETBT:
- evax_bfd_print_etir (file, "ETBT", rec, rec_len);
- break;
- default:
- fprintf (file, _(" unhandled EOBJ record type %u\n"), type);
- break;
- }
- free (rec);
- }
- }
- static void
- evax_bfd_print_relocation_records (FILE *file, const unsigned char *buf,
- size_t buf_size, size_t off,
- unsigned int stride)
- {
- while (off <= buf_size - 8)
- {
- unsigned int base;
- unsigned int count;
- unsigned int j;
- count = bfd_getl32 (buf + off + 0);
- if (count == 0)
- break;
- base = bfd_getl32 (buf + off + 4);
- /* xgettext:c-format */
- fprintf (file, _(" bitcount: %u, base addr: 0x%08x\n"),
- count, base);
- off += 8;
- for (j = 0; count > 0 && off <= buf_size - 4; j += 4, count -= 32)
- {
- unsigned int k;
- unsigned int n = 0;
- unsigned int val;
- val = bfd_getl32 (buf + off);
- off += 4;
- /* xgettext:c-format */
- fprintf (file, _(" bitmap: 0x%08x (count: %u):\n"), val, count);
- for (k = 0; k < 32; k++)
- if (val & (1u << k))
- {
- if (n == 0)
- fputs (" ", file);
- fprintf (file, _(" %08x"), base + (j * 8 + k) * stride);
- n++;
- if (n == 8)
- {
- fputs ("\n", file);
- n = 0;
- }
- }
- if (n)
- fputs ("\n", file);
- }
- }
- }
- static void
- evax_bfd_print_address_fixups (FILE *file, const unsigned char *buf,
- size_t buf_size, size_t off)
- {
- while (off <= buf_size - 8)
- {
- unsigned int j;
- unsigned int count;
- count = bfd_getl32 (buf + off + 0);
- if (count == 0)
- return;
- /* xgettext:c-format */
- fprintf (file, _(" image %u (%u entries)\n"),
- (unsigned) bfd_getl32 (buf + off + 4), count);
- off += 8;
- for (j = 0; j < count && off <= buf_size - 8; j++)
- {
- /* xgettext:c-format */
- fprintf (file, _(" offset: 0x%08x, val: 0x%08x\n"),
- (unsigned) bfd_getl32 (buf + off + 0),
- (unsigned) bfd_getl32 (buf + off + 4));
- off += 8;
- }
- }
- }
- static void
- evax_bfd_print_reference_fixups (FILE *file, const unsigned char *buf,
- size_t buf_size, size_t off)
- {
- unsigned int count;
- while (off <= buf_size - 8)
- {
- unsigned int j;
- unsigned int n = 0;
- count = bfd_getl32 (buf + off + 0);
- if (count == 0)
- break;
- /* xgettext:c-format */
- fprintf (file, _(" image %u (%u entries), offsets:\n"),
- (unsigned) bfd_getl32 (buf + off + 4), count);
- off += 8;
- for (j = 0; j < count && off <= buf_size - 4; j++)
- {
- if (n == 0)
- fputs (" ", file);
- fprintf (file, _(" 0x%08x"), (unsigned) bfd_getl32 (buf + off));
- n++;
- if (n == 7)
- {
- fputs ("\n", file);
- n = 0;
- }
- off += 4;
- }
- if (n)
- fputs ("\n", file);
- }
- }
- static void
- evax_bfd_print_indent (int indent, FILE *file)
- {
- for (; indent; indent--)
- fputc (' ', file);
- }
- static const char *
- evax_bfd_get_dsc_name (unsigned int v)
- {
- switch (v)
- {
- case DSC__K_DTYPE_Z:
- return "Z (Unspecified)";
- case DSC__K_DTYPE_V:
- return "V (Bit)";
- case DSC__K_DTYPE_BU:
- return "BU (Byte logical)";
- case DSC__K_DTYPE_WU:
- return "WU (Word logical)";
- case DSC__K_DTYPE_LU:
- return "LU (Longword logical)";
- case DSC__K_DTYPE_QU:
- return "QU (Quadword logical)";
- case DSC__K_DTYPE_B:
- return "B (Byte integer)";
- case DSC__K_DTYPE_W:
- return "W (Word integer)";
- case DSC__K_DTYPE_L:
- return "L (Longword integer)";
- case DSC__K_DTYPE_Q:
- return "Q (Quadword integer)";
- case DSC__K_DTYPE_F:
- return "F (Single-precision floating)";
- case DSC__K_DTYPE_D:
- return "D (Double-precision floating)";
- case DSC__K_DTYPE_FC:
- return "FC (Complex)";
- case DSC__K_DTYPE_DC:
- return "DC (Double-precision Complex)";
- case DSC__K_DTYPE_T:
- return "T (ASCII text string)";
- case DSC__K_DTYPE_NU:
- return "NU (Numeric string, unsigned)";
- case DSC__K_DTYPE_NL:
- return "NL (Numeric string, left separate sign)";
- case DSC__K_DTYPE_NLO:
- return "NLO (Numeric string, left overpunched sign)";
- case DSC__K_DTYPE_NR:
- return "NR (Numeric string, right separate sign)";
- case DSC__K_DTYPE_NRO:
- return "NRO (Numeric string, right overpunched sig)";
- case DSC__K_DTYPE_NZ:
- return "NZ (Numeric string, zoned sign)";
- case DSC__K_DTYPE_P:
- return "P (Packed decimal string)";
- case DSC__K_DTYPE_ZI:
- return "ZI (Sequence of instructions)";
- case DSC__K_DTYPE_ZEM:
- return "ZEM (Procedure entry mask)";
- case DSC__K_DTYPE_DSC:
- return "DSC (Descriptor, used for arrays of dyn strings)";
- case DSC__K_DTYPE_OU:
- return "OU (Octaword logical)";
- case DSC__K_DTYPE_O:
- return "O (Octaword integer)";
- case DSC__K_DTYPE_G:
- return "G (Double precision G floating, 64 bit)";
- case DSC__K_DTYPE_H:
- return "H (Quadruple precision floating, 128 bit)";
- case DSC__K_DTYPE_GC:
- return "GC (Double precision complex, G floating)";
- case DSC__K_DTYPE_HC:
- return "HC (Quadruple precision complex, H floating)";
- case DSC__K_DTYPE_CIT:
- return "CIT (COBOL intermediate temporary)";
- case DSC__K_DTYPE_BPV:
- return "BPV (Bound Procedure Value)";
- case DSC__K_DTYPE_BLV:
- return "BLV (Bound Label Value)";
- case DSC__K_DTYPE_VU:
- return "VU (Bit Unaligned)";
- case DSC__K_DTYPE_ADT:
- return "ADT (Absolute Date-Time)";
- case DSC__K_DTYPE_VT:
- return "VT (Varying Text)";
- case DSC__K_DTYPE_T2:
- return "T2 (16-bit char)";
- case DSC__K_DTYPE_VT2:
- return "VT2 (16-bit varying char)";
- default:
- return "?? (unknown)";
- }
- }
- static void
- evax_bfd_print_desc (const unsigned char *buf, unsigned int bufsize,
- int indent, FILE *file)
- {
- if (bufsize < 8)
- return;
- unsigned char bclass = buf[3];
- unsigned char dtype = buf[2];
- unsigned int len = (unsigned)bfd_getl16 (buf);
- unsigned int pointer = (unsigned)bfd_getl32 (buf + 4);
- evax_bfd_print_indent (indent, file);
- if (len == 1 && pointer == 0xffffffffUL)
- {
- /* 64 bits. */
- fprintf (file, _("64 bits *unhandled*\n"));
- }
- else
- {
- /* xgettext:c-format */
- fprintf (file, _("class: %u, dtype: %u, length: %u, pointer: 0x%08x\n"),
- bclass, dtype, len, pointer);
- switch (bclass)
- {
- case DSC__K_CLASS_NCA:
- {
- const struct vms_dsc_nca *dsc = (const void *)buf;
- unsigned int i;
- const unsigned char *b;
- evax_bfd_print_indent (indent, file);
- fprintf (file, _("non-contiguous array of %s\n"),
- evax_bfd_get_dsc_name (dsc->dtype));
- if (bufsize >= sizeof (*dsc))
- {
- evax_bfd_print_indent (indent + 1, file);
- fprintf (file,
- /* xgettext:c-format */
- _("dimct: %u, aflags: 0x%02x, digits: %u, scale: %u\n"),
- dsc->dimct, dsc->aflags, dsc->digits, dsc->scale);
- evax_bfd_print_indent (indent + 1, file);
- fprintf (file,
- /* xgettext:c-format */
- _("arsize: %u, a0: 0x%08x\n"),
- (unsigned) bfd_getl32 (dsc->arsize),
- (unsigned) bfd_getl32 (dsc->a0));
- evax_bfd_print_indent (indent + 1, file);
- fprintf (file, _("Strides:\n"));
- b = buf + sizeof (*dsc);
- bufsize -= sizeof (*dsc);
- for (i = 0; i < dsc->dimct; i++)
- {
- if (bufsize < 4)
- break;
- evax_bfd_print_indent (indent + 2, file);
- fprintf (file, "[%u]: %u\n", i + 1,
- (unsigned) bfd_getl32 (b));
- b += 4;
- bufsize -= 4;
- }
- evax_bfd_print_indent (indent + 1, file);
- fprintf (file, _("Bounds:\n"));
- for (i = 0; i < dsc->dimct; i++)
- {
- if (bufsize < 8)
- break;
- evax_bfd_print_indent (indent + 2, file);
- /* xgettext:c-format */
- fprintf (file, _("[%u]: Lower: %u, upper: %u\n"), i + 1,
- (unsigned) bfd_getl32 (b + 0),
- (unsigned) bfd_getl32 (b + 4));
- b += 8;
- bufsize -= 8;
- }
- }
- }
- break;
- case DSC__K_CLASS_UBS:
- {
- const struct vms_dsc_ubs *ubs = (const void *)buf;
- evax_bfd_print_indent (indent, file);
- fprintf (file, _("unaligned bit-string of %s\n"),
- evax_bfd_get_dsc_name (ubs->dtype));
- if (bufsize >= sizeof (*ubs))
- {
- evax_bfd_print_indent (indent + 1, file);
- fprintf (file,
- /* xgettext:c-format */
- _("base: %u, pos: %u\n"),
- (unsigned) bfd_getl32 (ubs->base),
- (unsigned) bfd_getl32 (ubs->pos));
- }
- }
- break;
- default:
- fprintf (file, _("*unhandled*\n"));
- break;
- }
- }
- }
- static unsigned int
- evax_bfd_print_valspec (const unsigned char *buf, unsigned int bufsize,
- int indent, FILE *file)
- {
- if (bufsize < 5)
- return bufsize;
- unsigned int vflags = buf[0];
- unsigned int value = (unsigned) bfd_getl32 (buf + 1);
- unsigned int len = 5;
- evax_bfd_print_indent (indent, file);
- /* xgettext:c-format */
- fprintf (file, _("vflags: 0x%02x, value: 0x%08x "), vflags, value);
- buf += 5;
- bufsize -= 5;
- switch (vflags)
- {
- case DST__K_VFLAGS_NOVAL:
- fprintf (file, _("(no value)\n"));
- break;
- case DST__K_VFLAGS_NOTACTIVE:
- fprintf (file, _("(not active)\n"));
- break;
- case DST__K_VFLAGS_UNALLOC:
- fprintf (file, _("(not allocated)\n"));
- break;
- case DST__K_VFLAGS_DSC:
- fprintf (file, _("(descriptor)\n"));
- if (value <= bufsize)
- evax_bfd_print_desc (buf + value, bufsize - value, indent + 1, file);
- break;
- case DST__K_VFLAGS_TVS:
- fprintf (file, _("(trailing value)\n"));
- break;
- case DST__K_VS_FOLLOWS:
- fprintf (file, _("(value spec follows)\n"));
- break;
- case DST__K_VFLAGS_BITOFFS:
- fprintf (file, _("(at bit offset %u)\n"), value);
- break;
- default:
- /* xgettext:c-format */
- fprintf (file, _("(reg: %u, disp: %u, indir: %u, kind: "),
- (vflags & DST__K_REGNUM_MASK) >> DST__K_REGNUM_SHIFT,
- vflags & DST__K_DISP ? 1 : 0,
- vflags & DST__K_INDIR ? 1 : 0);
- switch (vflags & DST__K_VALKIND_MASK)
- {
- case DST__K_VALKIND_LITERAL:
- fputs (_("literal"), file);
- break;
- case DST__K_VALKIND_ADDR:
- fputs (_("address"), file);
- break;
- case DST__K_VALKIND_DESC:
- fputs (_("desc"), file);
- break;
- case DST__K_VALKIND_REG:
- fputs (_("reg"), file);
- break;
- }
- fputs (")\n", file);
- break;
- }
- return len;
- }
- static void
- evax_bfd_print_typspec (const unsigned char *buf, unsigned int bufsize,
- int indent, FILE *file)
- {
- if (bufsize < 3)
- return;
- unsigned char kind = buf[2];
- unsigned int len = (unsigned) bfd_getl16 (buf);
- evax_bfd_print_indent (indent, file);
- /* xgettext:c-format */
- fprintf (file, _("len: %2u, kind: %2u "), len, kind);
- buf += 3;
- bufsize -= 3;
- switch (kind)
- {
- case DST__K_TS_ATOM:
- /* xgettext:c-format */
- if (bufsize >= 1)
- fprintf (file, _("atomic, type=0x%02x %s\n"),
- buf[0], evax_bfd_get_dsc_name (buf[0]));
- break;
- case DST__K_TS_IND:
- if (bufsize >= 4)
- fprintf (file, _("indirect, defined at 0x%08x\n"),
- (unsigned) bfd_getl32 (buf));
- break;
- case DST__K_TS_TPTR:
- fprintf (file, _("typed pointer\n"));
- evax_bfd_print_typspec (buf, bufsize, indent + 1, file);
- break;
- case DST__K_TS_PTR:
- fprintf (file, _("pointer\n"));
- break;
- case DST__K_TS_ARRAY:
- {
- const unsigned char *vs;
- unsigned int vs_len;
- unsigned int vec_len;
- unsigned int i;
- if (bufsize == 0)
- return;
- fprintf (file, _("array, dim: %u, bitmap: "), buf[0]);
- --bufsize;
- vec_len = (buf[0] + 1 + 7) / 8;
- for (i = 0; i < vec_len; i++)
- {
- if (bufsize == 0)
- break;
- fprintf (file, " %02x", buf[i + 1]);
- --bufsize;
- }
- fputc ('\n', file);
- if (bufsize == 0)
- return;
- vs = buf + 1 + vec_len;
- evax_bfd_print_indent (indent, file);
- fprintf (file, _("array descriptor:\n"));
- vs_len = evax_bfd_print_valspec (vs, bufsize, indent + 1, file);
- vs += vs_len;
- if (bufsize > vs_len)
- {
- bufsize -= vs_len;
- for (i = 0; i < buf[0] + 1U; i++)
- if (buf[1 + i / 8] & (1 << (i % 8)))
- {
- evax_bfd_print_indent (indent, file);
- if (i == 0)
- fprintf (file, _("type spec for element:\n"));
- else
- fprintf (file, _("type spec for subscript %u:\n"), i);
- evax_bfd_print_typspec (vs, bufsize, indent + 1, file);
- if (bufsize < 2)
- break;
- vs_len = bfd_getl16 (vs);
- if (bufsize <= vs_len)
- break;
- vs += vs_len;
- bufsize -= vs_len;
- }
- }
- }
- break;
- default:
- fprintf (file, _("*unhandled*\n"));
- }
- }
- static void
- evax_bfd_print_dst (struct bfd *abfd, unsigned int dst_size, FILE *file)
- {
- unsigned int off = 0;
- unsigned int pc = 0;
- unsigned int line = 0;
- fprintf (file, _("Debug symbol table:\n"));
- while (dst_size > 0)
- {
- struct vms_dst_header dsth;
- unsigned int len;
- unsigned int type;
- unsigned char *buf;
- if (bfd_bread (&dsth, sizeof (dsth), abfd) != sizeof (dsth))
- {
- fprintf (file, _("cannot read DST header\n"));
- return;
- }
- len = bfd_getl16 (dsth.length);
- type = bfd_getl16 (dsth.type);
- /* xgettext:c-format */
- fprintf (file, _(" type: %3u, len: %3u (at 0x%08x): "),
- type, len, off);
- if (len < sizeof (dsth))
- {
- fputc ('\n', file);
- break;
- }
- dst_size -= len;
- off += len;
- len -= sizeof (dsth);
- if (len == 0)
- buf = NULL;
- else
- {
- buf = _bfd_malloc_and_read (abfd, len, len);
- if (buf == NULL)
- {
- fprintf (file, _("cannot read DST symbol\n"));
- return;
- }
- }
- switch (type)
- {
- case DSC__K_DTYPE_V:
- case DSC__K_DTYPE_BU:
- case DSC__K_DTYPE_WU:
- case DSC__K_DTYPE_LU:
- case DSC__K_DTYPE_QU:
- case DSC__K_DTYPE_B:
- case DSC__K_DTYPE_W:
- case DSC__K_DTYPE_L:
- case DSC__K_DTYPE_Q:
- case DSC__K_DTYPE_F:
- case DSC__K_DTYPE_D:
- case DSC__K_DTYPE_FC:
- case DSC__K_DTYPE_DC:
- case DSC__K_DTYPE_T:
- case DSC__K_DTYPE_NU:
- case DSC__K_DTYPE_NL:
- case DSC__K_DTYPE_NLO:
- case DSC__K_DTYPE_NR:
- case DSC__K_DTYPE_NRO:
- case DSC__K_DTYPE_NZ:
- case DSC__K_DTYPE_P:
- case DSC__K_DTYPE_ZI:
- case DSC__K_DTYPE_ZEM:
- case DSC__K_DTYPE_DSC:
- case DSC__K_DTYPE_OU:
- case DSC__K_DTYPE_O:
- case DSC__K_DTYPE_G:
- case DSC__K_DTYPE_H:
- case DSC__K_DTYPE_GC:
- case DSC__K_DTYPE_HC:
- case DSC__K_DTYPE_CIT:
- case DSC__K_DTYPE_BPV:
- case DSC__K_DTYPE_BLV:
- case DSC__K_DTYPE_VU:
- case DSC__K_DTYPE_ADT:
- case DSC__K_DTYPE_VT:
- case DSC__K_DTYPE_T2:
- case DSC__K_DTYPE_VT2:
- fprintf (file, _("standard data: %s\n"),
- evax_bfd_get_dsc_name (type));
- evax_bfd_print_valspec (buf, len, 4, file);
- if (len > 6)
- fprintf (file, _(" name: %.*s\n"),
- buf[5] > len - 6 ? len - 6 : buf[5], buf + 6);
- break;
- case DST__K_MODBEG:
- {
- struct vms_dst_modbeg *dst = (void *)buf;
- unsigned char *name = buf + sizeof (*dst);
- fprintf (file, _("modbeg\n"));
- if (len < sizeof (*dst))
- break;
- /* xgettext:c-format */
- fprintf (file, _(" flags: %d, language: %u, "
- "major: %u, minor: %u\n"),
- dst->flags,
- (unsigned)bfd_getl32 (dst->language),
- (unsigned)bfd_getl16 (dst->major),
- (unsigned)bfd_getl16 (dst->minor));
- len -= sizeof (*dst);
- if (len > 0)
- {
- int nlen = len - 1;
- fprintf (file, _(" module name: %.*s\n"),
- name[0] > nlen ? nlen : name[0], name + 1);
- if (name[0] < nlen)
- {
- len -= name[0] + 1;
- name += name[0] + 1;
- nlen = len - 1;
- fprintf (file, _(" compiler : %.*s\n"),
- name[0] > nlen ? nlen : name[0], name + 1);
- }
- }
- }
- break;
- case DST__K_MODEND:
- fprintf (file, _("modend\n"));
- break;
- case DST__K_RTNBEG:
- {
- struct vms_dst_rtnbeg *dst = (void *)buf;
- unsigned char *name = buf + sizeof (*dst);
- fputs (_("rtnbeg\n"), file);
- if (len >= sizeof (*dst))
- {
- /* xgettext:c-format */
- fprintf (file, _(" flags: %u, address: 0x%08x, "
- "pd-address: 0x%08x\n"),
- dst->flags,
- (unsigned) bfd_getl32 (dst->address),
- (unsigned) bfd_getl32 (dst->pd_address));
- len -= sizeof (*dst);
- if (len > 0)
- {
- int nlen = len - 1;
- fprintf (file, _(" routine name: %.*s\n"),
- name[0] > nlen ? nlen : name[0], name + 1);
- }
- }
- }
- break;
- case DST__K_RTNEND:
- {
- struct vms_dst_rtnend *dst = (void *)buf;
- if (len >= sizeof (*dst))
- fprintf (file, _("rtnend: size 0x%08x\n"),
- (unsigned) bfd_getl32 (dst->size));
- }
- break;
- case DST__K_PROLOG:
- {
- struct vms_dst_prolog *dst = (void *)buf;
- if (len >= sizeof (*dst))
- /* xgettext:c-format */
- fprintf (file, _("prolog: bkpt address 0x%08x\n"),
- (unsigned) bfd_getl32 (dst->bkpt_addr));
- }
- break;
- case DST__K_EPILOG:
- {
- struct vms_dst_epilog *dst = (void *)buf;
- if (len >= sizeof (*dst))
- /* xgettext:c-format */
- fprintf (file, _("epilog: flags: %u, count: %u\n"),
- dst->flags, (unsigned) bfd_getl32 (dst->count));
- }
- break;
- case DST__K_BLKBEG:
- {
- struct vms_dst_blkbeg *dst = (void *)buf;
- unsigned char *name = buf + sizeof (*dst);
- if (len > sizeof (*dst))
- {
- int nlen;
- len -= sizeof (*dst);
- nlen = len - 1;
- /* xgettext:c-format */
- fprintf (file, _("blkbeg: address: 0x%08x, name: %.*s\n"),
- (unsigned) bfd_getl32 (dst->address),
- name[0] > nlen ? nlen : name[0], name + 1);
- }
- }
- break;
- case DST__K_BLKEND:
- {
- struct vms_dst_blkend *dst = (void *)buf;
- if (len >= sizeof (*dst))
- /* xgettext:c-format */
- fprintf (file, _("blkend: size: 0x%08x\n"),
- (unsigned) bfd_getl32 (dst->size));
- }
- break;
- case DST__K_TYPSPEC:
- {
- fprintf (file, _("typspec (len: %u)\n"), len);
- if (len >= 1)
- {
- int nlen = len - 1;
- fprintf (file, _(" name: %.*s\n"),
- buf[0] > nlen ? nlen : buf[0], buf + 1);
- if (nlen > buf[0])
- evax_bfd_print_typspec (buf + 1 + buf[0], len - (1 + buf[0]),
- 5, file);
- }
- }
- break;
- case DST__K_SEPTYP:
- {
- if (len >= 6)
- {
- fprintf (file, _("septyp, name: %.*s\n"),
- buf[5] > len - 6 ? len - 6 : buf[5], buf + 6);
- evax_bfd_print_valspec (buf, len, 4, file);
- }
- }
- break;
- case DST__K_RECBEG:
- {
- struct vms_dst_recbeg *recbeg = (void *)buf;
- unsigned char *name = buf + sizeof (*recbeg);
- if (len > sizeof (*recbeg))
- {
- int nlen = len - sizeof (*recbeg) - 1;
- if (name[0] < nlen)
- nlen = name[0];
- fprintf (file, _("recbeg: name: %.*s\n"), nlen, name + 1);
- evax_bfd_print_valspec (buf, len, 4, file);
- len -= 1 + nlen;
- if (len >= 4)
- fprintf (file, _(" len: %u bits\n"),
- (unsigned) bfd_getl32 (name + 1 + nlen));
- }
- }
- break;
- case DST__K_RECEND:
- fprintf (file, _("recend\n"));
- break;
- case DST__K_ENUMBEG:
- if (len >= 2)
- /* xgettext:c-format */
- fprintf (file, _("enumbeg, len: %u, name: %.*s\n"),
- buf[0], buf[1] > len - 2 ? len - 2 : buf[1], buf + 2);
- break;
- case DST__K_ENUMELT:
- if (len >= 6)
- {
- fprintf (file, _("enumelt, name: %.*s\n"),
- buf[5] > len - 6 ? len - 6 : buf[5], buf + 6);
- evax_bfd_print_valspec (buf, len, 4, file);
- }
- break;
- case DST__K_ENUMEND:
- fprintf (file, _("enumend\n"));
- break;
- case DST__K_LABEL:
- {
- struct vms_dst_label *lab = (void *)buf;
- if (len >= sizeof (*lab))
- {
- fprintf (file, _("label, name: %.*s\n"),
- lab->name[0] > len - 1 ? len - 1 : lab->name[0],
- lab->name + 1);
- fprintf (file, _(" address: 0x%08x\n"),
- (unsigned) bfd_getl32 (lab->value));
- }
- }
- break;
- case DST__K_DIS_RANGE:
- if (len >= 4)
- {
- unsigned int cnt = bfd_getl32 (buf);
- unsigned char *rng = buf + 4;
- unsigned int i;
- fprintf (file, _("discontiguous range (nbr: %u)\n"), cnt);
- len -= 4;
- for (i = 0; i < cnt; i++, rng += 8)
- {
- if (len < 8)
- break;
- /* xgettext:c-format */
- fprintf (file, _(" address: 0x%08x, size: %u\n"),
- (unsigned) bfd_getl32 (rng),
- (unsigned) bfd_getl32 (rng + 4));
- len -= 8;
- }
- }
- break;
- case DST__K_LINE_NUM:
- {
- unsigned char *buf_orig = buf;
- fprintf (file, _("line num (len: %u)\n"), len);
- while (len > 0)
- {
- int cmd;
- unsigned int val;
- int cmdlen = -1;
- cmd = *buf++;
- len--;
- fputs (" ", file);
- switch (cmd)
- {
- case DST__K_DELTA_PC_W:
- if (len < 2)
- break;
- val = bfd_getl16 (buf);
- fprintf (file, _("delta_pc_w %u\n"), val);
- pc += val;
- line++;
- cmdlen = 2;
- break;
- case DST__K_INCR_LINUM:
- if (len < 1)
- break;
- val = *buf;
- fprintf (file, _("incr_linum(b): +%u\n"), val);
- line += val;
- cmdlen = 1;
- break;
- case DST__K_INCR_LINUM_W:
- if (len < 2)
- break;
- val = bfd_getl16 (buf);
- fprintf (file, _("incr_linum_w: +%u\n"), val);
- line += val;
- cmdlen = 2;
- break;
- case DST__K_INCR_LINUM_L:
- if (len < 4)
- break;
- val = bfd_getl32 (buf);
- fprintf (file, _("incr_linum_l: +%u\n"), val);
- line += val;
- cmdlen = 4;
- break;
- case DST__K_SET_LINUM:
- if (len < 2)
- break;
- line = bfd_getl16 (buf);
- fprintf (file, _("set_line_num(w) %u\n"), line);
- cmdlen = 2;
- break;
- case DST__K_SET_LINUM_B:
- if (len < 1)
- break;
- line = *buf;
- fprintf (file, _("set_line_num_b %u\n"), line);
- cmdlen = 1;
- break;
- case DST__K_SET_LINUM_L:
- if (len < 4)
- break;
- line = bfd_getl32 (buf);
- fprintf (file, _("set_line_num_l %u\n"), line);
- cmdlen = 4;
- break;
- case DST__K_SET_ABS_PC:
- if (len < 4)
- break;
- pc = bfd_getl32 (buf);
- fprintf (file, _("set_abs_pc: 0x%08x\n"), pc);
- cmdlen = 4;
- break;
- case DST__K_DELTA_PC_L:
- if (len < 4)
- break;
- fprintf (file, _("delta_pc_l: +0x%08x\n"),
- (unsigned) bfd_getl32 (buf));
- cmdlen = 4;
- break;
- case DST__K_TERM:
- if (len < 1)
- break;
- fprintf (file, _("term(b): 0x%02x"), *buf);
- pc += *buf;
- fprintf (file, _(" pc: 0x%08x\n"), pc);
- cmdlen = 1;
- break;
- case DST__K_TERM_W:
- if (len < 2)
- break;
- val = bfd_getl16 (buf);
- fprintf (file, _("term_w: 0x%04x"), val);
- pc += val;
- fprintf (file, _(" pc: 0x%08x\n"), pc);
- cmdlen = 2;
- break;
- default:
- if (cmd <= 0)
- {
- fprintf (file, _("delta pc +%-4d"), -cmd);
- line++; /* FIXME: curr increment. */
- pc += -cmd;
- /* xgettext:c-format */
- fprintf (file, _(" pc: 0x%08x line: %5u\n"),
- pc, line);
- cmdlen = 0;
- }
- else
- fprintf (file, _(" *unhandled* cmd %u\n"), cmd);
- break;
- }
- if (cmdlen < 0)
- break;
- len -= cmdlen;
- buf += cmdlen;
- }
- buf = buf_orig;
- }
- break;
- case DST__K_SOURCE:
- {
- unsigned char *buf_orig = buf;
- fprintf (file, _("source (len: %u)\n"), len);
- while (len > 0)
- {
- int cmd = *buf++;
- int cmdlen = -1;
- len--;
- switch (cmd)
- {
- case DST__K_SRC_DECLFILE:
- {
- struct vms_dst_src_decl_src *src = (void *) buf;
- unsigned char *name;
- int nlen;
- if (len < sizeof (*src))
- break;
- /* xgettext:c-format */
- fprintf (file, _(" declfile: len: %u, flags: %u, "
- "fileid: %u\n"),
- src->length, src->flags,
- (unsigned)bfd_getl16 (src->fileid));
- /* xgettext:c-format */
- fprintf (file, _(" rms: cdt: 0x%08x %08x, "
- "ebk: 0x%08x, ffb: 0x%04x, "
- "rfo: %u\n"),
- (unsigned)bfd_getl32 (src->rms_cdt + 4),
- (unsigned)bfd_getl32 (src->rms_cdt + 0),
- (unsigned)bfd_getl32 (src->rms_ebk),
- (unsigned)bfd_getl16 (src->rms_ffb),
- src->rms_rfo);
- if (src->length > len || src->length <= sizeof (*src))
- break;
- nlen = src->length - sizeof (*src) - 1;
- name = buf + sizeof (*src);
- fprintf (file, _(" filename : %.*s\n"),
- name[0] > nlen ? nlen : name[0], name + 1);
- if (name[0] >= nlen)
- break;
- nlen -= name[0] + 1;
- name += name[0] + 1;
- fprintf (file, _(" module name: %.*s\n"),
- name[0] > nlen ? nlen : name[0], name + 1);
- if (name[0] > nlen)
- break;
- cmdlen = src->length;
- }
- break;
- case DST__K_SRC_SETFILE:
- if (len < 2)
- break;
- fprintf (file, _(" setfile %u\n"),
- (unsigned) bfd_getl16 (buf));
- cmdlen = 2;
- break;
- case DST__K_SRC_SETREC_W:
- if (len < 2)
- break;
- fprintf (file, _(" setrec %u\n"),
- (unsigned) bfd_getl16 (buf));
- cmdlen = 2;
- break;
- case DST__K_SRC_SETREC_L:
- if (len < 4)
- break;
- fprintf (file, _(" setrec %u\n"),
- (unsigned) bfd_getl32 (buf));
- cmdlen = 4;
- break;
- case DST__K_SRC_SETLNUM_W:
- if (len < 2)
- break;
- fprintf (file, _(" setlnum %u\n"),
- (unsigned) bfd_getl16 (buf));
- cmdlen = 2;
- break;
- case DST__K_SRC_SETLNUM_L:
- if (len < 4)
- break;
- fprintf (file, _(" setlnum %u\n"),
- (unsigned) bfd_getl32 (buf));
- cmdlen = 4;
- break;
- case DST__K_SRC_DEFLINES_W:
- if (len < 2)
- break;
- fprintf (file, _(" deflines %u\n"),
- (unsigned) bfd_getl16 (buf));
- cmdlen = 2;
- break;
- case DST__K_SRC_DEFLINES_B:
- if (len < 1)
- break;
- fprintf (file, _(" deflines %u\n"), *buf);
- cmdlen = 1;
- break;
- case DST__K_SRC_FORMFEED:
- fprintf (file, _(" formfeed\n"));
- cmdlen = 0;
- break;
- default:
- fprintf (file, _(" *unhandled* cmd %u\n"), cmd);
- break;
- }
- if (cmdlen < 0)
- break;
- len -= cmdlen;
- buf += cmdlen;
- }
- buf = buf_orig;
- }
- break;
- default:
- fprintf (file, _("*unhandled* dst type %u\n"), type);
- break;
- }
- free (buf);
- }
- }
- static void
- evax_bfd_print_image (bfd *abfd, FILE *file)
- {
- struct vms_eihd eihd;
- const char *name;
- unsigned int val;
- unsigned int eiha_off;
- unsigned int eihi_off;
- unsigned int eihs_off;
- unsigned int eisd_off;
- unsigned int eihef_off = 0;
- unsigned int eihnp_off = 0;
- unsigned int dmt_vbn = 0;
- unsigned int dmt_size = 0;
- unsigned int dst_vbn = 0;
- unsigned int dst_size = 0;
- unsigned int gst_vbn = 0;
- unsigned int gst_size = 0;
- unsigned int eiaf_vbn = 0;
- unsigned int eiaf_size = 0;
- unsigned int eihvn_off;
- if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET)
- || bfd_bread (&eihd, sizeof (eihd), abfd) != sizeof (eihd))
- {
- fprintf (file, _("cannot read EIHD\n"));
- return;
- }
- /* xgettext:c-format */
- fprintf (file, _("EIHD: (size: %u, nbr blocks: %u)\n"),
- (unsigned)bfd_getl32 (eihd.size),
- (unsigned)bfd_getl32 (eihd.hdrblkcnt));
- /* xgettext:c-format */
- fprintf (file, _(" majorid: %u, minorid: %u\n"),
- (unsigned)bfd_getl32 (eihd.majorid),
- (unsigned)bfd_getl32 (eihd.minorid));
- val = (unsigned)bfd_getl32 (eihd.imgtype);
- switch (val)
- {
- case EIHD__K_EXE:
- name = _("executable");
- break;
- case EIHD__K_LIM:
- name = _("linkable image");
- break;
- default:
- name = _("unknown");
- break;
- }
- /* xgettext:c-format */
- fprintf (file, _(" image type: %u (%s)"), val, name);
- val = (unsigned)bfd_getl32 (eihd.subtype);
- switch (val)
- {
- case EIHD__C_NATIVE:
- name = _("native");
- break;
- case EIHD__C_CLI:
- name = _("CLI");
- break;
- default:
- name = _("unknown");
- break;
- }
- /* xgettext:c-format */
- fprintf (file, _(", subtype: %u (%s)\n"), val, name);
- eisd_off = bfd_getl32 (eihd.isdoff);
- eiha_off = bfd_getl32 (eihd.activoff);
- eihi_off = bfd_getl32 (eihd.imgidoff);
- eihs_off = bfd_getl32 (eihd.symdbgoff);
- /* xgettext:c-format */
- fprintf (file, _(" offsets: isd: %u, activ: %u, symdbg: %u, "
- "imgid: %u, patch: %u\n"),
- eisd_off, eiha_off, eihs_off, eihi_off,
- (unsigned)bfd_getl32 (eihd.patchoff));
- fprintf (file, _(" fixup info rva: "));
- bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.iafva));
- fprintf (file, _(", symbol vector rva: "));
- bfd_fprintf_vma (abfd, file, bfd_getl64 (eihd.symvva));
- eihvn_off = bfd_getl32 (eihd.version_array_off);
- fprintf (file, _("\n"
- " version array off: %u\n"),
- eihvn_off);
- fprintf (file,
- /* xgettext:c-format */
- _(" img I/O count: %u, nbr channels: %u, req pri: %08x%08x\n"),
- (unsigned)bfd_getl32 (eihd.imgiocnt),
- (unsigned)bfd_getl32 (eihd.iochancnt),
- (unsigned)bfd_getl32 (eihd.privreqs + 4),
- (unsigned)bfd_getl32 (eihd.privreqs + 0));
- val = (unsigned)bfd_getl32 (eihd.lnkflags);
- fprintf (file, _(" linker flags: %08x:"), val);
- if (val & EIHD__M_LNKDEBUG)
- fprintf (file, " LNKDEBUG");
- if (val & EIHD__M_LNKNOTFR)
- fprintf (file, " LNKNOTFR");
- if (val & EIHD__M_NOP0BUFS)
- fprintf (file, " NOP0BUFS");
- if (val & EIHD__M_PICIMG)
- fprintf (file, " PICIMG");
- if (val & EIHD__M_P0IMAGE)
- fprintf (file, " P0IMAGE");
- if (val & EIHD__M_DBGDMT)
- fprintf (file, " DBGDMT");
- if (val & EIHD__M_INISHR)
- fprintf (file, " INISHR");
- if (val & EIHD__M_XLATED)
- fprintf (file, " XLATED");
- if (val & EIHD__M_BIND_CODE_SEC)
- fprintf (file, " BIND_CODE_SEC");
- if (val & EIHD__M_BIND_DATA_SEC)
- fprintf (file, " BIND_DATA_SEC");
- if (val & EIHD__M_MKTHREADS)
- fprintf (file, " MKTHREADS");
- if (val & EIHD__M_UPCALLS)
- fprintf (file, " UPCALLS");
- if (val & EIHD__M_OMV_READY)
- fprintf (file, " OMV_READY");
- if (val & EIHD__M_EXT_BIND_SECT)
- fprintf (file, " EXT_BIND_SECT");
- fprintf (file, "\n");
- /* xgettext:c-format */
- fprintf (file, _(" ident: 0x%08x, sysver: 0x%08x, "
- "match ctrl: %u, symvect_size: %u\n"),
- (unsigned)bfd_getl32 (eihd.ident),
- (unsigned)bfd_getl32 (eihd.sysver),
- eihd.matchctl,
- (unsigned)bfd_getl32 (eihd.symvect_size));
- fprintf (file, _(" BPAGE: %u"),
- (unsigned)bfd_getl32 (eihd.virt_mem_block_size));
- if (val & (EIHD__M_OMV_READY | EIHD__M_EXT_BIND_SECT))
- {
- eihef_off = bfd_getl32 (eihd.ext_fixup_off);
- eihnp_off = bfd_getl32 (eihd.noopt_psect_off);
- /* xgettext:c-format */
- fprintf (file, _(", ext fixup offset: %u, no_opt psect off: %u"),
- eihef_off, eihnp_off);
- }
- fprintf (file, _(", alias: %u\n"), (unsigned)bfd_getl16 (eihd.alias));
- if (eihvn_off != 0)
- {
- struct vms_eihvn eihvn;
- unsigned int mask;
- unsigned int j;
- fprintf (file, _("system version array information:\n"));
- if (bfd_seek (abfd, (file_ptr) eihvn_off, SEEK_SET)
- || bfd_bread (&eihvn, sizeof (eihvn), abfd) != sizeof (eihvn))
- {
- fprintf (file, _("cannot read EIHVN header\n"));
- return;
- }
- mask = bfd_getl32 (eihvn.subsystem_mask);
- for (j = 0; j < 32; j++)
- if (mask & (1u << j))
- {
- struct vms_eihvn_subversion ver;
- if (bfd_bread (&ver, sizeof (ver), abfd) != sizeof (ver))
- {
- fprintf (file, _("cannot read EIHVN version\n"));
- return;
- }
- fprintf (file, _(" %02u "), j);
- switch (j)
- {
- case EIHVN__BASE_IMAGE_BIT:
- fputs (_("BASE_IMAGE "), file);
- break;
- case EIHVN__MEMORY_MANAGEMENT_BIT:
- fputs (_("MEMORY_MANAGEMENT"), file);
- break;
- case EIHVN__IO_BIT:
- fputs (_("IO "), file);
- break;
- case EIHVN__FILES_VOLUMES_BIT:
- fputs (_("FILES_VOLUMES "), file);
- break;
- case EIHVN__PROCESS_SCHED_BIT:
- fputs (_("PROCESS_SCHED "), file);
- break;
- case EIHVN__SYSGEN_BIT:
- fputs (_("SYSGEN "), file);
- break;
- case EIHVN__CLUSTERS_LOCKMGR_BIT:
- fputs (_("CLUSTERS_LOCKMGR "), file);
- break;
- case EIHVN__LOGICAL_NAMES_BIT:
- fputs (_("LOGICAL_NAMES "), file);
- break;
- case EIHVN__SECURITY_BIT:
- fputs (_("SECURITY "), file);
- break;
- case EIHVN__IMAGE_ACTIVATOR_BIT:
- fputs (_("IMAGE_ACTIVATOR "), file);
- break;
- case EIHVN__NETWORKS_BIT:
- fputs (_("NETWORKS "), file);
- break;
- case EIHVN__COUNTERS_BIT:
- fputs (_("COUNTERS "), file);
- break;
- case EIHVN__STABLE_BIT:
- fputs (_("STABLE "), file);
- break;
- case EIHVN__MISC_BIT:
- fputs (_("MISC "), file);
- break;
- case EIHVN__CPU_BIT:
- fputs (_("CPU "), file);
- break;
- case EIHVN__VOLATILE_BIT:
- fputs (_("VOLATILE "), file);
- break;
- case EIHVN__SHELL_BIT:
- fputs (_("SHELL "), file);
- break;
- case EIHVN__POSIX_BIT:
- fputs (_("POSIX "), file);
- break;
- case EIHVN__MULTI_PROCESSING_BIT:
- fputs (_("MULTI_PROCESSING "), file);
- break;
- case EIHVN__GALAXY_BIT:
- fputs (_("GALAXY "), file);
- break;
- default:
- fputs (_("*unknown* "), file);
- break;
- }
- fprintf (file, ": %u.%u\n",
- (unsigned)bfd_getl16 (ver.major),
- (unsigned)bfd_getl16 (ver.minor));
- }
- }
- if (eiha_off != 0)
- {
- struct vms_eiha eiha;
- if (bfd_seek (abfd, (file_ptr) eiha_off, SEEK_SET)
- || bfd_bread (&eiha, sizeof (eiha), abfd) != sizeof (eiha))
- {
- fprintf (file, _("cannot read EIHA\n"));
- return;
- }
- fprintf (file, _("Image activation: (size=%u)\n"),
- (unsigned)bfd_getl32 (eiha.size));
- /* xgettext:c-format */
- fprintf (file, _(" First address : 0x%08x 0x%08x\n"),
- (unsigned)bfd_getl32 (eiha.tfradr1_h),
- (unsigned)bfd_getl32 (eiha.tfradr1));
- /* xgettext:c-format */
- fprintf (file, _(" Second address: 0x%08x 0x%08x\n"),
- (unsigned)bfd_getl32 (eiha.tfradr2_h),
- (unsigned)bfd_getl32 (eiha.tfradr2));
- /* xgettext:c-format */
- fprintf (file, _(" Third address : 0x%08x 0x%08x\n"),
- (unsigned)bfd_getl32 (eiha.tfradr3_h),
- (unsigned)bfd_getl32 (eiha.tfradr3));
- /* xgettext:c-format */
- fprintf (file, _(" Fourth address: 0x%08x 0x%08x\n"),
- (unsigned)bfd_getl32 (eiha.tfradr4_h),
- (unsigned)bfd_getl32 (eiha.tfradr4));
- /* xgettext:c-format */
- fprintf (file, _(" Shared image : 0x%08x 0x%08x\n"),
- (unsigned)bfd_getl32 (eiha.inishr_h),
- (unsigned)bfd_getl32 (eiha.inishr));
- }
- if (eihi_off != 0)
- {
- struct vms_eihi eihi;
- if (bfd_seek (abfd, (file_ptr) eihi_off, SEEK_SET)
- || bfd_bread (&eihi, sizeof (eihi), abfd) != sizeof (eihi))
- {
- fprintf (file, _("cannot read EIHI\n"));
- return;
- }
- /* xgettext:c-format */
- fprintf (file, _("Image identification: (major: %u, minor: %u)\n"),
- (unsigned)bfd_getl32 (eihi.majorid),
- (unsigned)bfd_getl32 (eihi.minorid));
- fprintf (file, _(" image name : %.*s\n"),
- eihi.imgnam[0], eihi.imgnam + 1);
- fprintf (file, _(" link time : %s\n"),
- vms_time_to_str (eihi.linktime));
- fprintf (file, _(" image ident : %.*s\n"),
- eihi.imgid[0], eihi.imgid + 1);
- fprintf (file, _(" linker ident : %.*s\n"),
- eihi.linkid[0], eihi.linkid + 1);
- fprintf (file, _(" image build ident: %.*s\n"),
- eihi.imgbid[0], eihi.imgbid + 1);
- }
- if (eihs_off != 0)
- {
- struct vms_eihs eihs;
- if (bfd_seek (abfd, (file_ptr) eihs_off, SEEK_SET)
- || bfd_bread (&eihs, sizeof (eihs), abfd) != sizeof (eihs))
- {
- fprintf (file, _("cannot read EIHS\n"));
- return;
- }
- /* xgettext:c-format */
- fprintf (file, _("Image symbol & debug table: (major: %u, minor: %u)\n"),
- (unsigned)bfd_getl32 (eihs.majorid),
- (unsigned)bfd_getl32 (eihs.minorid));
- dst_vbn = bfd_getl32 (eihs.dstvbn);
- dst_size = bfd_getl32 (eihs.dstsize);
- /* xgettext:c-format */
- fprintf (file, _(" debug symbol table : vbn: %u, size: %u (0x%x)\n"),
- dst_vbn, dst_size, dst_size);
- gst_vbn = bfd_getl32 (eihs.gstvbn);
- gst_size = bfd_getl32 (eihs.gstsize);
- /* xgettext:c-format */
- fprintf (file, _(" global symbol table: vbn: %u, records: %u\n"),
- gst_vbn, gst_size);
- dmt_vbn = bfd_getl32 (eihs.dmtvbn);
- dmt_size = bfd_getl32 (eihs.dmtsize);
- /* xgettext:c-format */
- fprintf (file, _(" debug module table : vbn: %u, size: %u\n"),
- dmt_vbn, dmt_size);
- }
- while (eisd_off != 0)
- {
- struct vms_eisd eisd;
- unsigned int len;
- while (1)
- {
- if (bfd_seek (abfd, (file_ptr) eisd_off, SEEK_SET)
- || bfd_bread (&eisd, sizeof (eisd), abfd) != sizeof (eisd))
- {
- fprintf (file, _("cannot read EISD\n"));
- return;
- }
- len = (unsigned)bfd_getl32 (eisd.eisdsize);
- if (len != (unsigned)-1)
- break;
- /* Next block. */
- eisd_off = (eisd_off + VMS_BLOCK_SIZE) & ~(VMS_BLOCK_SIZE - 1);
- }
- /* xgettext:c-format */
- fprintf (file, _("Image section descriptor: (major: %u, minor: %u, "
- "size: %u, offset: %u)\n"),
- (unsigned)bfd_getl32 (eisd.majorid),
- (unsigned)bfd_getl32 (eisd.minorid),
- len, eisd_off);
- if (len == 0)
- break;
- /* xgettext:c-format */
- fprintf (file, _(" section: base: 0x%08x%08x size: 0x%08x\n"),
- (unsigned)bfd_getl32 (eisd.virt_addr + 4),
- (unsigned)bfd_getl32 (eisd.virt_addr + 0),
- (unsigned)bfd_getl32 (eisd.secsize));
- val = (unsigned)bfd_getl32 (eisd.flags);
- fprintf (file, _(" flags: 0x%04x"), val);
- if (val & EISD__M_GBL)
- fprintf (file, " GBL");
- if (val & EISD__M_CRF)
- fprintf (file, " CRF");
- if (val & EISD__M_DZRO)
- fprintf (file, " DZRO");
- if (val & EISD__M_WRT)
- fprintf (file, " WRT");
- if (val & EISD__M_INITALCODE)
- fprintf (file, " INITALCODE");
- if (val & EISD__M_BASED)
- fprintf (file, " BASED");
- if (val & EISD__M_FIXUPVEC)
- fprintf (file, " FIXUPVEC");
- if (val & EISD__M_RESIDENT)
- fprintf (file, " RESIDENT");
- if (val & EISD__M_VECTOR)
- fprintf (file, " VECTOR");
- if (val & EISD__M_PROTECT)
- fprintf (file, " PROTECT");
- if (val & EISD__M_LASTCLU)
- fprintf (file, " LASTCLU");
- if (val & EISD__M_EXE)
- fprintf (file, " EXE");
- if (val & EISD__M_NONSHRADR)
- fprintf (file, " NONSHRADR");
- if (val & EISD__M_QUAD_LENGTH)
- fprintf (file, " QUAD_LENGTH");
- if (val & EISD__M_ALLOC_64BIT)
- fprintf (file, " ALLOC_64BIT");
- fprintf (file, "\n");
- if (val & EISD__M_FIXUPVEC)
- {
- eiaf_vbn = bfd_getl32 (eisd.vbn);
- eiaf_size = bfd_getl32 (eisd.secsize);
- }
- /* xgettext:c-format */
- fprintf (file, _(" vbn: %u, pfc: %u, matchctl: %u type: %u ("),
- (unsigned)bfd_getl32 (eisd.vbn),
- eisd.pfc, eisd.matchctl, eisd.type);
- switch (eisd.type)
- {
- case EISD__K_NORMAL:
- fputs (_("NORMAL"), file);
- break;
- case EISD__K_SHRFXD:
- fputs (_("SHRFXD"), file);
- break;
- case EISD__K_PRVFXD:
- fputs (_("PRVFXD"), file);
- break;
- case EISD__K_SHRPIC:
- fputs (_("SHRPIC"), file);
- break;
- case EISD__K_PRVPIC:
- fputs (_("PRVPIC"), file);
- break;
- case EISD__K_USRSTACK:
- fputs (_("USRSTACK"), file);
- break;
- default:
- fputs (_("*unknown*"), file);
- break;
- }
- fputs (_(")\n"), file);
- if (val & EISD__M_GBL)
- /* xgettext:c-format */
- fprintf (file, _(" ident: 0x%08x, name: %.*s\n"),
- (unsigned)bfd_getl32 (eisd.ident),
- eisd.gblnam[0], eisd.gblnam + 1);
- eisd_off += len;
- }
- if (dmt_vbn != 0)
- {
- if (bfd_seek (abfd, (file_ptr) (dmt_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
- {
- fprintf (file, _("cannot read DMT\n"));
- return;
- }
- fprintf (file, _("Debug module table:\n"));
- while (dmt_size > 0)
- {
- struct vms_dmt_header dmth;
- unsigned int count;
- if (bfd_bread (&dmth, sizeof (dmth), abfd) != sizeof (dmth))
- {
- fprintf (file, _("cannot read DMT header\n"));
- return;
- }
- count = bfd_getl16 (dmth.psect_count);
- fprintf (file,
- /* xgettext:c-format */
- _(" module offset: 0x%08x, size: 0x%08x, (%u psects)\n"),
- (unsigned)bfd_getl32 (dmth.modbeg),
- (unsigned)bfd_getl32 (dmth.size), count);
- dmt_size -= sizeof (dmth);
- while (count > 0)
- {
- struct vms_dmt_psect dmtp;
- if (bfd_bread (&dmtp, sizeof (dmtp), abfd) != sizeof (dmtp))
- {
- fprintf (file, _("cannot read DMT psect\n"));
- return;
- }
- /* xgettext:c-format */
- fprintf (file, _(" psect start: 0x%08x, length: %u\n"),
- (unsigned)bfd_getl32 (dmtp.start),
- (unsigned)bfd_getl32 (dmtp.length));
- count--;
- dmt_size -= sizeof (dmtp);
- }
- }
- }
- if (dst_vbn != 0)
- {
- if (bfd_seek (abfd, (file_ptr) (dst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
- {
- fprintf (file, _("cannot read DST\n"));
- return;
- }
- evax_bfd_print_dst (abfd, dst_size, file);
- }
- if (gst_vbn != 0)
- {
- if (bfd_seek (abfd, (file_ptr) (gst_vbn - 1) * VMS_BLOCK_SIZE, SEEK_SET))
- {
- fprintf (file, _("cannot read GST\n"));
- return;
- }
- fprintf (file, _("Global symbol table:\n"));
- evax_bfd_print_eobj (abfd, file);
- }
- if (eiaf_vbn != 0 && eiaf_size >= sizeof (struct vms_eiaf))
- {
- unsigned char *buf;
- struct vms_eiaf *eiaf;
- unsigned int qrelfixoff;
- unsigned int lrelfixoff;
- unsigned int qdotadroff;
- unsigned int ldotadroff;
- unsigned int shrimgcnt;
- unsigned int shlstoff;
- unsigned int codeadroff;
- unsigned int lpfixoff;
- unsigned int chgprtoff;
- file_ptr f_off = (file_ptr) (eiaf_vbn - 1) * VMS_BLOCK_SIZE;
- if (bfd_seek (abfd, f_off, SEEK_SET) != 0
- || (buf = _bfd_malloc_and_read (abfd, eiaf_size, eiaf_size)) == NULL)
- {
- fprintf (file, _("cannot read EIHA\n"));
- return;
- }
- eiaf = (struct vms_eiaf *)buf;
- fprintf (file,
- /* xgettext:c-format */
- _("Image activator fixup: (major: %u, minor: %u)\n"),
- (unsigned)bfd_getl32 (eiaf->majorid),
- (unsigned)bfd_getl32 (eiaf->minorid));
- /* xgettext:c-format */
- fprintf (file, _(" iaflink : 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (eiaf->iaflink + 0),
- (unsigned)bfd_getl32 (eiaf->iaflink + 4));
- /* xgettext:c-format */
- fprintf (file, _(" fixuplnk: 0x%08x %08x\n"),
- (unsigned)bfd_getl32 (eiaf->fixuplnk + 0),
- (unsigned)bfd_getl32 (eiaf->fixuplnk + 4));
- fprintf (file, _(" size : %u\n"),
- (unsigned)bfd_getl32 (eiaf->size));
- fprintf (file, _(" flags: 0x%08x\n"),
- (unsigned)bfd_getl32 (eiaf->flags));
- qrelfixoff = bfd_getl32 (eiaf->qrelfixoff);
- lrelfixoff = bfd_getl32 (eiaf->lrelfixoff);
- /* xgettext:c-format */
- fprintf (file, _(" qrelfixoff: %5u, lrelfixoff: %5u\n"),
- qrelfixoff, lrelfixoff);
- qdotadroff = bfd_getl32 (eiaf->qdotadroff);
- ldotadroff = bfd_getl32 (eiaf->ldotadroff);
- /* xgettext:c-format */
- fprintf (file, _(" qdotadroff: %5u, ldotadroff: %5u\n"),
- qdotadroff, ldotadroff);
- codeadroff = bfd_getl32 (eiaf->codeadroff);
- lpfixoff = bfd_getl32 (eiaf->lpfixoff);
- /* xgettext:c-format */
- fprintf (file, _(" codeadroff: %5u, lpfixoff : %5u\n"),
- codeadroff, lpfixoff);
- chgprtoff = bfd_getl32 (eiaf->chgprtoff);
- fprintf (file, _(" chgprtoff : %5u\n"), chgprtoff);
- shrimgcnt = bfd_getl32 (eiaf->shrimgcnt);
- shlstoff = bfd_getl32 (eiaf->shlstoff);
- /* xgettext:c-format */
- fprintf (file, _(" shlstoff : %5u, shrimgcnt : %5u\n"),
- shlstoff, shrimgcnt);
- /* xgettext:c-format */
- fprintf (file, _(" shlextra : %5u, permctx : %5u\n"),
- (unsigned)bfd_getl32 (eiaf->shlextra),
- (unsigned)bfd_getl32 (eiaf->permctx));
- fprintf (file, _(" base_va : 0x%08x\n"),
- (unsigned)bfd_getl32 (eiaf->base_va));
- fprintf (file, _(" lppsbfixoff: %5u\n"),
- (unsigned)bfd_getl32 (eiaf->lppsbfixoff));
- if (shlstoff)
- {
- unsigned int j;
- fprintf (file, _(" Shareable images:\n"));
- for (j = 0;
- j < shrimgcnt && shlstoff <= eiaf_size - sizeof (struct vms_shl);
- j++, shlstoff += sizeof (struct vms_shl))
- {
- struct vms_shl *shl = (struct vms_shl *) (buf + shlstoff);
- fprintf (file,
- /* xgettext:c-format */
- _(" %u: size: %u, flags: 0x%02x, name: %.*s\n"),
- j, shl->size, shl->flags,
- shl->imgnam[0], shl->imgnam + 1);
- }
- }
- if (qrelfixoff != 0)
- {
- fprintf (file, _(" quad-word relocation fixups:\n"));
- evax_bfd_print_relocation_records (file, buf, eiaf_size,
- qrelfixoff, 8);
- }
- if (lrelfixoff != 0)
- {
- fprintf (file, _(" long-word relocation fixups:\n"));
- evax_bfd_print_relocation_records (file, buf, eiaf_size,
- lrelfixoff, 4);
- }
- if (qdotadroff != 0)
- {
- fprintf (file, _(" quad-word .address reference fixups:\n"));
- evax_bfd_print_address_fixups (file, buf, eiaf_size, qdotadroff);
- }
- if (ldotadroff != 0)
- {
- fprintf (file, _(" long-word .address reference fixups:\n"));
- evax_bfd_print_address_fixups (file, buf, eiaf_size, ldotadroff);
- }
- if (codeadroff != 0)
- {
- fprintf (file, _(" Code Address Reference Fixups:\n"));
- evax_bfd_print_reference_fixups (file, buf, eiaf_size, codeadroff);
- }
- if (lpfixoff != 0)
- {
- fprintf (file, _(" Linkage Pairs Reference Fixups:\n"));
- evax_bfd_print_reference_fixups (file, buf, eiaf_size, lpfixoff);
- }
- if (chgprtoff && chgprtoff <= eiaf_size - 4)
- {
- unsigned int count = (unsigned) bfd_getl32 (buf + chgprtoff);
- unsigned int j;
- fprintf (file, _(" Change Protection (%u entries):\n"), count);
- for (j = 0, chgprtoff += 4;
- j < count && chgprtoff <= eiaf_size - sizeof (struct vms_eicp);
- j++, chgprtoff += sizeof (struct vms_eicp))
- {
- struct vms_eicp *eicp = (struct vms_eicp *) (buf + chgprtoff);
- unsigned int prot = bfd_getl32 (eicp->newprt);
- fprintf (file,
- /* xgettext:c-format */
- _(" base: 0x%08x %08x, size: 0x%08x, prot: 0x%08x "),
- (unsigned) bfd_getl32 (eicp->baseva + 4),
- (unsigned) bfd_getl32 (eicp->baseva + 0),
- (unsigned) bfd_getl32 (eicp->size),
- (unsigned) bfd_getl32 (eicp->newprt));
- switch (prot)
- {
- case PRT__C_NA:
- fprintf (file, "NA");
- break;
- case PRT__C_RESERVED:
- fprintf (file, "RES");
- break;
- case PRT__C_KW:
- fprintf (file, "KW");
- break;
- case PRT__C_KR:
- fprintf (file, "KR");
- break;
- case PRT__C_UW:
- fprintf (file, "UW");
- break;
- case PRT__C_EW:
- fprintf (file, "EW");
- break;
- case PRT__C_ERKW:
- fprintf (file, "ERKW");
- break;
- case PRT__C_ER:
- fprintf (file, "ER");
- break;
- case PRT__C_SW:
- fprintf (file, "SW");
- break;
- case PRT__C_SREW:
- fprintf (file, "SREW");
- break;
- case PRT__C_SRKW:
- fprintf (file, "SRKW");
- break;
- case PRT__C_SR:
- fprintf (file, "SR");
- break;
- case PRT__C_URSW:
- fprintf (file, "URSW");
- break;
- case PRT__C_UREW:
- fprintf (file, "UREW");
- break;
- case PRT__C_URKW:
- fprintf (file, "URKW");
- break;
- case PRT__C_UR:
- fprintf (file, "UR");
- break;
- default:
- fputs ("??", file);
- break;
- }
- fputc ('\n', file);
- }
- }
- free (buf);
- }
- }
- static bool
- vms_bfd_print_private_bfd_data (bfd *abfd, void *ptr)
- {
- FILE *file = (FILE *)ptr;
- if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
- evax_bfd_print_image (abfd, file);
- else
- {
- if (bfd_seek (abfd, 0, SEEK_SET))
- return false;
- evax_bfd_print_eobj (abfd, file);
- }
- return true;
- }
- /* Linking. */
- /* Slurp ETIR/EDBG/ETBT VMS object records. */
- static bool
- alpha_vms_read_sections_content (bfd *abfd, struct bfd_link_info *info)
- {
- asection *cur_section;
- file_ptr cur_offset;
- asection *dst_section;
- file_ptr dst_offset;
- if (bfd_seek (abfd, 0, SEEK_SET) != 0)
- return false;
- cur_section = NULL;
- cur_offset = 0;
- dst_section = PRIV (dst_section);
- dst_offset = 0;
- if (info)
- {
- if (info->strip == strip_all || info->strip == strip_debugger)
- {
- /* Discard the DST section. */
- dst_offset = 0;
- dst_section = NULL;
- }
- else if (dst_section)
- {
- dst_offset = dst_section->output_offset;
- dst_section = dst_section->output_section;
- }
- }
- while (1)
- {
- int type;
- bool res;
- type = _bfd_vms_get_object_record (abfd);
- if (type < 0)
- {
- vms_debug2 ((2, "next_record failed\n"));
- return false;
- }
- switch (type)
- {
- case EOBJ__C_ETIR:
- PRIV (image_section) = cur_section;
- PRIV (image_offset) = cur_offset;
- res = _bfd_vms_slurp_etir (abfd, info);
- cur_section = PRIV (image_section);
- cur_offset = PRIV (image_offset);
- break;
- case EOBJ__C_EDBG:
- case EOBJ__C_ETBT:
- if (dst_section == NULL)
- continue;
- PRIV (image_section) = dst_section;
- PRIV (image_offset) = dst_offset;
- res = _bfd_vms_slurp_etir (abfd, info);
- dst_offset = PRIV (image_offset);
- break;
- case EOBJ__C_EEOM:
- return true;
- default:
- continue;
- }
- if (!res)
- {
- vms_debug2 ((2, "slurp eobj type %d failed\n", type));
- return false;
- }
- }
- }
- static int
- alpha_vms_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info ATTRIBUTE_UNUSED)
- {
- return 0;
- }
- /* Add a linkage pair fixup at address SECT + OFFSET to SHLIB. */
- static bool
- alpha_vms_add_fixup_lp (struct bfd_link_info *info, bfd *src, bfd *shlib)
- {
- struct alpha_vms_shlib_el *sl;
- asection *sect = PRIV2 (src, image_section);
- file_ptr offset = PRIV2 (src, image_offset);
- bfd_vma *p;
- sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
- struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
- sl->has_fixups = true;
- p = VEC_APPEND (sl->lp, bfd_vma);
- if (p == NULL)
- return false;
- *p = sect->output_section->vma + sect->output_offset + offset;
- sect->output_section->flags |= SEC_RELOC;
- return true;
- }
- /* Add a code address fixup at address SECT + OFFSET to SHLIB. */
- static bool
- alpha_vms_add_fixup_ca (struct bfd_link_info *info, bfd *src, bfd *shlib)
- {
- struct alpha_vms_shlib_el *sl;
- asection *sect = PRIV2 (src, image_section);
- file_ptr offset = PRIV2 (src, image_offset);
- bfd_vma *p;
- sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
- struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
- sl->has_fixups = true;
- p = VEC_APPEND (sl->ca, bfd_vma);
- if (p == NULL)
- return false;
- *p = sect->output_section->vma + sect->output_offset + offset;
- sect->output_section->flags |= SEC_RELOC;
- return true;
- }
- /* Add a quad word relocation fixup at address SECT + OFFSET to SHLIB. */
- static bool
- alpha_vms_add_fixup_qr (struct bfd_link_info *info, bfd *src,
- bfd *shlib, bfd_vma vec)
- {
- struct alpha_vms_shlib_el *sl;
- struct alpha_vms_vma_ref *r;
- asection *sect = PRIV2 (src, image_section);
- file_ptr offset = PRIV2 (src, image_offset);
- sl = &VEC_EL (alpha_vms_link_hash (info)->shrlibs,
- struct alpha_vms_shlib_el, PRIV2 (shlib, shr_index));
- sl->has_fixups = true;
- r = VEC_APPEND (sl->qr, struct alpha_vms_vma_ref);
- if (r == NULL)
- return false;
- r->vma = sect->output_section->vma + sect->output_offset + offset;
- r->ref = vec;
- sect->output_section->flags |= SEC_RELOC;
- return true;
- }
- static bool
- alpha_vms_add_fixup_lr (struct bfd_link_info *info ATTRIBUTE_UNUSED,
- unsigned int shr ATTRIBUTE_UNUSED,
- bfd_vma vec ATTRIBUTE_UNUSED)
- {
- /* Not yet supported. */
- return false;
- }
- /* Add relocation. FIXME: Not yet emitted. */
- static bool
- alpha_vms_add_lw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
- {
- return false;
- }
- static bool
- alpha_vms_add_qw_reloc (struct bfd_link_info *info ATTRIBUTE_UNUSED)
- {
- return false;
- }
- static struct bfd_hash_entry *
- alpha_vms_link_hash_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string)
- {
- struct alpha_vms_link_hash_entry *ret =
- (struct alpha_vms_link_hash_entry *) entry;
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == NULL)
- ret = ((struct alpha_vms_link_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct alpha_vms_link_hash_entry)));
- if (ret == NULL)
- return NULL;
- /* Call the allocation method of the superclass. */
- ret = ((struct alpha_vms_link_hash_entry *)
- _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
- table, string));
- ret->sym = NULL;
- return (struct bfd_hash_entry *) ret;
- }
- static void
- alpha_vms_bfd_link_hash_table_free (bfd *abfd)
- {
- struct alpha_vms_link_hash_table *t;
- unsigned i;
- t = (struct alpha_vms_link_hash_table *) abfd->link.hash;
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- free (&VEC_EL (shlib->ca, bfd_vma, 0));
- free (&VEC_EL (shlib->lp, bfd_vma, 0));
- free (&VEC_EL (shlib->qr, struct alpha_vms_vma_ref, 0));
- }
- free (&VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, 0));
- _bfd_generic_link_hash_table_free (abfd);
- }
- /* Create an Alpha/VMS link hash table. */
- static struct bfd_link_hash_table *
- alpha_vms_bfd_link_hash_table_create (bfd *abfd)
- {
- struct alpha_vms_link_hash_table *ret;
- size_t amt = sizeof (struct alpha_vms_link_hash_table);
- ret = (struct alpha_vms_link_hash_table *) bfd_malloc (amt);
- if (ret == NULL)
- return NULL;
- if (!_bfd_link_hash_table_init (&ret->root, abfd,
- alpha_vms_link_hash_newfunc,
- sizeof (struct alpha_vms_link_hash_entry)))
- {
- free (ret);
- return NULL;
- }
- VEC_INIT (ret->shrlibs);
- ret->fixup = NULL;
- ret->root.hash_table_free = alpha_vms_bfd_link_hash_table_free;
- return &ret->root;
- }
- static bool
- alpha_vms_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
- {
- unsigned int i;
- for (i = 0; i < PRIV (gsd_sym_count); i++)
- {
- struct vms_symbol_entry *e = PRIV (syms)[i];
- struct alpha_vms_link_hash_entry *h;
- struct bfd_link_hash_entry *h_root;
- asymbol sym;
- if (!alpha_vms_convert_symbol (abfd, e, &sym))
- return false;
- if ((e->flags & EGSY__V_DEF) && abfd->selective_search)
- {
- /* In selective_search mode, only add definition that are
- required. */
- h = (struct alpha_vms_link_hash_entry *)bfd_link_hash_lookup
- (info->hash, sym.name, false, false, false);
- if (h == NULL || h->root.type != bfd_link_hash_undefined)
- continue;
- }
- else
- h = NULL;
- h_root = (struct bfd_link_hash_entry *) h;
- if (!_bfd_generic_link_add_one_symbol (info, abfd, sym.name, sym.flags,
- sym.section, sym.value, NULL,
- false, false, &h_root))
- return false;
- h = (struct alpha_vms_link_hash_entry *) h_root;
- if ((e->flags & EGSY__V_DEF)
- && h->sym == NULL
- && abfd->xvec == info->output_bfd->xvec)
- h->sym = e;
- }
- if (abfd->flags & DYNAMIC)
- {
- struct alpha_vms_shlib_el *shlib;
- /* We do not want to include any of the sections in a dynamic
- object in the output file. See comment in elflink.c. */
- bfd_section_list_clear (abfd);
- shlib = VEC_APPEND (alpha_vms_link_hash (info)->shrlibs,
- struct alpha_vms_shlib_el);
- if (shlib == NULL)
- return false;
- shlib->abfd = abfd;
- VEC_INIT (shlib->ca);
- VEC_INIT (shlib->lp);
- VEC_INIT (shlib->qr);
- PRIV (shr_index) = VEC_COUNT (alpha_vms_link_hash (info)->shrlibs) - 1;
- }
- return true;
- }
- static bool
- alpha_vms_link_add_archive_symbols (bfd *abfd, struct bfd_link_info *info)
- {
- int pass;
- struct bfd_link_hash_entry **pundef;
- struct bfd_link_hash_entry **next_pundef;
- /* We only accept VMS libraries. */
- if (info->output_bfd->xvec != abfd->xvec)
- {
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
- /* The archive_pass field in the archive itself is used to
- initialize PASS, since we may search the same archive multiple
- times. */
- pass = ++abfd->archive_pass;
- /* Look through the list of undefined symbols. */
- for (pundef = &info->hash->undefs; *pundef != NULL; pundef = next_pundef)
- {
- struct bfd_link_hash_entry *h;
- symindex symidx;
- bfd *element;
- bfd *orig_element;
- h = *pundef;
- next_pundef = &(*pundef)->u.undef.next;
- /* When a symbol is defined, it is not necessarily removed from
- the list. */
- if (h->type != bfd_link_hash_undefined
- && h->type != bfd_link_hash_common)
- {
- /* Remove this entry from the list, for general cleanliness
- and because we are going to look through the list again
- if we search any more libraries. We can't remove the
- entry if it is the tail, because that would lose any
- entries we add to the list later on. */
- if (*pundef != info->hash->undefs_tail)
- {
- *pundef = *next_pundef;
- next_pundef = pundef;
- }
- continue;
- }
- /* Look for this symbol in the archive hash table. */
- symidx = _bfd_vms_lib_find_symbol (abfd, h->root.string);
- if (symidx == BFD_NO_MORE_SYMBOLS)
- {
- /* Nothing in this slot. */
- continue;
- }
- element = bfd_get_elt_at_index (abfd, symidx);
- if (element == NULL)
- return false;
- if (element->archive_pass == -1 || element->archive_pass == pass)
- {
- /* Next symbol if this archive is wrong or already handled. */
- continue;
- }
- if (! bfd_check_format (element, bfd_object))
- {
- element->archive_pass = -1;
- return false;
- }
- orig_element = element;
- if (bfd_is_thin_archive (abfd))
- {
- element = _bfd_vms_lib_get_imagelib_file (element);
- if (element == NULL || !bfd_check_format (element, bfd_object))
- {
- orig_element->archive_pass = -1;
- return false;
- }
- }
- /* Unlike the generic linker, we know that this element provides
- a definition for an undefined symbol and we know that we want
- to include it. We don't need to check anything. */
- if (!(*info->callbacks
- ->add_archive_element) (info, element, h->root.string, &element))
- continue;
- if (!alpha_vms_link_add_object_symbols (element, info))
- return false;
- orig_element->archive_pass = pass;
- }
- return true;
- }
- static bool
- alpha_vms_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
- {
- switch (bfd_get_format (abfd))
- {
- case bfd_object:
- vms_debug2 ((2, "vms_link_add_symbols for object %s\n",
- abfd->filename));
- return alpha_vms_link_add_object_symbols (abfd, info);
- break;
- case bfd_archive:
- vms_debug2 ((2, "vms_link_add_symbols for archive %s\n",
- abfd->filename));
- return alpha_vms_link_add_archive_symbols (abfd, info);
- break;
- default:
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
- }
- static bool
- alpha_vms_build_fixups (struct bfd_link_info *info)
- {
- struct alpha_vms_link_hash_table *t = alpha_vms_link_hash (info);
- unsigned char *content;
- unsigned int i;
- unsigned int sz = 0;
- unsigned int lp_sz = 0;
- unsigned int ca_sz = 0;
- unsigned int qr_sz = 0;
- unsigned int shrimg_cnt = 0;
- unsigned int chgprt_num = 0;
- unsigned int chgprt_sz = 0;
- struct vms_eiaf *eiaf;
- unsigned int off;
- asection *sec;
- /* Shared libraries. */
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- if (!shlib->has_fixups)
- continue;
- shrimg_cnt++;
- if (VEC_COUNT (shlib->ca) > 0)
- {
- /* Header + entries. */
- ca_sz += 8;
- ca_sz += VEC_COUNT (shlib->ca) * 4;
- }
- if (VEC_COUNT (shlib->lp) > 0)
- {
- /* Header + entries. */
- lp_sz += 8;
- lp_sz += VEC_COUNT (shlib->lp) * 4;
- }
- if (VEC_COUNT (shlib->qr) > 0)
- {
- /* Header + entries. */
- qr_sz += 8;
- qr_sz += VEC_COUNT (shlib->qr) * 8;
- }
- }
- /* Add markers. */
- if (ca_sz > 0)
- ca_sz += 8;
- if (lp_sz > 0)
- lp_sz += 8;
- if (qr_sz > 0)
- qr_sz += 8;
- /* Finish now if there is no content. */
- if (ca_sz + lp_sz + qr_sz == 0)
- return true;
- /* Add an eicp entry for the fixup itself. */
- chgprt_num = 1;
- for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
- {
- /* This isect could be made RO or EXE after relocations are applied. */
- if ((sec->flags & SEC_RELOC) != 0
- && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
- chgprt_num++;
- }
- chgprt_sz = 4 + chgprt_num * sizeof (struct vms_eicp);
- /* Allocate section content (round-up size) */
- sz = sizeof (struct vms_eiaf) + shrimg_cnt * sizeof (struct vms_shl)
- + ca_sz + lp_sz + qr_sz + chgprt_sz;
- sz = (sz + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1);
- content = bfd_zalloc (info->output_bfd, sz);
- if (content == NULL)
- return false;
- sec = alpha_vms_link_hash (info)->fixup;
- sec->contents = content;
- sec->size = sz;
- eiaf = (struct vms_eiaf *)content;
- off = sizeof (struct vms_eiaf);
- bfd_putl32 (0, eiaf->majorid);
- bfd_putl32 (0, eiaf->minorid);
- bfd_putl32 (0, eiaf->iaflink);
- bfd_putl32 (0, eiaf->fixuplnk);
- bfd_putl32 (sizeof (struct vms_eiaf), eiaf->size);
- bfd_putl32 (0, eiaf->flags);
- bfd_putl32 (0, eiaf->qrelfixoff);
- bfd_putl32 (0, eiaf->lrelfixoff);
- bfd_putl32 (0, eiaf->qdotadroff);
- bfd_putl32 (0, eiaf->ldotadroff);
- bfd_putl32 (0, eiaf->codeadroff);
- bfd_putl32 (0, eiaf->lpfixoff);
- bfd_putl32 (0, eiaf->chgprtoff);
- bfd_putl32 (shrimg_cnt ? off : 0, eiaf->shlstoff);
- bfd_putl32 (shrimg_cnt, eiaf->shrimgcnt);
- bfd_putl32 (0, eiaf->shlextra);
- bfd_putl32 (0, eiaf->permctx);
- bfd_putl32 (0, eiaf->base_va);
- bfd_putl32 (0, eiaf->lppsbfixoff);
- if (shrimg_cnt)
- {
- shrimg_cnt = 0;
- /* Write shl. */
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- struct vms_shl *shl;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- if (!shlib->has_fixups)
- continue;
- /* Renumber shared images. */
- PRIV2 (shlib->abfd, shr_index) = shrimg_cnt++;
- shl = (struct vms_shl *)(content + off);
- bfd_putl32 (0, shl->baseva);
- bfd_putl32 (0, shl->shlptr);
- bfd_putl32 (0, shl->ident);
- bfd_putl32 (0, shl->permctx);
- shl->size = sizeof (struct vms_shl);
- bfd_putl16 (0, shl->fill_1);
- shl->flags = 0;
- bfd_putl32 (0, shl->icb);
- shl->imgnam[0] = strlen (PRIV2 (shlib->abfd, hdr_data.hdr_t_name));
- memcpy (shl->imgnam + 1, PRIV2 (shlib->abfd, hdr_data.hdr_t_name),
- shl->imgnam[0]);
- off += sizeof (struct vms_shl);
- }
- /* CA fixups. */
- if (ca_sz != 0)
- {
- bfd_putl32 (off, eiaf->codeadroff);
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- unsigned int j;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- if (VEC_COUNT (shlib->ca) == 0)
- continue;
- bfd_putl32 (VEC_COUNT (shlib->ca), content + off);
- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
- off += 8;
- for (j = 0; j < VEC_COUNT (shlib->ca); j++)
- {
- bfd_putl32 (VEC_EL (shlib->ca, bfd_vma, j) - t->base_addr,
- content + off);
- off += 4;
- }
- }
- bfd_putl32 (0, content + off);
- bfd_putl32 (0, content + off + 4);
- off += 8;
- }
- /* LP fixups. */
- if (lp_sz != 0)
- {
- bfd_putl32 (off, eiaf->lpfixoff);
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- unsigned int j;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- if (VEC_COUNT (shlib->lp) == 0)
- continue;
- bfd_putl32 (VEC_COUNT (shlib->lp), content + off);
- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
- off += 8;
- for (j = 0; j < VEC_COUNT (shlib->lp); j++)
- {
- bfd_putl32 (VEC_EL (shlib->lp, bfd_vma, j) - t->base_addr,
- content + off);
- off += 4;
- }
- }
- bfd_putl32 (0, content + off);
- bfd_putl32 (0, content + off + 4);
- off += 8;
- }
- /* QR fixups. */
- if (qr_sz != 0)
- {
- bfd_putl32 (off, eiaf->qdotadroff);
- for (i = 0; i < VEC_COUNT (t->shrlibs); i++)
- {
- struct alpha_vms_shlib_el *shlib;
- unsigned int j;
- shlib = &VEC_EL (t->shrlibs, struct alpha_vms_shlib_el, i);
- if (VEC_COUNT (shlib->qr) == 0)
- continue;
- bfd_putl32 (VEC_COUNT (shlib->qr), content + off);
- bfd_putl32 (PRIV2 (shlib->abfd, shr_index), content + off + 4);
- off += 8;
- for (j = 0; j < VEC_COUNT (shlib->qr); j++)
- {
- struct alpha_vms_vma_ref *r;
- r = &VEC_EL (shlib->qr, struct alpha_vms_vma_ref, j);
- bfd_putl32 (r->vma - t->base_addr, content + off);
- bfd_putl32 (r->ref, content + off + 4);
- off += 8;
- }
- }
- bfd_putl32 (0, content + off);
- bfd_putl32 (0, content + off + 4);
- off += 8;
- }
- }
- /* Write the change protection table. */
- bfd_putl32 (off, eiaf->chgprtoff);
- bfd_putl32 (chgprt_num, content + off);
- off += 4;
- for (sec = info->output_bfd->sections; sec != NULL; sec = sec->next)
- {
- struct vms_eicp *eicp;
- unsigned int prot;
- if ((sec->flags & SEC_LINKER_CREATED) != 0 &&
- strcmp (sec->name, "$FIXUP$") == 0)
- prot = PRT__C_UREW;
- else if ((sec->flags & SEC_RELOC) != 0
- && (sec->flags & (SEC_CODE | SEC_READONLY)) != 0)
- prot = PRT__C_UR;
- else
- continue;
- eicp = (struct vms_eicp *)(content + off);
- bfd_putl64 (sec->vma - t->base_addr, eicp->baseva);
- bfd_putl32 ((sec->size + VMS_BLOCK_SIZE - 1) & ~(VMS_BLOCK_SIZE - 1),
- eicp->size);
- bfd_putl32 (prot, eicp->newprt);
- off += sizeof (struct vms_eicp);
- }
- return true;
- }
- /* Called by bfd_hash_traverse to fill the symbol table.
- Return FALSE in case of failure. */
- static bool
- alpha_vms_link_output_symbol (struct bfd_hash_entry *bh, void *infov)
- {
- struct bfd_link_hash_entry *hc = (struct bfd_link_hash_entry *) bh;
- struct bfd_link_info *info = (struct bfd_link_info *)infov;
- struct alpha_vms_link_hash_entry *h;
- struct vms_symbol_entry *sym;
- if (hc->type == bfd_link_hash_warning)
- {
- hc = hc->u.i.link;
- if (hc->type == bfd_link_hash_new)
- return true;
- }
- h = (struct alpha_vms_link_hash_entry *) hc;
- switch (h->root.type)
- {
- case bfd_link_hash_undefined:
- return true;
- case bfd_link_hash_new:
- case bfd_link_hash_warning:
- abort ();
- case bfd_link_hash_undefweak:
- return true;
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- {
- asection *sec = h->root.u.def.section;
- /* FIXME: this is certainly a symbol from a dynamic library. */
- if (bfd_is_abs_section (sec))
- return true;
- if (sec->owner->flags & DYNAMIC)
- return true;
- }
- break;
- case bfd_link_hash_common:
- break;
- case bfd_link_hash_indirect:
- return true;
- }
- /* Do not write not kept symbols. */
- if (info->strip == strip_some
- && bfd_hash_lookup (info->keep_hash, h->root.root.string,
- false, false) != NULL)
- return true;
- if (h->sym == NULL)
- {
- /* This symbol doesn't come from a VMS object. So we suppose it is
- a data. */
- int len = strlen (h->root.root.string);
- sym = (struct vms_symbol_entry *)bfd_zalloc (info->output_bfd,
- sizeof (*sym) + len);
- if (sym == NULL)
- abort ();
- sym->namelen = len;
- memcpy (sym->name, h->root.root.string, len);
- sym->name[len] = 0;
- sym->owner = info->output_bfd;
- sym->typ = EGSD__C_SYMG;
- sym->data_type = 0;
- sym->flags = EGSY__V_DEF | EGSY__V_REL;
- sym->symbol_vector = h->root.u.def.value;
- sym->section = h->root.u.def.section;
- sym->value = h->root.u.def.value;
- }
- else
- sym = h->sym;
- if (!add_symbol_entry (info->output_bfd, sym))
- return false;
- return true;
- }
- static bool
- alpha_vms_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
- {
- asection *o;
- struct bfd_link_order *p;
- bfd *sub;
- asection *fixupsec;
- bfd_vma base_addr;
- bfd_vma last_addr;
- asection *dst;
- asection *dmt;
- if (bfd_link_relocatable (info))
- {
- /* FIXME: we do not yet support relocatable link. It is not obvious
- how to do it for debug infos. */
- (*info->callbacks->einfo)(_("%P: relocatable link is not supported\n"));
- return false;
- }
- abfd->outsymbols = NULL;
- abfd->symcount = 0;
- /* Mark all sections which will be included in the output file. */
- for (o = abfd->sections; o != NULL; o = o->next)
- for (p = o->map_head.link_order; p != NULL; p = p->next)
- if (p->type == bfd_indirect_link_order)
- p->u.indirect.section->linker_mark = true;
- #if 0
- /* Handle all the link order information for the sections. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- printf ("For section %s (at 0x%08x, flags=0x%08x):\n",
- o->name, (unsigned)o->vma, (unsigned)o->flags);
- for (p = o->map_head.link_order; p != NULL; p = p->next)
- {
- printf (" at 0x%08x - 0x%08x: ",
- (unsigned)p->offset, (unsigned)(p->offset + p->size - 1));
- switch (p->type)
- {
- case bfd_section_reloc_link_order:
- case bfd_symbol_reloc_link_order:
- printf (" section/symbol reloc\n");
- break;
- case bfd_indirect_link_order:
- printf (" section %s of %s\n",
- p->u.indirect.section->name,
- p->u.indirect.section->owner->filename);
- break;
- case bfd_data_link_order:
- printf (" explicit data\n");
- break;
- default:
- printf (" *unknown* type %u\n", p->type);
- break;
- }
- }
- }
- #endif
- /* Generate the symbol table. */
- BFD_ASSERT (PRIV (syms) == NULL);
- if (info->strip != strip_all)
- bfd_hash_traverse (&info->hash->table, alpha_vms_link_output_symbol, info);
- /* Find the entry point. */
- if (bfd_get_start_address (abfd) == 0)
- {
- bfd *startbfd = NULL;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- {
- /* Consider only VMS object files. */
- if (sub->xvec != abfd->xvec)
- continue;
- if (!PRIV2 (sub, eom_data).eom_has_transfer)
- continue;
- if ((PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR) && startbfd)
- continue;
- if (startbfd != NULL
- && !(PRIV2 (sub, eom_data).eom_b_tfrflg & EEOM__M_WKTFR))
- {
- (*info->callbacks->einfo)
- /* xgettext:c-format */
- (_("%P: multiple entry points: in modules %pB and %pB\n"),
- startbfd, sub);
- continue;
- }
- startbfd = sub;
- }
- if (startbfd)
- {
- unsigned int ps_idx = PRIV2 (startbfd, eom_data).eom_l_psindx;
- bfd_vma tfradr = PRIV2 (startbfd, eom_data).eom_l_tfradr;
- asection *sec;
- sec = PRIV2 (startbfd, sections)[ps_idx];
- bfd_set_start_address
- (abfd, sec->output_section->vma + sec->output_offset + tfradr);
- }
- }
- /* Set transfer addresses. */
- {
- int i;
- struct bfd_link_hash_entry *h;
- i = 0;
- PRIV (transfer_address[i++]) = 0xffffffff00000340ULL; /* SYS$IMGACT */
- h = bfd_link_hash_lookup (info->hash, "LIB$INITIALIZE", false, false, true);
- if (h != NULL && h->type == bfd_link_hash_defined)
- PRIV (transfer_address[i++]) =
- alpha_vms_get_sym_value (h->u.def.section, h->u.def.value);
- PRIV (transfer_address[i++]) = bfd_get_start_address (abfd);
- while (i < 4)
- PRIV (transfer_address[i++]) = 0;
- }
- /* Allocate contents.
- Also compute the virtual base address. */
- base_addr = (bfd_vma)-1;
- last_addr = 0;
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if (o->flags & SEC_HAS_CONTENTS)
- {
- o->contents = bfd_alloc (abfd, o->size);
- if (o->contents == NULL)
- return false;
- }
- if (o->flags & SEC_LOAD)
- {
- if (o->vma < base_addr)
- base_addr = o->vma;
- if (o->vma + o->size > last_addr)
- last_addr = o->vma + o->size;
- }
- /* Clear the RELOC flags. Currently we don't support incremental
- linking. We use the RELOC flag for computing the eicp entries. */
- o->flags &= ~SEC_RELOC;
- }
- /* Create the fixup section. */
- fixupsec = bfd_make_section_anyway_with_flags
- (info->output_bfd, "$FIXUP$",
- SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
- if (fixupsec == NULL)
- return false;
- last_addr = (last_addr + 0xffff) & ~0xffff;
- fixupsec->vma = last_addr;
- alpha_vms_link_hash (info)->fixup = fixupsec;
- alpha_vms_link_hash (info)->base_addr = base_addr;
- /* Create the DMT section, if necessary. */
- BFD_ASSERT (PRIV (dst_section) == NULL);
- dst = bfd_get_section_by_name (abfd, "$DST$");
- if (dst != NULL && dst->size == 0)
- dst = NULL;
- if (dst != NULL)
- {
- PRIV (dst_section) = dst;
- dmt = bfd_make_section_anyway_with_flags
- (info->output_bfd, "$DMT$",
- SEC_DEBUGGING | SEC_HAS_CONTENTS | SEC_LINKER_CREATED);
- if (dmt == NULL)
- return false;
- }
- else
- dmt = NULL;
- /* Read all sections from the inputs. */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- {
- if (sub->flags & DYNAMIC)
- {
- alpha_vms_create_eisd_for_shared (abfd, sub);
- continue;
- }
- if (!alpha_vms_read_sections_content (sub, info))
- return false;
- }
- /* Handle all the link order information for the sections.
- Note: past this point, it is not possible to create new sections. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- for (p = o->map_head.link_order; p != NULL; p = p->next)
- {
- switch (p->type)
- {
- case bfd_section_reloc_link_order:
- case bfd_symbol_reloc_link_order:
- abort ();
- return false;
- case bfd_indirect_link_order:
- /* Already done. */
- break;
- default:
- if (! _bfd_default_link_order (abfd, info, o, p))
- return false;
- break;
- }
- }
- }
- /* Compute fixups. */
- if (!alpha_vms_build_fixups (info))
- return false;
- /* Compute the DMT. */
- if (dmt != NULL)
- {
- int pass;
- unsigned char *contents = NULL;
- /* In pass 1, compute the size. In pass 2, write the DMT contents. */
- for (pass = 0; pass < 2; pass++)
- {
- unsigned int off = 0;
- /* For each object file (ie for each module). */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- {
- asection *sub_dst;
- struct vms_dmt_header *dmth = NULL;
- unsigned int psect_count;
- /* Skip this module if it has no DST. */
- sub_dst = PRIV2 (sub, dst_section);
- if (sub_dst == NULL || sub_dst->size == 0)
- continue;
- if (pass == 1)
- {
- /* Write the header. */
- dmth = (struct vms_dmt_header *)(contents + off);
- bfd_putl32 (sub_dst->output_offset, dmth->modbeg);
- bfd_putl32 (sub_dst->size, dmth->size);
- }
- off += sizeof (struct vms_dmt_header);
- psect_count = 0;
- /* For each section (ie for each psect). */
- for (o = sub->sections; o != NULL; o = o->next)
- {
- /* Only consider interesting sections. */
- if (!(o->flags & SEC_ALLOC))
- continue;
- if (o->flags & SEC_LINKER_CREATED)
- continue;
- if (pass == 1)
- {
- /* Write an entry. */
- struct vms_dmt_psect *dmtp;
- dmtp = (struct vms_dmt_psect *)(contents + off);
- bfd_putl32 (o->output_offset + o->output_section->vma,
- dmtp->start);
- bfd_putl32 (o->size, dmtp->length);
- psect_count++;
- }
- off += sizeof (struct vms_dmt_psect);
- }
- if (pass == 1)
- bfd_putl32 (psect_count, dmth->psect_count);
- }
- if (pass == 0)
- {
- contents = bfd_zalloc (info->output_bfd, off);
- if (contents == NULL)
- return false;
- dmt->contents = contents;
- dmt->size = off;
- }
- else
- {
- BFD_ASSERT (off == dmt->size);
- }
- }
- }
- return true;
- }
- /* Read the contents of a section.
- buf points to a buffer of buf_size bytes to be filled with
- section data (starting at offset into section) */
- static bool
- alpha_vms_get_section_contents (bfd *abfd, asection *section,
- void *buf, file_ptr offset,
- bfd_size_type count)
- {
- asection *sec;
- /* Image are easy. */
- if (bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC))
- return _bfd_generic_get_section_contents (abfd, section,
- buf, offset, count);
- /* Safety check. */
- if (offset + count < count
- || offset + count > section->size)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return false;
- }
- /* If the section is already in memory, just copy it. */
- if (section->flags & SEC_IN_MEMORY)
- {
- BFD_ASSERT (section->contents != NULL);
- memcpy (buf, section->contents + offset, count);
- return true;
- }
- if (section->size == 0)
- return true;
- /* Alloc in memory and read ETIRs. */
- for (sec = abfd->sections; sec; sec = sec->next)
- {
- BFD_ASSERT (sec->contents == NULL);
- if (sec->size != 0 && (sec->flags & SEC_HAS_CONTENTS))
- {
- sec->contents = bfd_alloc (abfd, sec->size);
- if (sec->contents == NULL)
- return false;
- }
- }
- if (!alpha_vms_read_sections_content (abfd, NULL))
- return false;
- for (sec = abfd->sections; sec; sec = sec->next)
- if (sec->contents)
- sec->flags |= SEC_IN_MEMORY;
- memcpy (buf, section->contents + offset, count);
- return true;
- }
- /* Set the format of a file being written. */
- static bool
- alpha_vms_mkobject (bfd * abfd)
- {
- const bfd_arch_info_type *arch;
- vms_debug2 ((1, "alpha_vms_mkobject (%p)\n", abfd));
- if (!vms_initialize (abfd))
- return false;
- PRIV (recwr.buf) = bfd_alloc (abfd, MAX_OUTREC_SIZE);
- if (PRIV (recwr.buf) == NULL)
- return false;
- arch = bfd_scan_arch ("alpha");
- if (arch == 0)
- {
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
- abfd->arch_info = arch;
- return true;
- }
- /* 4.1, generic. */
- /* Called when the BFD is being closed to do any necessary cleanup. */
- static bool
- vms_close_and_cleanup (bfd * abfd)
- {
- vms_debug2 ((1, "vms_close_and_cleanup (%p)\n", abfd));
- if (abfd == NULL || abfd->tdata.any == NULL)
- return true;
- if (abfd->format == bfd_object)
- {
- alpha_vms_free_private (abfd);
- #ifdef VMS
- if (abfd->direction == write_direction)
- {
- /* Last step on VMS is to convert the file to variable record length
- format. */
- if (!bfd_cache_close (abfd))
- return false;
- if (!_bfd_vms_convert_to_var_unix_filename (abfd->filename))
- return false;
- }
- #endif
- }
- return _bfd_generic_close_and_cleanup (abfd);
- }
- /* Called when a new section is created. */
- static bool
- vms_new_section_hook (bfd * abfd, asection *section)
- {
- size_t amt;
- vms_debug2 ((1, "vms_new_section_hook (%p, [%u]%s)\n",
- abfd, section->index, section->name));
- if (!bfd_set_section_alignment (section, 0))
- return false;
- vms_debug2 ((7, "%u: %s\n", section->index, section->name));
- amt = sizeof (struct vms_section_data_struct);
- section->used_by_bfd = bfd_zalloc (abfd, amt);
- if (section->used_by_bfd == NULL)
- return false;
- /* Create the section symbol. */
- return _bfd_generic_new_section_hook (abfd, section);
- }
- /* Part 4.5, symbols. */
- /* Print symbol to file according to how. how is one of
- bfd_print_symbol_name just print the name
- bfd_print_symbol_more print more (???)
- bfd_print_symbol_all print all we know, which is not much right now :-). */
- static void
- vms_print_symbol (bfd * abfd,
- void * file,
- asymbol *symbol,
- bfd_print_symbol_type how)
- {
- vms_debug2 ((1, "vms_print_symbol (%p, %p, %p, %d)\n",
- abfd, file, symbol, how));
- switch (how)
- {
- case bfd_print_symbol_name:
- case bfd_print_symbol_more:
- fprintf ((FILE *)file," %s", symbol->name);
- break;
- case bfd_print_symbol_all:
- {
- const char *section_name = symbol->section->name;
- bfd_print_symbol_vandf (abfd, file, symbol);
- fprintf ((FILE *) file," %-8s %s", section_name, symbol->name);
- }
- break;
- }
- }
- /* Return information about symbol in ret.
- fill type, value and name
- type:
- A absolute
- B bss segment symbol
- C common symbol
- D data segment symbol
- f filename
- t a static function symbol
- T text segment symbol
- U undefined
- - debug. */
- static void
- vms_get_symbol_info (bfd * abfd ATTRIBUTE_UNUSED,
- asymbol *symbol,
- symbol_info *ret)
- {
- asection *sec;
- vms_debug2 ((1, "vms_get_symbol_info (%p, %p, %p)\n", abfd, symbol, ret));
- sec = symbol->section;
- if (ret == NULL)
- return;
- if (sec == NULL)
- ret->type = 'U';
- else if (bfd_is_com_section (sec))
- ret->type = 'C';
- else if (bfd_is_abs_section (sec))
- ret->type = 'A';
- else if (bfd_is_und_section (sec))
- ret->type = 'U';
- else if (bfd_is_ind_section (sec))
- ret->type = 'I';
- else if ((symbol->flags & BSF_FUNCTION)
- || (bfd_section_flags (sec) & SEC_CODE))
- ret->type = 'T';
- else if (bfd_section_flags (sec) & SEC_DATA)
- ret->type = 'D';
- else if (bfd_section_flags (sec) & SEC_ALLOC)
- ret->type = 'B';
- else
- ret->type = '?';
- if (ret->type != 'U')
- ret->value = symbol->value + symbol->section->vma;
- else
- ret->value = 0;
- ret->name = symbol->name;
- }
- /* Return TRUE if the given symbol sym in the BFD abfd is
- a compiler generated local label, else return FALSE. */
- static bool
- vms_bfd_is_local_label_name (bfd * abfd ATTRIBUTE_UNUSED,
- const char *name)
- {
- return name[0] == '$';
- }
- /* Part 4.7, writing an object file. */
- /* Sets the contents of the section section in BFD abfd to the data starting
- in memory at LOCATION. The data is written to the output section starting
- at offset offset for count bytes.
- Normally TRUE is returned, else FALSE. Possible error returns are:
- o bfd_error_no_contents - The output section does not have the
- SEC_HAS_CONTENTS attribute, so nothing can be written to it.
- o and some more too */
- static bool
- _bfd_vms_set_section_contents (bfd * abfd,
- asection *section,
- const void * location,
- file_ptr offset,
- bfd_size_type count)
- {
- if (section->contents == NULL)
- {
- section->contents = bfd_alloc (abfd, section->size);
- if (section->contents == NULL)
- return false;
- memcpy (section->contents + offset, location, (size_t) count);
- }
- return true;
- }
- /* Set the architecture and machine type in BFD abfd to arch and mach.
- Find the correct pointer to a structure and insert it into the arch_info
- pointer. */
- static bool
- alpha_vms_set_arch_mach (bfd *abfd,
- enum bfd_architecture arch, unsigned long mach)
- {
- if (arch != bfd_arch_alpha
- && arch != bfd_arch_unknown)
- return false;
- return bfd_default_set_arch_mach (abfd, arch, mach);
- }
- /* Set section VMS flags. Clear NO_FLAGS and set FLAGS. */
- void
- bfd_vms_set_section_flags (bfd *abfd ATTRIBUTE_UNUSED,
- asection *sec, flagword no_flags, flagword flags)
- {
- vms_section_data (sec)->no_flags = no_flags;
- vms_section_data (sec)->flags = flags;
- }
- struct vms_private_data_struct *
- bfd_vms_get_data (bfd *abfd)
- {
- return (struct vms_private_data_struct *)abfd->tdata.any;
- }
- #define vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
- #define vms_bfd_link_just_syms _bfd_generic_link_just_syms
- #define vms_bfd_copy_link_hash_symbol_type \
- _bfd_generic_copy_link_hash_symbol_type
- #define vms_bfd_is_group_section bfd_generic_is_group_section
- #define vms_bfd_group_name bfd_generic_group_name
- #define vms_bfd_discard_group bfd_generic_discard_group
- #define vms_section_already_linked _bfd_generic_section_already_linked
- #define vms_bfd_define_common_symbol bfd_generic_define_common_symbol
- #define vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
- #define vms_bfd_define_start_stop bfd_generic_define_start_stop
- #define vms_bfd_copy_private_header_data _bfd_generic_bfd_copy_private_header_data
- #define vms_bfd_copy_private_bfd_data _bfd_generic_bfd_copy_private_bfd_data
- #define vms_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
- #define vms_bfd_copy_private_section_data _bfd_generic_bfd_copy_private_section_data
- #define vms_bfd_copy_private_symbol_data _bfd_generic_bfd_copy_private_symbol_data
- #define vms_bfd_set_private_flags _bfd_generic_bfd_set_private_flags
- #define vms_bfd_merge_private_bfd_data _bfd_generic_bfd_merge_private_bfd_data
- /* Symbols table. */
- #define alpha_vms_make_empty_symbol _bfd_generic_make_empty_symbol
- #define alpha_vms_bfd_is_target_special_symbol _bfd_bool_bfd_asymbol_false
- #define alpha_vms_print_symbol vms_print_symbol
- #define alpha_vms_get_symbol_info vms_get_symbol_info
- #define alpha_vms_get_symbol_version_string \
- _bfd_nosymbols_get_symbol_version_string
- #define alpha_vms_read_minisymbols _bfd_generic_read_minisymbols
- #define alpha_vms_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
- #define alpha_vms_get_lineno _bfd_nosymbols_get_lineno
- #define alpha_vms_find_inliner_info _bfd_nosymbols_find_inliner_info
- #define alpha_vms_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
- #define alpha_vms_find_nearest_line _bfd_vms_find_nearest_line
- #define alpha_vms_find_line _bfd_nosymbols_find_line
- #define alpha_vms_bfd_is_local_label_name vms_bfd_is_local_label_name
- /* Generic table. */
- #define alpha_vms_close_and_cleanup vms_close_and_cleanup
- #define alpha_vms_bfd_free_cached_info vms_bfd_free_cached_info
- #define alpha_vms_new_section_hook vms_new_section_hook
- #define alpha_vms_set_section_contents _bfd_vms_set_section_contents
- #define alpha_vms_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
- #define alpha_vms_bfd_get_relocated_section_contents \
- bfd_generic_get_relocated_section_contents
- #define alpha_vms_bfd_relax_section bfd_generic_relax_section
- #define alpha_vms_bfd_gc_sections bfd_generic_gc_sections
- #define alpha_vms_bfd_lookup_section_flags bfd_generic_lookup_section_flags
- #define alpha_vms_bfd_merge_sections bfd_generic_merge_sections
- #define alpha_vms_bfd_is_group_section bfd_generic_is_group_section
- #define alpha_vms_bfd_group_name bfd_generic_group_name
- #define alpha_vms_bfd_discard_group bfd_generic_discard_group
- #define alpha_vms_section_already_linked \
- _bfd_generic_section_already_linked
- #define alpha_vms_bfd_define_common_symbol bfd_generic_define_common_symbol
- #define alpha_vms_bfd_link_hide_symbol _bfd_generic_link_hide_symbol
- #define alpha_vms_bfd_define_start_stop bfd_generic_define_start_stop
- #define alpha_vms_bfd_link_just_syms _bfd_generic_link_just_syms
- #define alpha_vms_bfd_copy_link_hash_symbol_type \
- _bfd_generic_copy_link_hash_symbol_type
- #define alpha_vms_bfd_link_split_section _bfd_generic_link_split_section
- #define alpha_vms_get_dynamic_symtab_upper_bound \
- _bfd_nodynamic_get_dynamic_symtab_upper_bound
- #define alpha_vms_canonicalize_dynamic_symtab \
- _bfd_nodynamic_canonicalize_dynamic_symtab
- #define alpha_vms_get_dynamic_reloc_upper_bound \
- _bfd_nodynamic_get_dynamic_reloc_upper_bound
- #define alpha_vms_canonicalize_dynamic_reloc \
- _bfd_nodynamic_canonicalize_dynamic_reloc
- #define alpha_vms_bfd_link_check_relocs _bfd_generic_link_check_relocs
- const bfd_target alpha_vms_vec =
- {
- "vms-alpha", /* Name. */
- bfd_target_evax_flavour,
- BFD_ENDIAN_LITTLE, /* Data byte order is little. */
- BFD_ENDIAN_LITTLE, /* Header byte order is little. */
- (HAS_RELOC | EXEC_P | HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS
- | WP_TEXT | D_PAGED), /* Object flags. */
- (SEC_ALLOC | SEC_LOAD | SEC_RELOC
- | SEC_READONLY | SEC_CODE | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_IN_MEMORY), /* Sect flags. */
- 0, /* symbol_leading_char. */
- ' ', /* ar_pad_char. */
- 15, /* ar_max_namelen. */
- 0, /* match priority. */
- TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols. */
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16,
- bfd_getl64, bfd_getl_signed_64, bfd_putl64,
- bfd_getl32, bfd_getl_signed_32, bfd_putl32,
- bfd_getl16, bfd_getl_signed_16, bfd_putl16,
- { /* bfd_check_format. */
- _bfd_dummy_target,
- alpha_vms_object_p,
- _bfd_vms_lib_alpha_archive_p,
- _bfd_dummy_target
- },
- { /* bfd_set_format. */
- _bfd_bool_bfd_false_error,
- alpha_vms_mkobject,
- _bfd_vms_lib_alpha_mkarchive,
- _bfd_bool_bfd_false_error
- },
- { /* bfd_write_contents. */
- _bfd_bool_bfd_false_error,
- alpha_vms_write_object_contents,
- _bfd_vms_lib_write_archive_contents,
- _bfd_bool_bfd_false_error
- },
- BFD_JUMP_TABLE_GENERIC (alpha_vms),
- BFD_JUMP_TABLE_COPY (vms),
- BFD_JUMP_TABLE_CORE (_bfd_nocore),
- BFD_JUMP_TABLE_ARCHIVE (_bfd_vms_lib),
- BFD_JUMP_TABLE_SYMBOLS (alpha_vms),
- BFD_JUMP_TABLE_RELOCS (alpha_vms),
- BFD_JUMP_TABLE_WRITE (alpha_vms),
- BFD_JUMP_TABLE_LINK (alpha_vms),
- BFD_JUMP_TABLE_DYNAMIC (alpha_vms),
- NULL,
- NULL
- };
|