123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685 |
- /* BFD semi-generic back-end for a.out binaries.
- Copyright (C) 1990-2022 Free Software Foundation, Inc.
- Written by Cygnus Support.
- This file is part of BFD, the Binary File Descriptor library.
- 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. */
- /*
- SECTION
- a.out backends
- DESCRIPTION
- BFD supports a number of different flavours of a.out format,
- though the major differences are only the sizes of the
- structures on disk, and the shape of the relocation
- information.
- The support is split into a basic support file @file{aoutx.h}
- and other files which derive functions from the base. One
- derivation file is @file{aoutf1.h} (for a.out flavour 1), and
- adds to the basic a.out functions support for sun3, sun4, and
- 386 a.out files, to create a target jump vector for a specific
- target.
- This information is further split out into more specific files
- for each machine, including @file{sunos.c} for sun3 and sun4,
- and @file{demo64.c} for a demonstration of a 64 bit a.out format.
- The base file @file{aoutx.h} defines general mechanisms for
- reading and writing records to and from disk and various
- other methods which BFD requires. It is included by
- @file{aout32.c} and @file{aout64.c} to form the names
- <<aout_32_swap_exec_header_in>>, <<aout_64_swap_exec_header_in>>, etc.
- As an example, this is what goes on to make the back end for a
- sun4, from @file{aout32.c}:
- | #define ARCH_SIZE 32
- | #include "aoutx.h"
- Which exports names:
- | ...
- | aout_32_canonicalize_reloc
- | aout_32_find_nearest_line
- | aout_32_get_lineno
- | aout_32_get_reloc_upper_bound
- | ...
- from @file{sunos.c}:
- | #define TARGET_NAME "a.out-sunos-big"
- | #define VECNAME sparc_aout_sunos_be_vec
- | #include "aoutf1.h"
- requires all the names from @file{aout32.c}, and produces the jump vector
- | sparc_aout_sunos_be_vec
- The file @file{host-aout.c} is a special case. It is for a large set
- of hosts that use ``more or less standard'' a.out files, and
- for which cross-debugging is not interesting. It uses the
- standard 32-bit a.out support routines, but determines the
- file offsets and addresses of the text, data, and BSS
- sections, the machine architecture and machine type, and the
- entry point address, in a host-dependent manner. Once these
- values have been determined, generic code is used to handle
- the object file.
- When porting it to run on a new system, you must supply:
- | HOST_PAGE_SIZE
- | HOST_SEGMENT_SIZE
- | HOST_MACHINE_ARCH (optional)
- | HOST_MACHINE_MACHINE (optional)
- | HOST_TEXT_START_ADDR
- | HOST_STACK_END_ADDR
- in the file @file{../include/sys/h-@var{XXX}.h} (for your host). These
- values, plus the structures and macros defined in @file{a.out.h} on
- your host system, will produce a BFD target that will access
- ordinary a.out files on your host. To configure a new machine
- to use @file{host-aout.c}, specify:
- | TDEFAULTS = -DDEFAULT_VECTOR=host_aout_big_vec
- | TDEPFILES= host-aout.o trad-core.o
- in the @file{config/@var{XXX}.mt} file, and modify @file{configure.ac}
- to use the
- @file{@var{XXX}.mt} file (by setting "<<bfd_target=XXX>>") when your
- configuration is selected. */
- /* Some assumptions:
- * Any BFD with D_PAGED set is ZMAGIC, and vice versa.
- Doesn't matter what the setting of WP_TEXT is on output, but it'll
- get set on input.
- * Any BFD with D_PAGED clear and WP_TEXT set is NMAGIC.
- * Any BFD with both flags clear is OMAGIC.
- (Just want to make these explicit, so the conditions tested in this
- file make sense if you're more familiar with a.out than with BFD.) */
- #define KEEPIT udata.i
- #include "sysdep.h"
- #include <limits.h>
- #include "bfd.h"
- #include "safe-ctype.h"
- #include "bfdlink.h"
- #include "libaout.h"
- #include "libbfd.h"
- #include "aout/aout64.h"
- #include "aout/stab_gnu.h"
- #include "aout/ar.h"
- #ifdef BMAGIC
- #define N_IS_BMAGIC(x) (N_MAGIC (x) == BMAGIC)
- #else
- #define N_IS_BMAGIC(x) (0)
- #endif
- #ifdef QMAGIC
- #define N_SET_QMAGIC(x) N_SET_MAGIC (x, QMAGIC)
- #else
- #define N_SET_QMAGIC(x) do { /**/ } while (0)
- #endif
- /*
- SUBSECTION
- Relocations
- DESCRIPTION
- The file @file{aoutx.h} provides for both the @emph{standard}
- and @emph{extended} forms of a.out relocation records.
- The standard records contain only an address, a symbol index,
- and a type field. The extended records also have a full
- integer for an addend. */
- #ifndef CTOR_TABLE_RELOC_HOWTO
- #define CTOR_TABLE_RELOC_IDX 2
- #define CTOR_TABLE_RELOC_HOWTO(BFD) \
- ((obj_reloc_entry_size (BFD) == RELOC_EXT_SIZE \
- ? howto_table_ext : howto_table_std) \
- + CTOR_TABLE_RELOC_IDX)
- #endif
- #ifndef MY_swap_std_reloc_in
- #define MY_swap_std_reloc_in NAME (aout, swap_std_reloc_in)
- #endif
- #ifndef MY_swap_ext_reloc_in
- #define MY_swap_ext_reloc_in NAME (aout, swap_ext_reloc_in)
- #endif
- #ifndef MY_swap_std_reloc_out
- #define MY_swap_std_reloc_out NAME (aout, swap_std_reloc_out)
- #endif
- #ifndef MY_swap_ext_reloc_out
- #define MY_swap_ext_reloc_out NAME (aout, swap_ext_reloc_out)
- #endif
- #ifndef MY_final_link_relocate
- #define MY_final_link_relocate _bfd_final_link_relocate
- #endif
- #ifndef MY_relocate_contents
- #define MY_relocate_contents _bfd_relocate_contents
- #endif
- #define howto_table_ext NAME (aout, ext_howto_table)
- #define howto_table_std NAME (aout, std_howto_table)
- reloc_howto_type howto_table_ext[] =
- {
- /* Type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone. */
- HOWTO (RELOC_8, 0, 0, 8, false, 0, complain_overflow_bitfield, 0, "8", false, 0, 0x000000ff, false),
- HOWTO (RELOC_16, 0, 1, 16, false, 0, complain_overflow_bitfield, 0, "16", false, 0, 0x0000ffff, false),
- HOWTO (RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, 0, "32", false, 0, 0xffffffff, false),
- HOWTO (RELOC_DISP8, 0, 0, 8, true, 0, complain_overflow_signed, 0, "DISP8", false, 0, 0x000000ff, false),
- HOWTO (RELOC_DISP16, 0, 1, 16, true, 0, complain_overflow_signed, 0, "DISP16", false, 0, 0x0000ffff, false),
- HOWTO (RELOC_DISP32, 0, 2, 32, true, 0, complain_overflow_signed, 0, "DISP32", false, 0, 0xffffffff, false),
- HOWTO (RELOC_WDISP30, 2, 2, 30, true, 0, complain_overflow_signed, 0, "WDISP30", false, 0, 0x3fffffff, false),
- HOWTO (RELOC_WDISP22, 2, 2, 22, true, 0, complain_overflow_signed, 0, "WDISP22", false, 0, 0x003fffff, false),
- HOWTO (RELOC_HI22, 10, 2, 22, false, 0, complain_overflow_bitfield, 0, "HI22", false, 0, 0x003fffff, false),
- HOWTO (RELOC_22, 0, 2, 22, false, 0, complain_overflow_bitfield, 0, "22", false, 0, 0x003fffff, false),
- HOWTO (RELOC_13, 0, 2, 13, false, 0, complain_overflow_bitfield, 0, "13", false, 0, 0x00001fff, false),
- HOWTO (RELOC_LO10, 0, 2, 10, false, 0, complain_overflow_dont, 0, "LO10", false, 0, 0x000003ff, false),
- HOWTO (RELOC_SFA_BASE,0, 2, 32, false, 0, complain_overflow_bitfield, 0, "SFA_BASE", false, 0, 0xffffffff, false),
- HOWTO (RELOC_SFA_OFF13,0, 2, 32, false, 0, complain_overflow_bitfield, 0, "SFA_OFF13", false, 0, 0xffffffff, false),
- HOWTO (RELOC_BASE10, 0, 2, 10, false, 0, complain_overflow_dont, 0, "BASE10", false, 0, 0x000003ff, false),
- HOWTO (RELOC_BASE13, 0, 2, 13, false, 0, complain_overflow_signed, 0, "BASE13", false, 0, 0x00001fff, false),
- HOWTO (RELOC_BASE22, 10, 2, 22, false, 0, complain_overflow_bitfield, 0, "BASE22", false, 0, 0x003fffff, false),
- HOWTO (RELOC_PC10, 0, 2, 10, true, 0, complain_overflow_dont, 0, "PC10", false, 0, 0x000003ff, true),
- HOWTO (RELOC_PC22, 10, 2, 22, true, 0, complain_overflow_signed, 0, "PC22", false, 0, 0x003fffff, true),
- HOWTO (RELOC_JMP_TBL, 2, 2, 30, true, 0, complain_overflow_signed, 0, "JMP_TBL", false, 0, 0x3fffffff, false),
- HOWTO (RELOC_SEGOFF16,0, 2, 0, false, 0, complain_overflow_bitfield, 0, "SEGOFF16", false, 0, 0x00000000, false),
- HOWTO (RELOC_GLOB_DAT,0, 2, 0, false, 0, complain_overflow_bitfield, 0, "GLOB_DAT", false, 0, 0x00000000, false),
- HOWTO (RELOC_JMP_SLOT,0, 2, 0, false, 0, complain_overflow_bitfield, 0, "JMP_SLOT", false, 0, 0x00000000, false),
- HOWTO (RELOC_RELATIVE,0, 2, 0, false, 0, complain_overflow_bitfield, 0, "RELATIVE", false, 0, 0x00000000, false),
- HOWTO (0, 0, 3, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE",false, 0, 0x00000000, true),
- HOWTO (0, 0, 3, 0, false, 0, complain_overflow_dont, 0, "R_SPARC_NONE",false, 0, 0x00000000, true),
- #define RELOC_SPARC_REV32 RELOC_WDISP19
- HOWTO (RELOC_SPARC_REV32, 0, 2, 32, false, 0, complain_overflow_dont, 0,"R_SPARC_REV32",false, 0, 0xffffffff, false),
- };
- /* Convert standard reloc records to "arelent" format (incl byte swap). */
- reloc_howto_type howto_table_std[] =
- {
- /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone. */
- HOWTO ( 0, 0, 0, 8, false, 0, complain_overflow_bitfield,0,"8", true, 0x000000ff,0x000000ff, false),
- HOWTO ( 1, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"16", true, 0x0000ffff,0x0000ffff, false),
- HOWTO ( 2, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"32", true, 0xffffffff,0xffffffff, false),
- HOWTO ( 3, 0, 4, 64, false, 0, complain_overflow_bitfield,0,"64", true, 0xdeaddead,0xdeaddead, false),
- HOWTO ( 4, 0, 0, 8, true, 0, complain_overflow_signed, 0,"DISP8", true, 0x000000ff,0x000000ff, false),
- HOWTO ( 5, 0, 1, 16, true, 0, complain_overflow_signed, 0,"DISP16", true, 0x0000ffff,0x0000ffff, false),
- HOWTO ( 6, 0, 2, 32, true, 0, complain_overflow_signed, 0,"DISP32", true, 0xffffffff,0xffffffff, false),
- HOWTO ( 7, 0, 4, 64, true, 0, complain_overflow_signed, 0,"DISP64", true, 0xfeedface,0xfeedface, false),
- HOWTO ( 8, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"GOT_REL", false, 0,0x00000000, false),
- HOWTO ( 9, 0, 1, 16, false, 0, complain_overflow_bitfield,0,"BASE16", false,0xffffffff,0xffffffff, false),
- HOWTO (10, 0, 2, 32, false, 0, complain_overflow_bitfield,0,"BASE32", false,0xffffffff,0xffffffff, false),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- HOWTO (16, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"JMP_TABLE", false, 0,0x00000000, false),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- HOWTO (32, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"RELATIVE", false, 0,0x00000000, false),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- EMPTY_HOWTO (-1),
- HOWTO (40, 0, 2, 0, false, 0, complain_overflow_bitfield,0,"BASEREL", false, 0,0x00000000, false),
- };
- #define TABLE_SIZE(TABLE) (sizeof (TABLE) / sizeof (TABLE[0]))
- reloc_howto_type *
- NAME (aout, reloc_type_lookup) (bfd *abfd, bfd_reloc_code_real_type code)
- {
- #define EXT(i, j) case i: return & howto_table_ext [j]
- #define STD(i, j) case i: return & howto_table_std [j]
- int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
- if (code == BFD_RELOC_CTOR)
- switch (bfd_arch_bits_per_address (abfd))
- {
- case 32:
- code = BFD_RELOC_32;
- break;
- case 64:
- code = BFD_RELOC_64;
- break;
- }
- if (ext)
- switch (code)
- {
- EXT (BFD_RELOC_8, 0);
- EXT (BFD_RELOC_16, 1);
- EXT (BFD_RELOC_32, 2);
- EXT (BFD_RELOC_HI22, 8);
- EXT (BFD_RELOC_LO10, 11);
- EXT (BFD_RELOC_32_PCREL_S2, 6);
- EXT (BFD_RELOC_SPARC_WDISP22, 7);
- EXT (BFD_RELOC_SPARC13, 10);
- EXT (BFD_RELOC_SPARC_GOT10, 14);
- EXT (BFD_RELOC_SPARC_BASE13, 15);
- EXT (BFD_RELOC_SPARC_GOT13, 15);
- EXT (BFD_RELOC_SPARC_GOT22, 16);
- EXT (BFD_RELOC_SPARC_PC10, 17);
- EXT (BFD_RELOC_SPARC_PC22, 18);
- EXT (BFD_RELOC_SPARC_WPLT30, 19);
- EXT (BFD_RELOC_SPARC_REV32, 26);
- default:
- return NULL;
- }
- else
- /* std relocs. */
- switch (code)
- {
- STD (BFD_RELOC_8, 0);
- STD (BFD_RELOC_16, 1);
- STD (BFD_RELOC_32, 2);
- STD (BFD_RELOC_8_PCREL, 4);
- STD (BFD_RELOC_16_PCREL, 5);
- STD (BFD_RELOC_32_PCREL, 6);
- STD (BFD_RELOC_16_BASEREL, 9);
- STD (BFD_RELOC_32_BASEREL, 10);
- default:
- return NULL;
- }
- }
- reloc_howto_type *
- NAME (aout, reloc_name_lookup) (bfd *abfd, const char *r_name)
- {
- unsigned int i, size;
- reloc_howto_type *howto_table;
- if (obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE)
- {
- howto_table = howto_table_ext;
- size = sizeof (howto_table_ext) / sizeof (howto_table_ext[0]);
- }
- else
- {
- howto_table = howto_table_std;
- size = sizeof (howto_table_std) / sizeof (howto_table_std[0]);
- }
- for (i = 0; i < size; i++)
- if (howto_table[i].name != NULL
- && strcasecmp (howto_table[i].name, r_name) == 0)
- return &howto_table[i];
- return NULL;
- }
- /*
- SUBSECTION
- Internal entry points
- DESCRIPTION
- @file{aoutx.h} exports several routines for accessing the
- contents of an a.out file, which are gathered and exported in
- turn by various format specific files (eg sunos.c).
- */
- /*
- FUNCTION
- aout_@var{size}_swap_exec_header_in
- SYNOPSIS
- void aout_@var{size}_swap_exec_header_in,
- (bfd *abfd,
- struct external_exec *bytes,
- struct internal_exec *execp);
- DESCRIPTION
- Swap the information in an executable header @var{raw_bytes} taken
- from a raw byte stream memory image into the internal exec header
- structure @var{execp}.
- */
- #ifndef NAME_swap_exec_header_in
- void
- NAME (aout, swap_exec_header_in) (bfd *abfd,
- struct external_exec *bytes,
- struct internal_exec *execp)
- {
- /* The internal_exec structure has some fields that are unused in this
- configuration (IE for i960), so ensure that all such uninitialized
- fields are zero'd out. There are places where two of these structs
- are memcmp'd, and thus the contents do matter. */
- memset ((void *) execp, 0, sizeof (struct internal_exec));
- /* Now fill in fields in the execp, from the bytes in the raw data. */
- execp->a_info = H_GET_32 (abfd, bytes->e_info);
- execp->a_text = GET_WORD (abfd, bytes->e_text);
- execp->a_data = GET_WORD (abfd, bytes->e_data);
- execp->a_bss = GET_WORD (abfd, bytes->e_bss);
- execp->a_syms = GET_WORD (abfd, bytes->e_syms);
- execp->a_entry = GET_WORD (abfd, bytes->e_entry);
- execp->a_trsize = GET_WORD (abfd, bytes->e_trsize);
- execp->a_drsize = GET_WORD (abfd, bytes->e_drsize);
- }
- #define NAME_swap_exec_header_in NAME (aout, swap_exec_header_in)
- #endif
- /*
- FUNCTION
- aout_@var{size}_swap_exec_header_out
- SYNOPSIS
- void aout_@var{size}_swap_exec_header_out
- (bfd *abfd,
- struct internal_exec *execp,
- struct external_exec *raw_bytes);
- DESCRIPTION
- Swap the information in an internal exec header structure
- @var{execp} into the buffer @var{raw_bytes} ready for writing to disk.
- */
- void
- NAME (aout, swap_exec_header_out) (bfd *abfd,
- struct internal_exec *execp,
- struct external_exec *bytes)
- {
- /* Now fill in fields in the raw data, from the fields in the exec struct. */
- H_PUT_32 (abfd, execp->a_info , bytes->e_info);
- PUT_WORD (abfd, execp->a_text , bytes->e_text);
- PUT_WORD (abfd, execp->a_data , bytes->e_data);
- PUT_WORD (abfd, execp->a_bss , bytes->e_bss);
- PUT_WORD (abfd, execp->a_syms , bytes->e_syms);
- PUT_WORD (abfd, execp->a_entry , bytes->e_entry);
- PUT_WORD (abfd, execp->a_trsize, bytes->e_trsize);
- PUT_WORD (abfd, execp->a_drsize, bytes->e_drsize);
- }
- /* Make all the section for an a.out file. */
- bool
- NAME (aout, make_sections) (bfd *abfd)
- {
- if (obj_textsec (abfd) == NULL && bfd_make_section (abfd, ".text") == NULL)
- return false;
- if (obj_datasec (abfd) == NULL && bfd_make_section (abfd, ".data") == NULL)
- return false;
- if (obj_bsssec (abfd) == NULL && bfd_make_section (abfd, ".bss") == NULL)
- return false;
- return true;
- }
- /*
- FUNCTION
- aout_@var{size}_some_aout_object_p
- SYNOPSIS
- const bfd_target *aout_@var{size}_some_aout_object_p
- (bfd *abfd,
- struct internal_exec *execp,
- const bfd_target *(*callback_to_real_object_p) (bfd *));
- DESCRIPTION
- Some a.out variant thinks that the file open in @var{abfd}
- checking is an a.out file. Do some more checking, and set up
- for access if it really is. Call back to the calling
- environment's "finish up" function just before returning, to
- handle any last-minute setup.
- */
- bfd_cleanup
- NAME (aout, some_aout_object_p) (bfd *abfd,
- struct internal_exec *execp,
- bfd_cleanup (*callback_to_real_object_p) (bfd *))
- {
- struct aout_data_struct *rawptr, *oldrawptr;
- bfd_cleanup result;
- size_t amt = sizeof (* rawptr);
- rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
- if (rawptr == NULL)
- return NULL;
- oldrawptr = abfd->tdata.aout_data;
- abfd->tdata.aout_data = rawptr;
- /* Copy the contents of the old tdata struct. */
- if (oldrawptr != NULL)
- *abfd->tdata.aout_data = *oldrawptr;
- abfd->tdata.aout_data->a.hdr = &rawptr->e;
- /* Copy in the internal_exec struct. */
- *(abfd->tdata.aout_data->a.hdr) = *execp;
- execp = abfd->tdata.aout_data->a.hdr;
- /* Set the file flags. */
- abfd->flags = BFD_NO_FLAGS;
- if (execp->a_drsize || execp->a_trsize)
- abfd->flags |= HAS_RELOC;
- /* Setting of EXEC_P has been deferred to the bottom of this function. */
- if (execp->a_syms)
- abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS;
- if (N_DYNAMIC (execp))
- abfd->flags |= DYNAMIC;
- if (N_MAGIC (execp) == ZMAGIC)
- {
- abfd->flags |= D_PAGED | WP_TEXT;
- adata (abfd).magic = z_magic;
- }
- else if (N_IS_QMAGIC (execp))
- {
- abfd->flags |= D_PAGED | WP_TEXT;
- adata (abfd).magic = z_magic;
- adata (abfd).subformat = q_magic_format;
- }
- else if (N_MAGIC (execp) == NMAGIC)
- {
- abfd->flags |= WP_TEXT;
- adata (abfd).magic = n_magic;
- }
- else if (N_MAGIC (execp) == OMAGIC || N_IS_BMAGIC (execp))
- adata (abfd).magic = o_magic;
- else
- /* Should have been checked with N_BADMAG before this routine
- was called. */
- abort ();
- abfd->start_address = execp->a_entry;
- obj_aout_symbols (abfd) = NULL;
- abfd->symcount = execp->a_syms / sizeof (struct external_nlist);
- /* The default relocation entry size is that of traditional V7 Unix. */
- obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
- /* The default symbol entry size is that of traditional Unix. */
- obj_symbol_entry_size (abfd) = EXTERNAL_NLIST_SIZE;
- #ifdef USE_MMAP
- bfd_init_window (&obj_aout_sym_window (abfd));
- bfd_init_window (&obj_aout_string_window (abfd));
- #endif
- obj_aout_external_syms (abfd) = NULL;
- obj_aout_external_strings (abfd) = NULL;
- obj_aout_sym_hashes (abfd) = NULL;
- if (! NAME (aout, make_sections) (abfd))
- goto error_ret;
- obj_datasec (abfd)->size = execp->a_data;
- obj_bsssec (abfd)->size = execp->a_bss;
- obj_textsec (abfd)->flags =
- (execp->a_trsize != 0
- ? (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS | SEC_RELOC)
- : (SEC_ALLOC | SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS));
- obj_datasec (abfd)->flags =
- (execp->a_drsize != 0
- ? (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS | SEC_RELOC)
- : (SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_HAS_CONTENTS));
- obj_bsssec (abfd)->flags = SEC_ALLOC;
- #ifdef THIS_IS_ONLY_DOCUMENTATION
- /* The common code can't fill in these things because they depend
- on either the start address of the text segment, the rounding
- up of virtual addresses between segments, or the starting file
- position of the text segment -- all of which varies among different
- versions of a.out. */
- /* Call back to the format-dependent code to fill in the rest of the
- fields and do any further cleanup. Things that should be filled
- in by the callback: */
- struct exec *execp = exec_hdr (abfd);
- obj_textsec (abfd)->size = N_TXTSIZE (execp);
- /* Data and bss are already filled in since they're so standard. */
- /* The virtual memory addresses of the sections. */
- obj_textsec (abfd)->vma = N_TXTADDR (execp);
- obj_datasec (abfd)->vma = N_DATADDR (execp);
- obj_bsssec (abfd)->vma = N_BSSADDR (execp);
- /* The file offsets of the sections. */
- obj_textsec (abfd)->filepos = N_TXTOFF (execp);
- obj_datasec (abfd)->filepos = N_DATOFF (execp);
- /* The file offsets of the relocation info. */
- obj_textsec (abfd)->rel_filepos = N_TRELOFF (execp);
- obj_datasec (abfd)->rel_filepos = N_DRELOFF (execp);
- /* The file offsets of the string table and symbol table. */
- obj_str_filepos (abfd) = N_STROFF (execp);
- obj_sym_filepos (abfd) = N_SYMOFF (execp);
- /* Determine the architecture and machine type of the object file. */
- switch (N_MACHTYPE (exec_hdr (abfd)))
- {
- default:
- abfd->obj_arch = bfd_arch_obscure;
- break;
- }
- adata (abfd)->page_size = TARGET_PAGE_SIZE;
- adata (abfd)->segment_size = SEGMENT_SIZE;
- adata (abfd)->exec_bytes_size = EXEC_BYTES_SIZE;
- return _bfd_no_cleanup
- /* The architecture is encoded in various ways in various a.out variants,
- or is not encoded at all in some of them. The relocation size depends
- on the architecture and the a.out variant. Finally, the return value
- is the bfd_target vector in use. If an error occurs, return zero and
- set bfd_error to the appropriate error code.
- Formats such as b.out, which have additional fields in the a.out
- header, should cope with them in this callback as well. */
- #endif /* DOCUMENTATION */
- result = (*callback_to_real_object_p) (abfd);
- /* Now that the segment addresses have been worked out, take a better
- guess at whether the file is executable. If the entry point
- is within the text segment, assume it is. (This makes files
- executable even if their entry point address is 0, as long as
- their text starts at zero.).
- This test had to be changed to deal with systems where the text segment
- runs at a different location than the default. The problem is that the
- entry address can appear to be outside the text segment, thus causing an
- erroneous conclusion that the file isn't executable.
- To fix this, we now accept any non-zero entry point as an indication of
- executability. This will work most of the time, since only the linker
- sets the entry point, and that is likely to be non-zero for most systems. */
- if (execp->a_entry != 0
- || (execp->a_entry >= obj_textsec (abfd)->vma
- && execp->a_entry < (obj_textsec (abfd)->vma
- + obj_textsec (abfd)->size)
- && execp->a_trsize == 0
- && execp->a_drsize == 0))
- abfd->flags |= EXEC_P;
- #ifdef STAT_FOR_EXEC
- else
- {
- struct stat stat_buf;
- /* The original heuristic doesn't work in some important cases.
- The a.out file has no information about the text start
- address. For files (like kernels) linked to non-standard
- addresses (ld -Ttext nnn) the entry point may not be between
- the default text start (obj_textsec(abfd)->vma) and
- (obj_textsec(abfd)->vma) + text size. This is not just a mach
- issue. Many kernels are loaded at non standard addresses. */
- if (abfd->iostream != NULL
- && (abfd->flags & BFD_IN_MEMORY) == 0
- && (fstat (fileno ((FILE *) (abfd->iostream)), &stat_buf) == 0)
- && ((stat_buf.st_mode & 0111) != 0))
- abfd->flags |= EXEC_P;
- }
- #endif /* STAT_FOR_EXEC */
- if (result)
- return result;
- error_ret:
- bfd_release (abfd, rawptr);
- abfd->tdata.aout_data = oldrawptr;
- return NULL;
- }
- /*
- FUNCTION
- aout_@var{size}_mkobject
- SYNOPSIS
- bool aout_@var{size}_mkobject, (bfd *abfd);
- DESCRIPTION
- Initialize BFD @var{abfd} for use with a.out files.
- */
- bool
- NAME (aout, mkobject) (bfd *abfd)
- {
- struct aout_data_struct *rawptr;
- size_t amt = sizeof (* rawptr);
- bfd_set_error (bfd_error_system_call);
- rawptr = (struct aout_data_struct *) bfd_zalloc (abfd, amt);
- if (rawptr == NULL)
- return false;
- abfd->tdata.aout_data = rawptr;
- exec_hdr (abfd) = &(rawptr->e);
- obj_textsec (abfd) = NULL;
- obj_datasec (abfd) = NULL;
- obj_bsssec (abfd) = NULL;
- return true;
- }
- /*
- FUNCTION
- aout_@var{size}_machine_type
- SYNOPSIS
- enum machine_type aout_@var{size}_machine_type
- (enum bfd_architecture arch,
- unsigned long machine,
- bool *unknown);
- DESCRIPTION
- Keep track of machine architecture and machine type for
- a.out's. Return the <<machine_type>> for a particular
- architecture and machine, or <<M_UNKNOWN>> if that exact architecture
- and machine can't be represented in a.out format.
- If the architecture is understood, machine type 0 (default)
- is always understood.
- */
- enum machine_type
- NAME (aout, machine_type) (enum bfd_architecture arch,
- unsigned long machine,
- bool *unknown)
- {
- enum machine_type arch_flags;
- arch_flags = M_UNKNOWN;
- *unknown = true;
- switch (arch)
- {
- case bfd_arch_sparc:
- if (machine == 0
- || machine == bfd_mach_sparc
- || machine == bfd_mach_sparc_sparclite
- || machine == bfd_mach_sparc_sparclite_le
- || machine == bfd_mach_sparc_v8plus
- || machine == bfd_mach_sparc_v8plusa
- || machine == bfd_mach_sparc_v8plusb
- || machine == bfd_mach_sparc_v8plusc
- || machine == bfd_mach_sparc_v8plusd
- || machine == bfd_mach_sparc_v8pluse
- || machine == bfd_mach_sparc_v8plusv
- || machine == bfd_mach_sparc_v8plusm
- || machine == bfd_mach_sparc_v8plusm8
- || machine == bfd_mach_sparc_v9
- || machine == bfd_mach_sparc_v9a
- || machine == bfd_mach_sparc_v9b
- || machine == bfd_mach_sparc_v9c
- || machine == bfd_mach_sparc_v9d
- || machine == bfd_mach_sparc_v9e
- || machine == bfd_mach_sparc_v9v
- || machine == bfd_mach_sparc_v9m
- || machine == bfd_mach_sparc_v9m8)
- arch_flags = M_SPARC;
- else if (machine == bfd_mach_sparc_sparclet)
- arch_flags = M_SPARCLET;
- break;
- case bfd_arch_i386:
- if (machine == 0
- || machine == bfd_mach_i386_i386
- || machine == bfd_mach_i386_i386_intel_syntax)
- arch_flags = M_386;
- break;
- case bfd_arch_arm:
- if (machine == 0)
- arch_flags = M_ARM;
- break;
- case bfd_arch_mips:
- switch (machine)
- {
- case 0:
- case bfd_mach_mips3000:
- case bfd_mach_mips3900:
- arch_flags = M_MIPS1;
- break;
- case bfd_mach_mips6000:
- arch_flags = M_MIPS2;
- break;
- case bfd_mach_mips4000:
- case bfd_mach_mips4010:
- case bfd_mach_mips4100:
- case bfd_mach_mips4300:
- case bfd_mach_mips4400:
- case bfd_mach_mips4600:
- case bfd_mach_mips4650:
- case bfd_mach_mips8000:
- case bfd_mach_mips9000:
- case bfd_mach_mips10000:
- case bfd_mach_mips12000:
- case bfd_mach_mips14000:
- case bfd_mach_mips16000:
- case bfd_mach_mips16:
- case bfd_mach_mipsisa32:
- case bfd_mach_mipsisa32r2:
- case bfd_mach_mipsisa32r3:
- case bfd_mach_mipsisa32r5:
- case bfd_mach_mipsisa32r6:
- case bfd_mach_mips5:
- case bfd_mach_mipsisa64:
- case bfd_mach_mipsisa64r2:
- case bfd_mach_mipsisa64r3:
- case bfd_mach_mipsisa64r5:
- case bfd_mach_mipsisa64r6:
- case bfd_mach_mips_sb1:
- case bfd_mach_mips_xlr:
- /* FIXME: These should be MIPS3, MIPS4, MIPS16, MIPS32, etc. */
- arch_flags = M_MIPS2;
- break;
- default:
- arch_flags = M_UNKNOWN;
- break;
- }
- break;
- case bfd_arch_ns32k:
- switch (machine)
- {
- case 0: arch_flags = M_NS32532; break;
- case 32032: arch_flags = M_NS32032; break;
- case 32532: arch_flags = M_NS32532; break;
- default: arch_flags = M_UNKNOWN; break;
- }
- break;
- case bfd_arch_vax:
- *unknown = false;
- break;
- case bfd_arch_cris:
- if (machine == 0 || machine == 255)
- arch_flags = M_CRIS;
- break;
- default:
- arch_flags = M_UNKNOWN;
- }
- if (arch_flags != M_UNKNOWN)
- *unknown = false;
- return arch_flags;
- }
- /*
- FUNCTION
- aout_@var{size}_set_arch_mach
- SYNOPSIS
- bool aout_@var{size}_set_arch_mach,
- (bfd *,
- enum bfd_architecture arch,
- unsigned long machine);
- DESCRIPTION
- Set the architecture and the machine of the BFD @var{abfd} to the
- values @var{arch} and @var{machine}. Verify that @var{abfd}'s format
- can support the architecture required.
- */
- bool
- NAME (aout, set_arch_mach) (bfd *abfd,
- enum bfd_architecture arch,
- unsigned long machine)
- {
- if (! bfd_default_set_arch_mach (abfd, arch, machine))
- return false;
- if (arch != bfd_arch_unknown)
- {
- bool unknown;
- NAME (aout, machine_type) (arch, machine, &unknown);
- if (unknown)
- return false;
- }
- /* Determine the size of a relocation entry. */
- switch (arch)
- {
- case bfd_arch_sparc:
- case bfd_arch_mips:
- obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
- break;
- default:
- obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
- break;
- }
- return (*aout_backend_info (abfd)->set_sizes) (abfd);
- }
- static void
- adjust_o_magic (bfd *abfd, struct internal_exec *execp)
- {
- file_ptr pos = adata (abfd).exec_bytes_size;
- bfd_vma vma = 0;
- int pad = 0;
- asection *text = obj_textsec (abfd);
- asection *data = obj_datasec (abfd);
- asection *bss = obj_bsssec (abfd);
- /* Text. */
- text->filepos = pos;
- if (!text->user_set_vma)
- text->vma = vma;
- else
- vma = text->vma;
- pos += execp->a_text;
- vma += execp->a_text;
- /* Data. */
- if (!data->user_set_vma)
- {
- pos += pad;
- vma += pad;
- data->vma = vma;
- }
- else
- vma = data->vma;
- execp->a_text += pad;
- data->filepos = pos;
- pos += data->size;
- vma += data->size;
- /* BSS. */
- if (!bss->user_set_vma)
- {
- pos += pad;
- vma += pad;
- bss->vma = vma;
- }
- else
- {
- /* The VMA of the .bss section is set by the VMA of the
- .data section plus the size of the .data section. We may
- need to add padding bytes to make this true. */
- pad = bss->vma - vma;
- if (pad < 0)
- pad = 0;
- pos += pad;
- }
- execp->a_data = data->size + pad;
- bss->filepos = pos;
- execp->a_bss = bss->size;
- N_SET_MAGIC (execp, OMAGIC);
- }
- static void
- adjust_z_magic (bfd *abfd, struct internal_exec *execp)
- {
- bfd_size_type data_pad, text_pad;
- file_ptr text_end;
- const struct aout_backend_data *abdp;
- /* TRUE if text includes exec header. */
- bool ztih;
- asection *text = obj_textsec (abfd);
- asection *data = obj_datasec (abfd);
- asection *bss = obj_bsssec (abfd);
- abdp = aout_backend_info (abfd);
- /* Text. */
- ztih = (abdp != NULL
- && (abdp->text_includes_header
- || obj_aout_subformat (abfd) == q_magic_format));
- text->filepos = (ztih
- ? adata (abfd).exec_bytes_size
- : adata (abfd).zmagic_disk_block_size);
- if (!text->user_set_vma)
- {
- /* ?? Do we really need to check for relocs here? */
- text->vma = ((abfd->flags & HAS_RELOC)
- ? 0
- : (ztih
- ? abdp->default_text_vma + adata (abfd).exec_bytes_size
- : abdp->default_text_vma));
- text_pad = 0;
- }
- else
- {
- /* The .text section is being loaded at an unusual address. We
- may need to pad it such that the .data section starts at a page
- boundary. */
- if (ztih)
- text_pad = ((text->filepos - text->vma)
- & (adata (abfd).page_size - 1));
- else
- text_pad = (-text->vma
- & (adata (abfd).page_size - 1));
- }
- /* Find start of data. */
- if (ztih)
- {
- text_end = text->filepos + execp->a_text;
- text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
- }
- else
- {
- /* Note that if page_size == zmagic_disk_block_size, then
- filepos == page_size, and this case is the same as the ztih
- case. */
- text_end = execp->a_text;
- text_pad += BFD_ALIGN (text_end, adata (abfd).page_size) - text_end;
- text_end += text->filepos;
- }
- execp->a_text += text_pad;
- /* Data. */
- if (!data->user_set_vma)
- {
- bfd_vma vma;
- vma = text->vma + execp->a_text;
- data->vma = BFD_ALIGN (vma, adata (abfd).segment_size);
- }
- if (abdp && abdp->zmagic_mapped_contiguous)
- {
- text_pad = data->vma - (text->vma + execp->a_text);
- /* Only pad the text section if the data
- section is going to be placed after it. */
- if (text_pad > 0)
- execp->a_text += text_pad;
- }
- data->filepos = text->filepos + execp->a_text;
- /* Fix up exec header while we're at it. */
- if (ztih && (!abdp || (abdp && !abdp->exec_header_not_counted)))
- execp->a_text += adata (abfd).exec_bytes_size;
- if (obj_aout_subformat (abfd) == q_magic_format)
- N_SET_QMAGIC (execp);
- else
- N_SET_MAGIC (execp, ZMAGIC);
- /* Spec says data section should be rounded up to page boundary. */
- execp->a_data = align_power (data->size, bss->alignment_power);
- execp->a_data = BFD_ALIGN (execp->a_data, adata (abfd).page_size);
- data_pad = execp->a_data - data->size;
- /* BSS. */
- if (!bss->user_set_vma)
- bss->vma = data->vma + execp->a_data;
- /* If the BSS immediately follows the data section and extra space
- in the page is left after the data section, fudge data
- in the header so that the bss section looks smaller by that
- amount. We'll start the bss section there, and lie to the OS.
- (Note that a linker script, as well as the above assignment,
- could have explicitly set the BSS vma to immediately follow
- the data section.) */
- if (align_power (bss->vma, bss->alignment_power) == data->vma + execp->a_data)
- execp->a_bss = data_pad > bss->size ? 0 : bss->size - data_pad;
- else
- execp->a_bss = bss->size;
- }
- static void
- adjust_n_magic (bfd *abfd, struct internal_exec *execp)
- {
- file_ptr pos = adata (abfd).exec_bytes_size;
- bfd_vma vma = 0;
- int pad;
- asection *text = obj_textsec (abfd);
- asection *data = obj_datasec (abfd);
- asection *bss = obj_bsssec (abfd);
- /* Text. */
- text->filepos = pos;
- if (!text->user_set_vma)
- text->vma = vma;
- else
- vma = text->vma;
- pos += execp->a_text;
- vma += execp->a_text;
- /* Data. */
- data->filepos = pos;
- if (!data->user_set_vma)
- data->vma = BFD_ALIGN (vma, adata (abfd).segment_size);
- vma = data->vma;
- /* Since BSS follows data immediately, see if it needs alignment. */
- vma += data->size;
- pad = align_power (vma, bss->alignment_power) - vma;
- execp->a_data = data->size + pad;
- pos += execp->a_data;
- /* BSS. */
- if (!bss->user_set_vma)
- bss->vma = vma;
- else
- vma = bss->vma;
- /* Fix up exec header. */
- execp->a_bss = bss->size;
- N_SET_MAGIC (execp, NMAGIC);
- }
- bool
- NAME (aout, adjust_sizes_and_vmas) (bfd *abfd)
- {
- struct internal_exec *execp = exec_hdr (abfd);
- if (! NAME (aout, make_sections) (abfd))
- return false;
- if (adata (abfd).magic != undecided_magic)
- return true;
- execp->a_text = align_power (obj_textsec (abfd)->size,
- obj_textsec (abfd)->alignment_power);
- /* Rule (heuristic) for when to pad to a new page. Note that there
- are (at least) two ways demand-paged (ZMAGIC) files have been
- handled. Most Berkeley-based systems start the text segment at
- (TARGET_PAGE_SIZE). However, newer versions of SUNOS start the text
- segment right after the exec header; the latter is counted in the
- text segment size, and is paged in by the kernel with the rest of
- the text. */
- /* This perhaps isn't the right way to do this, but made it simpler for me
- to understand enough to implement it. Better would probably be to go
- right from BFD flags to alignment/positioning characteristics. But the
- old code was sloppy enough about handling the flags, and had enough
- other magic, that it was a little hard for me to understand. I think
- I understand it better now, but I haven't time to do the cleanup this
- minute. */
- if (abfd->flags & D_PAGED)
- /* Whether or not WP_TEXT is set -- let D_PAGED override. */
- adata (abfd).magic = z_magic;
- else if (abfd->flags & WP_TEXT)
- adata (abfd).magic = n_magic;
- else
- adata (abfd).magic = o_magic;
- #ifdef BFD_AOUT_DEBUG /* requires gcc2 */
- #if __GNUC__ >= 2
- fprintf (stderr, "%s text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x,%x>\n",
- ({ char *str;
- switch (adata (abfd).magic)
- {
- case n_magic: str = "NMAGIC"; break;
- case o_magic: str = "OMAGIC"; break;
- case z_magic: str = "ZMAGIC"; break;
- default: abort ();
- }
- str;
- }),
- obj_textsec (abfd)->vma, obj_textsec (abfd)->size,
- obj_textsec (abfd)->alignment_power,
- obj_datasec (abfd)->vma, obj_datasec (abfd)->size,
- obj_datasec (abfd)->alignment_power,
- obj_bsssec (abfd)->vma, obj_bsssec (abfd)->size,
- obj_bsssec (abfd)->alignment_power);
- #endif
- #endif
- switch (adata (abfd).magic)
- {
- case o_magic:
- adjust_o_magic (abfd, execp);
- break;
- case z_magic:
- adjust_z_magic (abfd, execp);
- break;
- case n_magic:
- adjust_n_magic (abfd, execp);
- break;
- default:
- abort ();
- }
- #ifdef BFD_AOUT_DEBUG
- fprintf (stderr, " text=<%x,%x,%x> data=<%x,%x,%x> bss=<%x,%x>\n",
- obj_textsec (abfd)->vma, execp->a_text,
- obj_textsec (abfd)->filepos,
- obj_datasec (abfd)->vma, execp->a_data,
- obj_datasec (abfd)->filepos,
- obj_bsssec (abfd)->vma, execp->a_bss);
- #endif
- return true;
- }
- /*
- FUNCTION
- aout_@var{size}_new_section_hook
- SYNOPSIS
- bool aout_@var{size}_new_section_hook,
- (bfd *abfd,
- asection *newsect);
- DESCRIPTION
- Called by the BFD in response to a @code{bfd_make_section}
- request.
- */
- bool
- NAME (aout, new_section_hook) (bfd *abfd, asection *newsect)
- {
- /* Align to double at least. */
- newsect->alignment_power = bfd_get_arch_info (abfd)->section_align_power;
- if (bfd_get_format (abfd) == bfd_object)
- {
- if (obj_textsec (abfd) == NULL && !strcmp (newsect->name, ".text"))
- {
- obj_textsec (abfd)= newsect;
- newsect->target_index = N_TEXT;
- }
- else if (obj_datasec (abfd) == NULL && !strcmp (newsect->name, ".data"))
- {
- obj_datasec (abfd) = newsect;
- newsect->target_index = N_DATA;
- }
- else if (obj_bsssec (abfd) == NULL && !strcmp (newsect->name, ".bss"))
- {
- obj_bsssec (abfd) = newsect;
- newsect->target_index = N_BSS;
- }
- }
- /* We allow more than three sections internally. */
- return _bfd_generic_new_section_hook (abfd, newsect);
- }
- bool
- NAME (aout, set_section_contents) (bfd *abfd,
- sec_ptr section,
- const void * location,
- file_ptr offset,
- bfd_size_type count)
- {
- if (! abfd->output_has_begun)
- {
- if (! NAME (aout, adjust_sizes_and_vmas) (abfd))
- return false;
- }
- if (section == obj_bsssec (abfd))
- {
- bfd_set_error (bfd_error_no_contents);
- return false;
- }
- if (section != obj_textsec (abfd)
- && section != obj_datasec (abfd))
- {
- if (aout_section_merge_with_text_p (abfd, section))
- section->filepos = obj_textsec (abfd)->filepos +
- (section->vma - obj_textsec (abfd)->vma);
- else
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: can not represent section `%pA' in a.out object file format"),
- abfd, section);
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
- }
- if (count != 0)
- {
- if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0
- || bfd_bwrite (location, count, abfd) != count)
- return false;
- }
- return true;
- }
- /* Read the external symbols from an a.out file. */
- static bool
- aout_get_external_symbols (bfd *abfd)
- {
- if (obj_aout_external_syms (abfd) == NULL)
- {
- bfd_size_type count;
- struct external_nlist *syms;
- bfd_size_type amt = exec_hdr (abfd)->a_syms;
- count = amt / EXTERNAL_NLIST_SIZE;
- if (count == 0)
- return true; /* Nothing to do. */
- #ifdef USE_MMAP
- if (! bfd_get_file_window (abfd, obj_sym_filepos (abfd), amt,
- &obj_aout_sym_window (abfd), true))
- return false;
- syms = (struct external_nlist *) obj_aout_sym_window (abfd).data;
- #else
- /* We allocate using malloc to make the values easy to free
- later on. If we put them on the objalloc it might not be
- possible to free them. */
- if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0)
- return false;
- syms = (struct external_nlist *) _bfd_malloc_and_read (abfd, amt, amt);
- if (syms == NULL)
- return false;
- #endif
- obj_aout_external_syms (abfd) = syms;
- obj_aout_external_sym_count (abfd) = count;
- }
- if (obj_aout_external_strings (abfd) == NULL
- && exec_hdr (abfd)->a_syms != 0)
- {
- unsigned char string_chars[BYTES_IN_WORD];
- bfd_size_type stringsize;
- char *strings;
- bfd_size_type amt = BYTES_IN_WORD;
- /* Get the size of the strings. */
- if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0
- || bfd_bread ((void *) string_chars, amt, abfd) != amt)
- return false;
- stringsize = GET_WORD (abfd, string_chars);
- if (stringsize == 0)
- stringsize = 1;
- else if (stringsize < BYTES_IN_WORD
- || (size_t) stringsize != stringsize)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- #ifdef USE_MMAP
- if (stringsize >= BYTES_IN_WORD)
- {
- if (! bfd_get_file_window (abfd, obj_str_filepos (abfd), stringsize + 1,
- &obj_aout_string_window (abfd), true))
- return false;
- strings = (char *) obj_aout_string_window (abfd).data;
- }
- else
- #endif
- {
- strings = (char *) bfd_malloc (stringsize + 1);
- if (strings == NULL)
- return false;
- if (stringsize >= BYTES_IN_WORD)
- {
- amt = stringsize - BYTES_IN_WORD;
- if (bfd_bread (strings + BYTES_IN_WORD, amt, abfd) != amt)
- {
- free (strings);
- return false;
- }
- }
- }
- /* Ensure that a zero index yields an empty string. */
- if (stringsize >= BYTES_IN_WORD)
- memset (strings, 0, BYTES_IN_WORD);
- /* Ensure that the string buffer is NUL terminated. */
- strings[stringsize] = 0;
- obj_aout_external_strings (abfd) = strings;
- obj_aout_external_string_size (abfd) = stringsize;
- }
- return true;
- }
- /* Translate an a.out symbol into a BFD symbol. The desc, other, type
- and symbol->value fields of CACHE_PTR will be set from the a.out
- nlist structure. This function is responsible for setting
- symbol->flags and symbol->section, and adjusting symbol->value. */
- static bool
- translate_from_native_sym_flags (bfd *abfd, aout_symbol_type *cache_ptr)
- {
- flagword visible;
- if ((cache_ptr->type & N_STAB) != 0
- || cache_ptr->type == N_FN)
- {
- asection *sec;
- /* This is a debugging symbol. */
- cache_ptr->symbol.flags = BSF_DEBUGGING;
- /* Work out the symbol section. */
- switch (cache_ptr->type & N_TYPE)
- {
- case N_TEXT:
- case N_FN:
- sec = obj_textsec (abfd);
- break;
- case N_DATA:
- sec = obj_datasec (abfd);
- break;
- case N_BSS:
- sec = obj_bsssec (abfd);
- break;
- default:
- case N_ABS:
- sec = bfd_abs_section_ptr;
- break;
- }
- cache_ptr->symbol.section = sec;
- cache_ptr->symbol.value -= sec->vma;
- return true;
- }
- /* Get the default visibility. This does not apply to all types, so
- we just hold it in a local variable to use if wanted. */
- if ((cache_ptr->type & N_EXT) == 0)
- visible = BSF_LOCAL;
- else
- visible = BSF_GLOBAL;
- switch (cache_ptr->type)
- {
- default:
- case N_ABS: case N_ABS | N_EXT:
- cache_ptr->symbol.section = bfd_abs_section_ptr;
- cache_ptr->symbol.flags = visible;
- break;
- case N_UNDF | N_EXT:
- if (cache_ptr->symbol.value != 0)
- {
- /* This is a common symbol. */
- cache_ptr->symbol.flags = BSF_GLOBAL;
- cache_ptr->symbol.section = bfd_com_section_ptr;
- }
- else
- {
- cache_ptr->symbol.flags = 0;
- cache_ptr->symbol.section = bfd_und_section_ptr;
- }
- break;
- case N_TEXT: case N_TEXT | N_EXT:
- cache_ptr->symbol.section = obj_textsec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = visible;
- break;
- /* N_SETV symbols used to represent set vectors placed in the
- data section. They are no longer generated. Theoretically,
- it was possible to extract the entries and combine them with
- new ones, although I don't know if that was ever actually
- done. Unless that feature is restored, treat them as data
- symbols. */
- case N_SETV: case N_SETV | N_EXT:
- case N_DATA: case N_DATA | N_EXT:
- cache_ptr->symbol.section = obj_datasec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = visible;
- break;
- case N_BSS: case N_BSS | N_EXT:
- cache_ptr->symbol.section = obj_bsssec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = visible;
- break;
- case N_SETA: case N_SETA | N_EXT:
- case N_SETT: case N_SETT | N_EXT:
- case N_SETD: case N_SETD | N_EXT:
- case N_SETB: case N_SETB | N_EXT:
- {
- /* This code is no longer needed. It used to be used to make
- the linker handle set symbols, but they are now handled in
- the add_symbols routine instead. */
- switch (cache_ptr->type & N_TYPE)
- {
- case N_SETA:
- cache_ptr->symbol.section = bfd_abs_section_ptr;
- break;
- case N_SETT:
- cache_ptr->symbol.section = obj_textsec (abfd);
- break;
- case N_SETD:
- cache_ptr->symbol.section = obj_datasec (abfd);
- break;
- case N_SETB:
- cache_ptr->symbol.section = obj_bsssec (abfd);
- break;
- }
- cache_ptr->symbol.flags |= BSF_CONSTRUCTOR;
- }
- break;
- case N_WARNING:
- /* This symbol is the text of a warning message. The next
- symbol is the symbol to associate the warning with. If a
- reference is made to that symbol, a warning is issued. */
- cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_WARNING;
- cache_ptr->symbol.section = bfd_abs_section_ptr;
- break;
- case N_INDR: case N_INDR | N_EXT:
- /* An indirect symbol. This consists of two symbols in a row.
- The first symbol is the name of the indirection. The second
- symbol is the name of the target. A reference to the first
- symbol becomes a reference to the second. */
- cache_ptr->symbol.flags = BSF_DEBUGGING | BSF_INDIRECT | visible;
- cache_ptr->symbol.section = bfd_ind_section_ptr;
- break;
- case N_WEAKU:
- cache_ptr->symbol.section = bfd_und_section_ptr;
- cache_ptr->symbol.flags = BSF_WEAK;
- break;
- case N_WEAKA:
- cache_ptr->symbol.section = bfd_abs_section_ptr;
- cache_ptr->symbol.flags = BSF_WEAK;
- break;
- case N_WEAKT:
- cache_ptr->symbol.section = obj_textsec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = BSF_WEAK;
- break;
- case N_WEAKD:
- cache_ptr->symbol.section = obj_datasec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = BSF_WEAK;
- break;
- case N_WEAKB:
- cache_ptr->symbol.section = obj_bsssec (abfd);
- cache_ptr->symbol.value -= cache_ptr->symbol.section->vma;
- cache_ptr->symbol.flags = BSF_WEAK;
- break;
- }
- return true;
- }
- /* Set the fields of SYM_POINTER according to CACHE_PTR. */
- static bool
- translate_to_native_sym_flags (bfd *abfd,
- asymbol *cache_ptr,
- struct external_nlist *sym_pointer)
- {
- bfd_vma value = cache_ptr->value;
- asection *sec;
- bfd_vma off;
- /* Mask out any existing type bits in case copying from one section
- to another. */
- sym_pointer->e_type[0] &= ~N_TYPE;
- sec = bfd_asymbol_section (cache_ptr);
- off = 0;
- if (sec == NULL)
- {
- /* This case occurs, e.g., for the *DEBUG* section of a COFF
- file. */
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: can not represent section for symbol `%s' in a.out "
- "object file format"),
- abfd,
- cache_ptr->name != NULL ? cache_ptr->name : _("*unknown*"));
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
- if (sec->output_section != NULL)
- {
- off = sec->output_offset;
- sec = sec->output_section;
- }
- if (bfd_is_abs_section (sec))
- sym_pointer->e_type[0] |= N_ABS;
- else if (sec == obj_textsec (abfd))
- sym_pointer->e_type[0] |= N_TEXT;
- else if (sec == obj_datasec (abfd))
- sym_pointer->e_type[0] |= N_DATA;
- else if (sec == obj_bsssec (abfd))
- sym_pointer->e_type[0] |= N_BSS;
- else if (bfd_is_und_section (sec))
- sym_pointer->e_type[0] = N_UNDF | N_EXT;
- else if (bfd_is_ind_section (sec))
- sym_pointer->e_type[0] = N_INDR;
- else if (bfd_is_com_section (sec))
- sym_pointer->e_type[0] = N_UNDF | N_EXT;
- else
- {
- if (aout_section_merge_with_text_p (abfd, sec))
- sym_pointer->e_type[0] |= N_TEXT;
- else
- {
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: can not represent section `%pA' in a.out object file format"),
- abfd, sec);
- bfd_set_error (bfd_error_nonrepresentable_section);
- return false;
- }
- }
- /* Turn the symbol from section relative to absolute again. */
- value += sec->vma + off;
- if ((cache_ptr->flags & BSF_WARNING) != 0)
- sym_pointer->e_type[0] = N_WARNING;
- if ((cache_ptr->flags & BSF_DEBUGGING) != 0)
- sym_pointer->e_type[0] = ((aout_symbol_type *) cache_ptr)->type;
- else if ((cache_ptr->flags & BSF_GLOBAL) != 0)
- sym_pointer->e_type[0] |= N_EXT;
- else if ((cache_ptr->flags & BSF_LOCAL) != 0)
- sym_pointer->e_type[0] &= ~N_EXT;
- if ((cache_ptr->flags & BSF_CONSTRUCTOR) != 0)
- {
- int type = ((aout_symbol_type *) cache_ptr)->type;
- switch (type)
- {
- case N_ABS: type = N_SETA; break;
- case N_TEXT: type = N_SETT; break;
- case N_DATA: type = N_SETD; break;
- case N_BSS: type = N_SETB; break;
- }
- sym_pointer->e_type[0] = type;
- }
- if ((cache_ptr->flags & BSF_WEAK) != 0)
- {
- int type;
- switch (sym_pointer->e_type[0] & N_TYPE)
- {
- default:
- case N_ABS: type = N_WEAKA; break;
- case N_TEXT: type = N_WEAKT; break;
- case N_DATA: type = N_WEAKD; break;
- case N_BSS: type = N_WEAKB; break;
- case N_UNDF: type = N_WEAKU; break;
- }
- sym_pointer->e_type[0] = type;
- }
- PUT_WORD (abfd, value, sym_pointer->e_value);
- return true;
- }
- /* Native-level interface to symbols. */
- asymbol *
- NAME (aout, make_empty_symbol) (bfd *abfd)
- {
- size_t amt = sizeof (aout_symbol_type);
- aout_symbol_type *new_symbol = (aout_symbol_type *) bfd_zalloc (abfd, amt);
- if (!new_symbol)
- return NULL;
- new_symbol->symbol.the_bfd = abfd;
- return &new_symbol->symbol;
- }
- /* Translate a set of external symbols into internal symbols. */
- bool
- NAME (aout, translate_symbol_table) (bfd *abfd,
- aout_symbol_type *in,
- struct external_nlist *ext,
- bfd_size_type count,
- char *str,
- bfd_size_type strsize,
- bool dynamic)
- {
- struct external_nlist *ext_end;
- ext_end = ext + count;
- for (; ext < ext_end; ext++, in++)
- {
- bfd_vma x;
- x = GET_WORD (abfd, ext->e_strx);
- in->symbol.the_bfd = abfd;
- /* For the normal symbols, the zero index points at the number
- of bytes in the string table but is to be interpreted as the
- null string. For the dynamic symbols, the number of bytes in
- the string table is stored in the __DYNAMIC structure and the
- zero index points at an actual string. */
- if (x == 0 && ! dynamic)
- in->symbol.name = "";
- else if (x < strsize)
- in->symbol.name = str + x;
- else
- {
- _bfd_error_handler
- (_("%pB: invalid string offset %" PRIu64 " >= %" PRIu64),
- abfd, (uint64_t) x, (uint64_t) strsize);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- in->symbol.value = GET_SWORD (abfd, ext->e_value);
- in->desc = H_GET_16 (abfd, ext->e_desc);
- in->other = H_GET_8 (abfd, ext->e_other);
- in->type = H_GET_8 (abfd, ext->e_type);
- in->symbol.udata.p = NULL;
- if (! translate_from_native_sym_flags (abfd, in))
- return false;
- if (dynamic)
- in->symbol.flags |= BSF_DYNAMIC;
- }
- return true;
- }
- /* We read the symbols into a buffer, which is discarded when this
- function exits. We read the strings into a buffer large enough to
- hold them all plus all the cached symbol entries. */
- bool
- NAME (aout, slurp_symbol_table) (bfd *abfd)
- {
- struct external_nlist *old_external_syms;
- aout_symbol_type *cached;
- bfd_size_type cached_size;
- /* If there's no work to be done, don't do any. */
- if (obj_aout_symbols (abfd) != NULL)
- return true;
- old_external_syms = obj_aout_external_syms (abfd);
- if (! aout_get_external_symbols (abfd))
- return false;
- cached_size = obj_aout_external_sym_count (abfd);
- if (cached_size == 0)
- return true; /* Nothing to do. */
- cached_size *= sizeof (aout_symbol_type);
- cached = (aout_symbol_type *) bfd_zmalloc (cached_size);
- if (cached == NULL)
- return false;
- /* Convert from external symbol information to internal. */
- if (! (NAME (aout, translate_symbol_table)
- (abfd, cached,
- obj_aout_external_syms (abfd),
- obj_aout_external_sym_count (abfd),
- obj_aout_external_strings (abfd),
- obj_aout_external_string_size (abfd),
- false)))
- {
- free (cached);
- return false;
- }
- abfd->symcount = obj_aout_external_sym_count (abfd);
- obj_aout_symbols (abfd) = cached;
- /* It is very likely that anybody who calls this function will not
- want the external symbol information, so if it was allocated
- because of our call to aout_get_external_symbols, we free it up
- right away to save space. */
- if (old_external_syms == NULL
- && obj_aout_external_syms (abfd) != NULL)
- {
- #ifdef USE_MMAP
- bfd_free_window (&obj_aout_sym_window (abfd));
- #else
- free (obj_aout_external_syms (abfd));
- #endif
- obj_aout_external_syms (abfd) = NULL;
- }
- return true;
- }
- /* We use a hash table when writing out symbols so that we only write
- out a particular string once. This helps particularly when the
- linker writes out stabs debugging entries, because each different
- contributing object file tends to have many duplicate stabs
- strings.
- This hash table code breaks dbx on SunOS 4.1.3, so we don't do it
- if BFD_TRADITIONAL_FORMAT is set. */
- /* Get the index of a string in a strtab, adding it if it is not
- already present. */
- static inline bfd_size_type
- add_to_stringtab (bfd *abfd,
- struct bfd_strtab_hash *tab,
- const char *str,
- bool copy)
- {
- bool hash;
- bfd_size_type str_index;
- /* An index of 0 always means the empty string. */
- if (str == 0 || *str == '\0')
- return 0;
- /* Don't hash if BFD_TRADITIONAL_FORMAT is set, because SunOS dbx
- doesn't understand a hashed string table. */
- hash = true;
- if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0)
- hash = false;
- str_index = _bfd_stringtab_add (tab, str, hash, copy);
- if (str_index != (bfd_size_type) -1)
- /* Add BYTES_IN_WORD to the return value to account for the
- space taken up by the string table size. */
- str_index += BYTES_IN_WORD;
- return str_index;
- }
- /* Write out a strtab. ABFD is already at the right location in the
- file. */
- static bool
- emit_stringtab (bfd *abfd, struct bfd_strtab_hash *tab)
- {
- bfd_byte buffer[BYTES_IN_WORD];
- size_t amt = BYTES_IN_WORD;
- /* The string table starts with the size. */
- PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer);
- if (bfd_bwrite ((void *) buffer, amt, abfd) != amt)
- return false;
- return _bfd_stringtab_emit (abfd, tab);
- }
- bool
- NAME (aout, write_syms) (bfd *abfd)
- {
- unsigned int count ;
- asymbol **generic = bfd_get_outsymbols (abfd);
- struct bfd_strtab_hash *strtab;
- strtab = _bfd_stringtab_init ();
- if (strtab == NULL)
- return false;
- for (count = 0; count < bfd_get_symcount (abfd); count++)
- {
- asymbol *g = generic[count];
- bfd_size_type indx;
- struct external_nlist nsp;
- size_t amt;
- indx = add_to_stringtab (abfd, strtab, g->name, false);
- if (indx == (bfd_size_type) -1)
- goto error_return;
- PUT_WORD (abfd, indx, (bfd_byte *) nsp.e_strx);
- if (bfd_asymbol_flavour (g) == abfd->xvec->flavour)
- {
- H_PUT_16 (abfd, aout_symbol (g)->desc, nsp.e_desc);
- H_PUT_8 (abfd, aout_symbol (g)->other, nsp.e_other);
- H_PUT_8 (abfd, aout_symbol (g)->type, nsp.e_type);
- }
- else
- {
- H_PUT_16 (abfd, 0, nsp.e_desc);
- H_PUT_8 (abfd, 0, nsp.e_other);
- H_PUT_8 (abfd, 0, nsp.e_type);
- }
- if (! translate_to_native_sym_flags (abfd, g, &nsp))
- goto error_return;
- amt = EXTERNAL_NLIST_SIZE;
- if (bfd_bwrite ((void *) &nsp, amt, abfd) != amt)
- goto error_return;
- /* NB: `KEEPIT' currently overlays `udata.p', so set this only
- here, at the end. */
- g->KEEPIT = count;
- }
- if (! emit_stringtab (abfd, strtab))
- goto error_return;
- _bfd_stringtab_free (strtab);
- return true;
- error_return:
- _bfd_stringtab_free (strtab);
- return false;
- }
- long
- NAME (aout, canonicalize_symtab) (bfd *abfd, asymbol **location)
- {
- unsigned int counter = 0;
- aout_symbol_type *symbase;
- if (!NAME (aout, slurp_symbol_table) (abfd))
- return -1;
- for (symbase = obj_aout_symbols (abfd);
- counter++ < bfd_get_symcount (abfd);
- )
- *(location++) = (asymbol *) (symbase++);
- *location++ =0;
- return bfd_get_symcount (abfd);
- }
- /* Standard reloc stuff. */
- /* Output standard relocation information to a file in target byte order. */
- extern void NAME (aout, swap_std_reloc_out)
- (bfd *, arelent *, struct reloc_std_external *);
- void
- NAME (aout, swap_std_reloc_out) (bfd *abfd,
- arelent *g,
- struct reloc_std_external *natptr)
- {
- int r_index;
- asymbol *sym = *(g->sym_ptr_ptr);
- int r_extern;
- unsigned int r_length;
- int r_pcrel;
- int r_baserel, r_jmptable, r_relative;
- asection *output_section = sym->section->output_section;
- PUT_WORD (abfd, g->address, natptr->r_address);
- BFD_ASSERT (g->howto != NULL);
- switch (bfd_get_reloc_size (g->howto))
- {
- default:
- _bfd_error_handler (_("%pB: unsupported AOUT relocation size: %d"),
- abfd, bfd_get_reloc_size (g->howto));
- bfd_set_error (bfd_error_bad_value);
- return;
- case 1:
- case 2:
- case 4:
- r_length = g->howto->size; /* Size as a power of two. */
- break;
- case 8:
- r_length = 3;
- break;
- }
- r_pcrel = (int) g->howto->pc_relative; /* Relative to PC? */
- /* XXX This relies on relocs coming from a.out files. */
- r_baserel = (g->howto->type & 8) != 0;
- r_jmptable = (g->howto->type & 16) != 0;
- r_relative = (g->howto->type & 32) != 0;
- /* Name was clobbered by aout_write_syms to be symbol index. */
- /* If this relocation is relative to a symbol then set the
- r_index to the symbols index, and the r_extern bit.
- Absolute symbols can come in in two ways, either as an offset
- from the abs section, or as a symbol which has an abs value.
- check for that here. */
- if (bfd_is_com_section (output_section)
- || bfd_is_abs_section (output_section)
- || bfd_is_und_section (output_section)
- /* PR gas/3041 a.out relocs against weak symbols
- must be treated as if they were against externs. */
- || (sym->flags & BSF_WEAK))
- {
- if (bfd_abs_section_ptr->symbol == sym)
- {
- /* Whoops, looked like an abs symbol, but is
- really an offset from the abs section. */
- r_index = N_ABS;
- r_extern = 0;
- }
- else
- {
- /* Fill in symbol. */
- r_extern = 1;
- r_index = (*(g->sym_ptr_ptr))->KEEPIT;
- }
- }
- else
- {
- /* Just an ordinary section. */
- r_extern = 0;
- r_index = output_section->target_index;
- }
- /* Now the fun stuff. */
- if (bfd_header_big_endian (abfd))
- {
- natptr->r_index[0] = r_index >> 16;
- natptr->r_index[1] = r_index >> 8;
- natptr->r_index[2] = r_index;
- natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
- | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
- | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
- | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
- | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
- | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
- }
- else
- {
- natptr->r_index[2] = r_index >> 16;
- natptr->r_index[1] = r_index >> 8;
- natptr->r_index[0] = r_index;
- natptr->r_type[0] = ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
- | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
- | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
- | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
- | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
- | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
- }
- }
- /* Extended stuff. */
- /* Output extended relocation information to a file in target byte order. */
- extern void NAME (aout, swap_ext_reloc_out)
- (bfd *, arelent *, struct reloc_ext_external *);
- void
- NAME (aout, swap_ext_reloc_out) (bfd *abfd,
- arelent *g,
- struct reloc_ext_external *natptr)
- {
- int r_index;
- int r_extern;
- unsigned int r_type;
- bfd_vma r_addend;
- asymbol *sym = *(g->sym_ptr_ptr);
- asection *output_section = sym->section->output_section;
- PUT_WORD (abfd, g->address, natptr->r_address);
- r_type = (unsigned int) g->howto->type;
- r_addend = g->addend;
- if ((sym->flags & BSF_SECTION_SYM) != 0)
- r_addend += (*(g->sym_ptr_ptr))->section->output_section->vma;
- /* If this relocation is relative to a symbol then set the
- r_index to the symbols index, and the r_extern bit.
- Absolute symbols can come in in two ways, either as an offset
- from the abs section, or as a symbol which has an abs value.
- check for that here. */
- if (bfd_is_abs_section (bfd_asymbol_section (sym)))
- {
- r_extern = 0;
- r_index = N_ABS;
- }
- else if ((sym->flags & BSF_SECTION_SYM) == 0)
- {
- if (bfd_is_und_section (bfd_asymbol_section (sym))
- || (sym->flags & BSF_GLOBAL) != 0)
- r_extern = 1;
- else
- r_extern = 0;
- r_index = (*(g->sym_ptr_ptr))->KEEPIT;
- }
- else
- {
- /* Just an ordinary section. */
- r_extern = 0;
- r_index = output_section->target_index;
- }
- /* Now the fun stuff. */
- if (bfd_header_big_endian (abfd))
- {
- natptr->r_index[0] = r_index >> 16;
- natptr->r_index[1] = r_index >> 8;
- natptr->r_index[2] = r_index;
- natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
- | (r_type << RELOC_EXT_BITS_TYPE_SH_BIG));
- }
- else
- {
- natptr->r_index[2] = r_index >> 16;
- natptr->r_index[1] = r_index >> 8;
- natptr->r_index[0] = r_index;
- natptr->r_type[0] = ((r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
- | (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE));
- }
- PUT_WORD (abfd, r_addend, natptr->r_addend);
- }
- /* BFD deals internally with all things based from the section they're
- in. so, something in 10 bytes into a text section with a base of
- 50 would have a symbol (.text+10) and know .text vma was 50.
- Aout keeps all it's symbols based from zero, so the symbol would
- contain 60. This macro subs the base of each section from the value
- to give the true offset from the section. */
- #define MOVE_ADDRESS(ad) \
- if (r_extern) \
- { \
- /* Undefined symbol. */ \
- if (r_index < bfd_get_symcount (abfd)) \
- cache_ptr->sym_ptr_ptr = symbols + r_index; \
- cache_ptr->addend = ad; \
- } \
- else \
- { \
- /* Defined, section relative. Replace symbol with pointer to \
- symbol which points to section. */ \
- switch (r_index) \
- { \
- case N_TEXT: \
- case N_TEXT | N_EXT: \
- cache_ptr->sym_ptr_ptr = obj_textsec (abfd)->symbol_ptr_ptr; \
- cache_ptr->addend = ad - su->textsec->vma; \
- break; \
- case N_DATA: \
- case N_DATA | N_EXT: \
- cache_ptr->sym_ptr_ptr = obj_datasec (abfd)->symbol_ptr_ptr; \
- cache_ptr->addend = ad - su->datasec->vma; \
- break; \
- case N_BSS: \
- case N_BSS | N_EXT: \
- cache_ptr->sym_ptr_ptr = obj_bsssec (abfd)->symbol_ptr_ptr; \
- cache_ptr->addend = ad - su->bsssec->vma; \
- break; \
- default: \
- case N_ABS: \
- case N_ABS | N_EXT: \
- cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; \
- cache_ptr->addend = ad; \
- break; \
- } \
- }
- void
- NAME (aout, swap_ext_reloc_in) (bfd *abfd,
- struct reloc_ext_external *bytes,
- arelent *cache_ptr,
- asymbol **symbols,
- bfd_size_type symcount)
- {
- unsigned int r_index;
- int r_extern;
- unsigned int r_type;
- struct aoutdata *su = &(abfd->tdata.aout_data->a);
- cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
- /* Now the fun stuff. */
- if (bfd_header_big_endian (abfd))
- {
- r_index = (((unsigned int) bytes->r_index[0] << 16)
- | ((unsigned int) bytes->r_index[1] << 8)
- | bytes->r_index[2]);
- r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
- r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
- >> RELOC_EXT_BITS_TYPE_SH_BIG);
- }
- else
- {
- r_index = (((unsigned int) bytes->r_index[2] << 16)
- | ((unsigned int) bytes->r_index[1] << 8)
- | bytes->r_index[0]);
- r_extern = (0 != (bytes->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
- r_type = ((bytes->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
- >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
- }
- if (r_type < TABLE_SIZE (howto_table_ext))
- cache_ptr->howto = howto_table_ext + r_type;
- else
- cache_ptr->howto = NULL;
- /* Base relative relocs are always against the symbol table,
- regardless of the setting of r_extern. r_extern just reflects
- whether the symbol the reloc is against is local or global. */
- if (r_type == (unsigned int) RELOC_BASE10
- || r_type == (unsigned int) RELOC_BASE13
- || r_type == (unsigned int) RELOC_BASE22)
- r_extern = 1;
- if (r_extern && r_index > symcount)
- {
- /* We could arrange to return an error, but it might be useful
- to see the file even if it is bad. */
- r_extern = 0;
- r_index = N_ABS;
- }
- MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
- }
- void
- NAME (aout, swap_std_reloc_in) (bfd *abfd,
- struct reloc_std_external *bytes,
- arelent *cache_ptr,
- asymbol **symbols,
- bfd_size_type symcount)
- {
- unsigned int r_index;
- int r_extern;
- unsigned int r_length;
- int r_pcrel;
- int r_baserel, r_jmptable, r_relative;
- struct aoutdata *su = &(abfd->tdata.aout_data->a);
- unsigned int howto_idx;
- cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
- /* Now the fun stuff. */
- if (bfd_header_big_endian (abfd))
- {
- r_index = (((unsigned int) bytes->r_index[0] << 16)
- | ((unsigned int) bytes->r_index[1] << 8)
- | bytes->r_index[2]);
- r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
- r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
- r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
- r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
- r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
- r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
- >> RELOC_STD_BITS_LENGTH_SH_BIG);
- }
- else
- {
- r_index = (((unsigned int) bytes->r_index[2] << 16)
- | ((unsigned int) bytes->r_index[1] << 8)
- | bytes->r_index[0]);
- r_extern = (0 != (bytes->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
- r_pcrel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
- r_baserel = (0 != (bytes->r_type[0] & RELOC_STD_BITS_BASEREL_LITTLE));
- r_jmptable= (0 != (bytes->r_type[0] & RELOC_STD_BITS_JMPTABLE_LITTLE));
- r_relative= (0 != (bytes->r_type[0] & RELOC_STD_BITS_RELATIVE_LITTLE));
- r_length = ((bytes->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
- >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
- }
- howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel
- + 16 * r_jmptable + 32 * r_relative);
- if (howto_idx < TABLE_SIZE (howto_table_std))
- {
- cache_ptr->howto = howto_table_std + howto_idx;
- if (cache_ptr->howto->type == (unsigned int) -1)
- cache_ptr->howto = NULL;
- }
- else
- cache_ptr->howto = NULL;
- /* Base relative relocs are always against the symbol table,
- regardless of the setting of r_extern. r_extern just reflects
- whether the symbol the reloc is against is local or global. */
- if (r_baserel)
- r_extern = 1;
- if (r_extern && r_index >= symcount)
- {
- /* We could arrange to return an error, but it might be useful
- to see the file even if it is bad. FIXME: Of course this
- means that objdump -r *doesn't* see the actual reloc, and
- objcopy silently writes a different reloc. */
- r_extern = 0;
- r_index = N_ABS;
- }
- MOVE_ADDRESS (0);
- }
- /* Read and swap the relocs for a section. */
- bool
- NAME (aout, slurp_reloc_table) (bfd *abfd, sec_ptr asect, asymbol **symbols)
- {
- bfd_size_type count;
- bfd_size_type reloc_size;
- void * relocs;
- arelent *reloc_cache;
- size_t each_size;
- unsigned int counter = 0;
- arelent *cache_ptr;
- bfd_size_type amt;
- if (asect->relocation)
- return true;
- if (asect->flags & SEC_CONSTRUCTOR)
- return true;
- if (asect == obj_datasec (abfd))
- reloc_size = exec_hdr (abfd)->a_drsize;
- else if (asect == obj_textsec (abfd))
- reloc_size = exec_hdr (abfd)->a_trsize;
- else if (asect == obj_bsssec (abfd))
- reloc_size = 0;
- else
- {
- bfd_set_error (bfd_error_invalid_operation);
- return false;
- }
- each_size = obj_reloc_entry_size (abfd);
- count = reloc_size / each_size;
- if (count == 0)
- return true; /* Nothing to be done. */
- if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
- return false;
- relocs = _bfd_malloc_and_read (abfd, reloc_size, reloc_size);
- if (relocs == NULL)
- return false;
- amt = count * sizeof (arelent);
- reloc_cache = (arelent *) bfd_zmalloc (amt);
- if (reloc_cache == NULL)
- {
- free (relocs);
- return false;
- }
- cache_ptr = reloc_cache;
- if (each_size == RELOC_EXT_SIZE)
- {
- struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
- for (; counter < count; counter++, rptr++, cache_ptr++)
- MY_swap_ext_reloc_in (abfd, rptr, cache_ptr, symbols,
- (bfd_size_type) bfd_get_symcount (abfd));
- }
- else
- {
- struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
- for (; counter < count; counter++, rptr++, cache_ptr++)
- MY_swap_std_reloc_in (abfd, rptr, cache_ptr, symbols,
- (bfd_size_type) bfd_get_symcount (abfd));
- }
- free (relocs);
- asect->relocation = reloc_cache;
- asect->reloc_count = cache_ptr - reloc_cache;
- return true;
- }
- /* Write out a relocation section into an object file. */
- bool
- NAME (aout, squirt_out_relocs) (bfd *abfd, asection *section)
- {
- arelent **generic;
- unsigned char *native, *natptr;
- size_t each_size;
- unsigned int count = section->reloc_count;
- bfd_size_type natsize;
- if (count == 0 || section->orelocation == NULL)
- return true;
- each_size = obj_reloc_entry_size (abfd);
- natsize = (bfd_size_type) each_size * count;
- native = (unsigned char *) bfd_zalloc (abfd, natsize);
- if (!native)
- return false;
- generic = section->orelocation;
- if (each_size == RELOC_EXT_SIZE)
- {
- for (natptr = native;
- count != 0;
- --count, natptr += each_size, ++generic)
- {
- /* PR 20921: If the howto field has not been initialised then skip
- this reloc.
- PR 20929: Similarly for the symbol field. */
- if ((*generic)->howto == NULL
- || (*generic)->sym_ptr_ptr == NULL)
- {
- bfd_set_error (bfd_error_invalid_operation);
- _bfd_error_handler (_("%pB: attempt to write out "
- "unknown reloc type"), abfd);
- return false;
- }
- MY_swap_ext_reloc_out (abfd, *generic,
- (struct reloc_ext_external *) natptr);
- }
- }
- else
- {
- for (natptr = native;
- count != 0;
- --count, natptr += each_size, ++generic)
- {
- if ((*generic)->howto == NULL
- || (*generic)->sym_ptr_ptr == NULL)
- {
- bfd_set_error (bfd_error_invalid_operation);
- _bfd_error_handler (_("%pB: attempt to write out "
- "unknown reloc type"), abfd);
- return false;
- }
- MY_swap_std_reloc_out (abfd, *generic,
- (struct reloc_std_external *) natptr);
- }
- }
- if (bfd_bwrite ((void *) native, natsize, abfd) != natsize)
- {
- bfd_release (abfd, native);
- return false;
- }
- bfd_release (abfd, native);
- return true;
- }
- /* This is stupid. This function should be a boolean predicate. */
- long
- NAME (aout, canonicalize_reloc) (bfd *abfd,
- sec_ptr section,
- arelent **relptr,
- asymbol **symbols)
- {
- arelent *tblptr = section->relocation;
- unsigned int count;
- if (section == obj_bsssec (abfd))
- {
- *relptr = NULL;
- return 0;
- }
- if (!(tblptr || NAME (aout, slurp_reloc_table) (abfd, section, symbols)))
- return -1;
- if (section->flags & SEC_CONSTRUCTOR)
- {
- arelent_chain *chain = section->constructor_chain;
- for (count = 0; count < section->reloc_count; count ++)
- {
- *relptr ++ = &chain->relent;
- chain = chain->next;
- }
- }
- else
- {
- tblptr = section->relocation;
- for (count = 0; count++ < section->reloc_count; )
- {
- *relptr++ = tblptr++;
- }
- }
- *relptr = 0;
- return section->reloc_count;
- }
- long
- NAME (aout, get_reloc_upper_bound) (bfd *abfd, sec_ptr asect)
- {
- bfd_size_type count;
- if (bfd_get_format (abfd) != bfd_object)
- {
- bfd_set_error (bfd_error_invalid_operation);
- return -1;
- }
- if (asect->flags & SEC_CONSTRUCTOR)
- count = asect->reloc_count;
- else if (asect == obj_datasec (abfd))
- count = exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
- else if (asect == obj_textsec (abfd))
- count = exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
- else if (asect == obj_bsssec (abfd))
- count = 0;
- else
- {
- bfd_set_error (bfd_error_invalid_operation);
- return -1;
- }
- if (count >= LONG_MAX / sizeof (arelent *))
- {
- bfd_set_error (bfd_error_file_too_big);
- return -1;
- }
- return (count + 1) * sizeof (arelent *);
- }
- long
- NAME (aout, get_symtab_upper_bound) (bfd *abfd)
- {
- if (!NAME (aout, slurp_symbol_table) (abfd))
- return -1;
- return (bfd_get_symcount (abfd)+1) * (sizeof (aout_symbol_type *));
- }
- alent *
- NAME (aout, get_lineno) (bfd *ignore_abfd ATTRIBUTE_UNUSED,
- asymbol *ignore_symbol ATTRIBUTE_UNUSED)
- {
- return NULL;
- }
- void
- NAME (aout, get_symbol_info) (bfd *ignore_abfd ATTRIBUTE_UNUSED,
- asymbol *symbol,
- symbol_info *ret)
- {
- bfd_symbol_info (symbol, ret);
- if (ret->type == '?')
- {
- int type_code = aout_symbol (symbol)->type & 0xff;
- const char *stab_name = bfd_get_stab_name (type_code);
- static char buf[10];
- if (stab_name == NULL)
- {
- sprintf (buf, "(%d)", type_code);
- stab_name = buf;
- }
- ret->type = '-';
- ret->stab_type = type_code;
- ret->stab_other = (unsigned) (aout_symbol (symbol)->other & 0xff);
- ret->stab_desc = (unsigned) (aout_symbol (symbol)->desc & 0xffff);
- ret->stab_name = stab_name;
- }
- }
- void
- NAME (aout, print_symbol) (bfd *abfd,
- void * afile,
- asymbol *symbol,
- bfd_print_symbol_type how)
- {
- FILE *file = (FILE *)afile;
- switch (how)
- {
- case bfd_print_symbol_name:
- if (symbol->name)
- fprintf (file,"%s", symbol->name);
- break;
- case bfd_print_symbol_more:
- fprintf (file,"%4x %2x %2x",
- (unsigned) (aout_symbol (symbol)->desc & 0xffff),
- (unsigned) (aout_symbol (symbol)->other & 0xff),
- (unsigned) (aout_symbol (symbol)->type));
- break;
- case bfd_print_symbol_all:
- {
- const char *section_name = symbol->section->name;
- bfd_print_symbol_vandf (abfd, (void *)file, symbol);
- fprintf (file," %-5s %04x %02x %02x",
- section_name,
- (unsigned) (aout_symbol (symbol)->desc & 0xffff),
- (unsigned) (aout_symbol (symbol)->other & 0xff),
- (unsigned) (aout_symbol (symbol)->type & 0xff));
- if (symbol->name)
- fprintf (file," %s", symbol->name);
- }
- break;
- }
- }
- /* If we don't have to allocate more than 1MB to hold the generic
- symbols, we use the generic minisymbol methord: it's faster, since
- it only translates the symbols once, not multiple times. */
- #define MINISYM_THRESHOLD (1000000 / sizeof (asymbol))
- /* Read minisymbols. For minisymbols, we use the unmodified a.out
- symbols. The minisymbol_to_symbol function translates these into
- BFD asymbol structures. */
- long
- NAME (aout, read_minisymbols) (bfd *abfd,
- bool dynamic,
- void * *minisymsp,
- unsigned int *sizep)
- {
- if (dynamic)
- /* We could handle the dynamic symbols here as well, but it's
- easier to hand them off. */
- return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
- if (! aout_get_external_symbols (abfd))
- return -1;
- if (obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
- return _bfd_generic_read_minisymbols (abfd, dynamic, minisymsp, sizep);
- *minisymsp = (void *) obj_aout_external_syms (abfd);
- /* By passing the external symbols back from this routine, we are
- giving up control over the memory block. Clear
- obj_aout_external_syms, so that we do not try to free it
- ourselves. */
- obj_aout_external_syms (abfd) = NULL;
- *sizep = EXTERNAL_NLIST_SIZE;
- return obj_aout_external_sym_count (abfd);
- }
- /* Convert a minisymbol to a BFD asymbol. A minisymbol is just an
- unmodified a.out symbol. The SYM argument is a structure returned
- by bfd_make_empty_symbol, which we fill in here. */
- asymbol *
- NAME (aout, minisymbol_to_symbol) (bfd *abfd,
- bool dynamic,
- const void * minisym,
- asymbol *sym)
- {
- if (dynamic
- || obj_aout_external_sym_count (abfd) < MINISYM_THRESHOLD)
- return _bfd_generic_minisymbol_to_symbol (abfd, dynamic, minisym, sym);
- memset (sym, 0, sizeof (aout_symbol_type));
- /* We call translate_symbol_table to translate a single symbol. */
- if (! (NAME (aout, translate_symbol_table)
- (abfd,
- (aout_symbol_type *) sym,
- (struct external_nlist *) minisym,
- (bfd_size_type) 1,
- obj_aout_external_strings (abfd),
- obj_aout_external_string_size (abfd),
- false)))
- return NULL;
- return sym;
- }
- /* 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. */
- bool
- NAME (aout, find_nearest_line) (bfd *abfd,
- asymbol **symbols,
- asection *section,
- bfd_vma offset,
- const char **filename_ptr,
- const char **functionname_ptr,
- unsigned int *line_ptr,
- unsigned int *disriminator_ptr)
- {
- /* Run down the file looking for the filename, function and linenumber. */
- asymbol **p;
- const char *directory_name = NULL;
- const char *main_file_name = NULL;
- const char *current_file_name = NULL;
- const char *line_file_name = NULL; /* Value of current_file_name at line number. */
- const char *line_directory_name = NULL; /* Value of directory_name at line number. */
- bfd_vma low_line_vma = 0;
- bfd_vma low_func_vma = 0;
- asymbol *func = 0;
- bfd_size_type filelen, funclen;
- char *buf;
- *filename_ptr = bfd_get_filename (abfd);
- *functionname_ptr = NULL;
- *line_ptr = 0;
- if (disriminator_ptr)
- *disriminator_ptr = 0;
- if (symbols != NULL)
- {
- for (p = symbols; *p; p++)
- {
- aout_symbol_type *q = (aout_symbol_type *) (*p);
- next:
- switch (q->type)
- {
- case N_TEXT:
- /* If this looks like a file name symbol, and it comes after
- the line number we have found so far, but before the
- offset, then we have probably not found the right line
- number. */
- if (q->symbol.value <= offset
- && ((q->symbol.value > low_line_vma
- && (line_file_name != NULL
- || *line_ptr != 0))
- || (q->symbol.value > low_func_vma
- && func != NULL)))
- {
- const char *symname;
- symname = q->symbol.name;
- if (symname != NULL
- && strlen (symname) > 2
- && strcmp (symname + strlen (symname) - 2, ".o") == 0)
- {
- if (q->symbol.value > low_line_vma)
- {
- *line_ptr = 0;
- line_file_name = NULL;
- }
- if (q->symbol.value > low_func_vma)
- func = NULL;
- }
- }
- break;
- case N_SO:
- /* If this symbol is less than the offset, but greater than
- the line number we have found so far, then we have not
- found the right line number. */
- if (q->symbol.value <= offset)
- {
- if (q->symbol.value > low_line_vma)
- {
- *line_ptr = 0;
- line_file_name = NULL;
- }
- if (q->symbol.value > low_func_vma)
- func = NULL;
- }
- main_file_name = current_file_name = q->symbol.name;
- /* Look ahead to next symbol to check if that too is an N_SO. */
- p++;
- if (*p == NULL)
- goto done;
- q = (aout_symbol_type *) (*p);
- if (q->type != (int)N_SO)
- goto next;
- /* Found a second N_SO First is directory; second is filename. */
- directory_name = current_file_name;
- main_file_name = current_file_name = q->symbol.name;
- if (obj_textsec (abfd) != section)
- goto done;
- break;
- case N_SOL:
- current_file_name = q->symbol.name;
- break;
- case N_SLINE:
- case N_DSLINE:
- case N_BSLINE:
- /* We'll keep this if it resolves nearer than the one we have
- already. */
- if (q->symbol.value >= low_line_vma
- && q->symbol.value <= offset)
- {
- *line_ptr = q->desc;
- low_line_vma = q->symbol.value;
- line_file_name = current_file_name;
- line_directory_name = directory_name;
- }
- break;
- case N_FUN:
- {
- /* We'll keep this if it is nearer than the one we have already. */
- if (q->symbol.value >= low_func_vma
- && q->symbol.value <= offset)
- {
- low_func_vma = q->symbol.value;
- func = (asymbol *)q;
- }
- else if (q->symbol.value > offset)
- goto done;
- }
- break;
- }
- }
- }
- done:
- if (*line_ptr != 0)
- {
- main_file_name = line_file_name;
- directory_name = line_directory_name;
- }
- if (main_file_name == NULL
- || IS_ABSOLUTE_PATH (main_file_name)
- || directory_name == NULL)
- filelen = 0;
- else
- filelen = strlen (directory_name) + strlen (main_file_name);
- if (func == NULL)
- funclen = 0;
- else
- funclen = strlen (bfd_asymbol_name (func));
- free (adata (abfd).line_buf);
- if (filelen + funclen == 0)
- adata (abfd).line_buf = buf = NULL;
- else
- {
- buf = (char *) bfd_malloc (filelen + funclen + 3);
- adata (abfd).line_buf = buf;
- if (buf == NULL)
- return false;
- }
- if (main_file_name != NULL)
- {
- if (IS_ABSOLUTE_PATH (main_file_name) || directory_name == NULL)
- *filename_ptr = main_file_name;
- else
- {
- if (buf == NULL)
- /* PR binutils/20891: In a corrupt input file both
- main_file_name and directory_name can be empty... */
- * filename_ptr = NULL;
- else
- {
- snprintf (buf, filelen + 1, "%s%s", directory_name,
- main_file_name);
- *filename_ptr = buf;
- buf += filelen + 1;
- }
- }
- }
- if (func)
- {
- const char *function = func->name;
- char *colon;
- if (buf == NULL)
- {
- /* PR binutils/20892: In a corrupt input file func can be empty. */
- * functionname_ptr = NULL;
- return true;
- }
- /* The caller expects a symbol name. We actually have a
- function name, without the leading underscore. Put the
- underscore back in, so that the caller gets a symbol name. */
- if (bfd_get_symbol_leading_char (abfd) == '\0')
- strcpy (buf, function);
- else
- {
- buf[0] = bfd_get_symbol_leading_char (abfd);
- strcpy (buf + 1, function);
- }
- /* Have to remove : stuff. */
- colon = strchr (buf, ':');
- if (colon != NULL)
- *colon = '\0';
- *functionname_ptr = buf;
- }
- return true;
- }
- int
- NAME (aout, sizeof_headers) (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED)
- {
- return adata (abfd).exec_bytes_size;
- }
- /* Free all information we have cached for this BFD. We can always
- read it again later if we need it. */
- bool
- NAME (aout, bfd_free_cached_info) (bfd *abfd)
- {
- asection *o;
- if (bfd_get_format (abfd) != bfd_object
- || abfd->tdata.aout_data == NULL)
- return true;
- #define BFCI_FREE(x) do { free (x); x = NULL; } while (0)
- BFCI_FREE (obj_aout_symbols (abfd));
- #ifdef USE_MMAP
- obj_aout_external_syms (abfd) = 0;
- bfd_free_window (&obj_aout_sym_window (abfd));
- bfd_free_window (&obj_aout_string_window (abfd));
- obj_aout_external_strings (abfd) = 0;
- #else
- BFCI_FREE (obj_aout_external_syms (abfd));
- BFCI_FREE (obj_aout_external_strings (abfd));
- #endif
- for (o = abfd->sections; o != NULL; o = o->next)
- BFCI_FREE (o->relocation);
- #undef BFCI_FREE
- return true;
- }
- /* a.out link code. */
- /* Routine to create an entry in an a.out link hash table. */
- struct bfd_hash_entry *
- NAME (aout, link_hash_newfunc) (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string)
- {
- struct aout_link_hash_entry *ret = (struct aout_link_hash_entry *) entry;
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == NULL)
- ret = (struct aout_link_hash_entry *) bfd_hash_allocate (table,
- sizeof (* ret));
- if (ret == NULL)
- return NULL;
- /* Call the allocation method of the superclass. */
- ret = ((struct aout_link_hash_entry *)
- _bfd_link_hash_newfunc ((struct bfd_hash_entry *) ret,
- table, string));
- if (ret)
- {
- /* Set local fields. */
- ret->written = false;
- ret->indx = -1;
- }
- return (struct bfd_hash_entry *) ret;
- }
- /* Initialize an a.out link hash table. */
- bool
- NAME (aout, link_hash_table_init) (struct aout_link_hash_table *table,
- bfd *abfd,
- struct bfd_hash_entry *(*newfunc)
- (struct bfd_hash_entry *, struct bfd_hash_table *,
- const char *),
- unsigned int entsize)
- {
- return _bfd_link_hash_table_init (&table->root, abfd, newfunc, entsize);
- }
- /* Create an a.out link hash table. */
- struct bfd_link_hash_table *
- NAME (aout, link_hash_table_create) (bfd *abfd)
- {
- struct aout_link_hash_table *ret;
- size_t amt = sizeof (* ret);
- ret = (struct aout_link_hash_table *) bfd_malloc (amt);
- if (ret == NULL)
- return NULL;
- if (!NAME (aout, link_hash_table_init) (ret, abfd,
- NAME (aout, link_hash_newfunc),
- sizeof (struct aout_link_hash_entry)))
- {
- free (ret);
- return NULL;
- }
- return &ret->root;
- }
- /* Add all symbols from an object file to the hash table. */
- static bool
- aout_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
- {
- bool (*add_one_symbol)
- (struct bfd_link_info *, bfd *, const char *, flagword, asection *,
- bfd_vma, const char *, bool, bool, struct bfd_link_hash_entry **);
- struct external_nlist *syms;
- bfd_size_type sym_count;
- char *strings;
- bool copy;
- struct aout_link_hash_entry **sym_hash;
- struct external_nlist *p;
- struct external_nlist *pend;
- bfd_size_type amt;
- syms = obj_aout_external_syms (abfd);
- sym_count = obj_aout_external_sym_count (abfd);
- strings = obj_aout_external_strings (abfd);
- if (info->keep_memory)
- copy = false;
- else
- copy = true;
- if (aout_backend_info (abfd)->add_dynamic_symbols != NULL)
- {
- if (! ((*aout_backend_info (abfd)->add_dynamic_symbols)
- (abfd, info, &syms, &sym_count, &strings)))
- return false;
- }
- if (sym_count == 0)
- return true; /* Nothing to do. */
- /* We keep a list of the linker hash table entries that correspond
- to particular symbols. We could just look them up in the hash
- table, but keeping the list is more efficient. Perhaps this
- should be conditional on info->keep_memory. */
- amt = sym_count * sizeof (struct aout_link_hash_entry *);
- sym_hash = (struct aout_link_hash_entry **) bfd_alloc (abfd, amt);
- if (sym_hash == NULL)
- return false;
- obj_aout_sym_hashes (abfd) = sym_hash;
- add_one_symbol = aout_backend_info (abfd)->add_one_symbol;
- if (add_one_symbol == NULL)
- add_one_symbol = _bfd_generic_link_add_one_symbol;
- p = syms;
- pend = p + sym_count;
- for (; p < pend; p++, sym_hash++)
- {
- int type;
- const char *name;
- bfd_vma value;
- asection *section;
- flagword flags;
- const char *string;
- *sym_hash = NULL;
- type = H_GET_8 (abfd, p->e_type);
- /* Ignore debugging symbols. */
- if ((type & N_STAB) != 0)
- continue;
- /* PR 19629: Corrupt binaries can contain illegal string offsets. */
- if (GET_WORD (abfd, p->e_strx) >= obj_aout_external_string_size (abfd))
- return false;
- name = strings + GET_WORD (abfd, p->e_strx);
- value = GET_WORD (abfd, p->e_value);
- flags = BSF_GLOBAL;
- string = NULL;
- switch (type)
- {
- default:
- abort ();
- case N_UNDF:
- case N_ABS:
- case N_TEXT:
- case N_DATA:
- case N_BSS:
- case N_FN_SEQ:
- case N_COMM:
- case N_SETV:
- case N_FN:
- /* Ignore symbols that are not externally visible. */
- continue;
- case N_INDR:
- /* Ignore local indirect symbol. */
- ++p;
- ++sym_hash;
- continue;
- case N_UNDF | N_EXT:
- if (value == 0)
- {
- section = bfd_und_section_ptr;
- flags = 0;
- }
- else
- section = bfd_com_section_ptr;
- break;
- case N_ABS | N_EXT:
- section = bfd_abs_section_ptr;
- break;
- case N_TEXT | N_EXT:
- section = obj_textsec (abfd);
- value -= bfd_section_vma (section);
- break;
- case N_DATA | N_EXT:
- case N_SETV | N_EXT:
- /* Treat N_SETV symbols as N_DATA symbol; see comment in
- translate_from_native_sym_flags. */
- section = obj_datasec (abfd);
- value -= bfd_section_vma (section);
- break;
- case N_BSS | N_EXT:
- section = obj_bsssec (abfd);
- value -= bfd_section_vma (section);
- break;
- case N_INDR | N_EXT:
- /* An indirect symbol. The next symbol is the symbol
- which this one really is. */
- /* See PR 20925 for a reproducer. */
- if (p + 1 >= pend)
- return false;
- ++p;
- /* PR 19629: Corrupt binaries can contain illegal string offsets. */
- if (GET_WORD (abfd, p->e_strx) >= obj_aout_external_string_size (abfd))
- return false;
- string = strings + GET_WORD (abfd, p->e_strx);
- section = bfd_ind_section_ptr;
- flags |= BSF_INDIRECT;
- break;
- case N_COMM | N_EXT:
- section = bfd_com_section_ptr;
- break;
- case N_SETA: case N_SETA | N_EXT:
- section = bfd_abs_section_ptr;
- flags |= BSF_CONSTRUCTOR;
- break;
- case N_SETT: case N_SETT | N_EXT:
- section = obj_textsec (abfd);
- flags |= BSF_CONSTRUCTOR;
- value -= bfd_section_vma (section);
- break;
- case N_SETD: case N_SETD | N_EXT:
- section = obj_datasec (abfd);
- flags |= BSF_CONSTRUCTOR;
- value -= bfd_section_vma (section);
- break;
- case N_SETB: case N_SETB | N_EXT:
- section = obj_bsssec (abfd);
- flags |= BSF_CONSTRUCTOR;
- value -= bfd_section_vma (section);
- break;
- case N_WARNING:
- /* A warning symbol. The next symbol is the one to warn
- about. If there is no next symbol, just look away. */
- if (p + 1 >= pend)
- return true;
- ++p;
- string = name;
- /* PR 19629: Corrupt binaries can contain illegal string offsets. */
- if (GET_WORD (abfd, p->e_strx) >= obj_aout_external_string_size (abfd))
- return false;
- name = strings + GET_WORD (abfd, p->e_strx);
- section = bfd_und_section_ptr;
- flags |= BSF_WARNING;
- break;
- case N_WEAKU:
- section = bfd_und_section_ptr;
- flags = BSF_WEAK;
- break;
- case N_WEAKA:
- section = bfd_abs_section_ptr;
- flags = BSF_WEAK;
- break;
- case N_WEAKT:
- section = obj_textsec (abfd);
- value -= bfd_section_vma (section);
- flags = BSF_WEAK;
- break;
- case N_WEAKD:
- section = obj_datasec (abfd);
- value -= bfd_section_vma (section);
- flags = BSF_WEAK;
- break;
- case N_WEAKB:
- section = obj_bsssec (abfd);
- value -= bfd_section_vma (section);
- flags = BSF_WEAK;
- break;
- }
- if (! ((*add_one_symbol)
- (info, abfd, name, flags, section, value, string, copy, false,
- (struct bfd_link_hash_entry **) sym_hash)))
- return false;
- /* Restrict the maximum alignment of a common symbol based on
- the architecture, since a.out has no way to represent
- alignment requirements of a section in a .o file. FIXME:
- This isn't quite right: it should use the architecture of the
- output file, not the input files. */
- if ((*sym_hash)->root.type == bfd_link_hash_common
- && ((*sym_hash)->root.u.c.p->alignment_power >
- bfd_get_arch_info (abfd)->section_align_power))
- (*sym_hash)->root.u.c.p->alignment_power =
- bfd_get_arch_info (abfd)->section_align_power;
- /* If this is a set symbol, and we are not building sets, then
- it is possible for the hash entry to not have been set. In
- such a case, treat the symbol as not globally defined. */
- if ((*sym_hash)->root.type == bfd_link_hash_new)
- {
- BFD_ASSERT ((flags & BSF_CONSTRUCTOR) != 0);
- *sym_hash = NULL;
- }
- if (type == (N_INDR | N_EXT) || type == N_WARNING)
- ++sym_hash;
- }
- return true;
- }
- /* Free up the internal symbols read from an a.out file. */
- static bool
- aout_link_free_symbols (bfd *abfd)
- {
- if (obj_aout_external_syms (abfd) != NULL)
- {
- #ifdef USE_MMAP
- bfd_free_window (&obj_aout_sym_window (abfd));
- #else
- free ((void *) obj_aout_external_syms (abfd));
- #endif
- obj_aout_external_syms (abfd) = NULL;
- }
- if (obj_aout_external_strings (abfd) != NULL)
- {
- #ifdef USE_MMAP
- bfd_free_window (&obj_aout_string_window (abfd));
- #else
- free ((void *) obj_aout_external_strings (abfd));
- #endif
- obj_aout_external_strings (abfd) = NULL;
- }
- return true;
- }
- /* Add symbols from an a.out object file. */
- static bool
- aout_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
- {
- if (! aout_get_external_symbols (abfd))
- return false;
- if (! aout_link_add_symbols (abfd, info))
- return false;
- if (! info->keep_memory)
- {
- if (! aout_link_free_symbols (abfd))
- return false;
- }
- return true;
- }
- /* Look through the internal symbols to see if this object file should
- be included in the link. We should include this object file if it
- defines any symbols which are currently undefined. If this object
- file defines a common symbol, then we may adjust the size of the
- known symbol but we do not include the object file in the link
- (unless there is some other reason to include it). */
- static bool
- aout_link_check_ar_symbols (bfd *abfd,
- struct bfd_link_info *info,
- bool *pneeded,
- bfd **subsbfd)
- {
- struct external_nlist *p;
- struct external_nlist *pend;
- char *strings;
- *pneeded = false;
- /* Look through all the symbols. */
- p = obj_aout_external_syms (abfd);
- pend = p + obj_aout_external_sym_count (abfd);
- strings = obj_aout_external_strings (abfd);
- for (; p < pend; p++)
- {
- int type = H_GET_8 (abfd, p->e_type);
- const char *name;
- struct bfd_link_hash_entry *h;
- /* Ignore symbols that are not externally visible. This is an
- optimization only, as we check the type more thoroughly
- below. */
- if (((type & N_EXT) == 0
- || (type & N_STAB) != 0
- || type == N_FN)
- && type != N_WEAKA
- && type != N_WEAKT
- && type != N_WEAKD
- && type != N_WEAKB)
- {
- if (type == N_WARNING
- || type == N_INDR)
- ++p;
- continue;
- }
- name = strings + GET_WORD (abfd, p->e_strx);
- h = bfd_link_hash_lookup (info->hash, name, false, false, true);
- /* We are only interested in symbols that are currently
- undefined or common. */
- if (h == NULL
- || (h->type != bfd_link_hash_undefined
- && h->type != bfd_link_hash_common))
- {
- if (type == (N_INDR | N_EXT))
- ++p;
- continue;
- }
- if (type == (N_TEXT | N_EXT)
- || type == (N_DATA | N_EXT)
- || type == (N_BSS | N_EXT)
- || type == (N_ABS | N_EXT)
- || type == (N_INDR | N_EXT))
- {
- /* This object file defines this symbol. We must link it
- in. This is true regardless of whether the current
- definition of the symbol is undefined or common.
- If the current definition is common, we have a case in
- which we have already seen an object file including:
- int a;
- and this object file from the archive includes:
- int a = 5;
- In such a case, whether to include this object is target
- dependant for backward compatibility.
- FIXME: The SunOS 4.1.3 linker will pull in the archive
- element if the symbol is defined in the .data section,
- but not if it is defined in the .text section. That
- seems a bit crazy to me, and it has not been implemented
- yet. However, it might be correct. */
- if (h->type == bfd_link_hash_common)
- {
- int skip = 0;
- switch (info->common_skip_ar_symbols)
- {
- case bfd_link_common_skip_none:
- break;
- case bfd_link_common_skip_text:
- skip = (type == (N_TEXT | N_EXT));
- break;
- case bfd_link_common_skip_data:
- skip = (type == (N_DATA | N_EXT));
- break;
- case bfd_link_common_skip_all:
- skip = 1;
- break;
- }
- if (skip)
- continue;
- }
- if (!(*info->callbacks
- ->add_archive_element) (info, abfd, name, subsbfd))
- return false;
- *pneeded = true;
- return true;
- }
- if (type == (N_UNDF | N_EXT))
- {
- bfd_vma value;
- value = GET_WORD (abfd, p->e_value);
- if (value != 0)
- {
- /* This symbol is common in the object from the archive
- file. */
- if (h->type == bfd_link_hash_undefined)
- {
- bfd *symbfd;
- unsigned int power;
- symbfd = h->u.undef.abfd;
- if (symbfd == NULL)
- {
- /* This symbol was created as undefined from
- outside BFD. We assume that we should link
- in the object file. This is done for the -u
- option in the linker. */
- if (!(*info->callbacks
- ->add_archive_element) (info, abfd, name, subsbfd))
- return false;
- *pneeded = true;
- return true;
- }
- /* Turn the current link symbol into a common
- symbol. It is already on the undefs list. */
- h->type = bfd_link_hash_common;
- h->u.c.p = (struct bfd_link_hash_common_entry *)
- bfd_hash_allocate (&info->hash->table,
- sizeof (struct bfd_link_hash_common_entry));
- if (h->u.c.p == NULL)
- return false;
- h->u.c.size = value;
- /* FIXME: This isn't quite right. The maximum
- alignment of a common symbol should be set by the
- architecture of the output file, not of the input
- file. */
- power = bfd_log2 (value);
- if (power > bfd_get_arch_info (abfd)->section_align_power)
- power = bfd_get_arch_info (abfd)->section_align_power;
- h->u.c.p->alignment_power = power;
- h->u.c.p->section = bfd_make_section_old_way (symbfd,
- "COMMON");
- }
- else
- {
- /* Adjust the size of the common symbol if
- necessary. */
- if (value > h->u.c.size)
- h->u.c.size = value;
- }
- }
- }
- if (type == N_WEAKA
- || type == N_WEAKT
- || type == N_WEAKD
- || type == N_WEAKB)
- {
- /* This symbol is weak but defined. We must pull it in if
- the current link symbol is undefined, but we don't want
- it if the current link symbol is common. */
- if (h->type == bfd_link_hash_undefined)
- {
- if (!(*info->callbacks
- ->add_archive_element) (info, abfd, name, subsbfd))
- return false;
- *pneeded = true;
- return true;
- }
- }
- }
- /* We do not need this object file. */
- return true;
- }
- /* Check a single archive element to see if we need to include it in
- the link. *PNEEDED is set according to whether this element is
- needed in the link or not. This is called from
- _bfd_generic_link_add_archive_symbols. */
- static bool
- aout_link_check_archive_element (bfd *abfd,
- struct bfd_link_info *info,
- struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED,
- const char *name ATTRIBUTE_UNUSED,
- bool *pneeded)
- {
- bfd *oldbfd;
- bool needed;
- if (!aout_get_external_symbols (abfd))
- return false;
- oldbfd = abfd;
- if (!aout_link_check_ar_symbols (abfd, info, pneeded, &abfd))
- return false;
- needed = *pneeded;
- if (needed)
- {
- /* Potentially, the add_archive_element hook may have set a
- substitute BFD for us. */
- if (abfd != oldbfd)
- {
- if (!info->keep_memory
- && !aout_link_free_symbols (oldbfd))
- return false;
- if (!aout_get_external_symbols (abfd))
- return false;
- }
- if (!aout_link_add_symbols (abfd, info))
- return false;
- }
- if (!info->keep_memory || !needed)
- {
- if (!aout_link_free_symbols (abfd))
- return false;
- }
- return true;
- }
- /* Given an a.out BFD, add symbols to the global hash table as
- appropriate. */
- bool
- NAME (aout, link_add_symbols) (bfd *abfd, struct bfd_link_info *info)
- {
- switch (bfd_get_format (abfd))
- {
- case bfd_object:
- return aout_link_add_object_symbols (abfd, info);
- case bfd_archive:
- return _bfd_generic_link_add_archive_symbols
- (abfd, info, aout_link_check_archive_element);
- default:
- bfd_set_error (bfd_error_wrong_format);
- return false;
- }
- }
- /* A hash table used for header files with N_BINCL entries. */
- struct aout_link_includes_table
- {
- struct bfd_hash_table root;
- };
- /* A linked list of totals that we have found for a particular header
- file. */
- struct aout_link_includes_totals
- {
- struct aout_link_includes_totals *next;
- bfd_vma total;
- };
- /* An entry in the header file hash table. */
- struct aout_link_includes_entry
- {
- struct bfd_hash_entry root;
- /* List of totals we have found for this file. */
- struct aout_link_includes_totals *totals;
- };
- /* Look up an entry in an the header file hash table. */
- #define aout_link_includes_lookup(table, string, create, copy) \
- ((struct aout_link_includes_entry *) \
- bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
- /* During the final link step we need to pass around a bunch of
- information, so we do it in an instance of this structure. */
- struct aout_final_link_info
- {
- /* General link information. */
- struct bfd_link_info *info;
- /* Output bfd. */
- bfd *output_bfd;
- /* Reloc file positions. */
- file_ptr treloff, dreloff;
- /* File position of symbols. */
- file_ptr symoff;
- /* String table. */
- struct bfd_strtab_hash *strtab;
- /* Header file hash table. */
- struct aout_link_includes_table includes;
- /* A buffer large enough to hold the contents of any section. */
- bfd_byte *contents;
- /* A buffer large enough to hold the relocs of any section. */
- void * relocs;
- /* A buffer large enough to hold the symbol map of any input BFD. */
- int *symbol_map;
- /* A buffer large enough to hold output symbols of any input BFD. */
- struct external_nlist *output_syms;
- };
- /* The function to create a new entry in the header file hash table. */
- static struct bfd_hash_entry *
- aout_link_includes_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string)
- {
- struct aout_link_includes_entry *ret =
- (struct aout_link_includes_entry *) entry;
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (ret == NULL)
- ret = (struct aout_link_includes_entry *)
- bfd_hash_allocate (table, sizeof (* ret));
- if (ret == NULL)
- return NULL;
- /* Call the allocation method of the superclass. */
- ret = ((struct aout_link_includes_entry *)
- bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
- if (ret)
- {
- /* Set local fields. */
- ret->totals = NULL;
- }
- return (struct bfd_hash_entry *) ret;
- }
- /* Write out a symbol that was not associated with an a.out input
- object. */
- static bool
- aout_link_write_other_symbol (struct bfd_hash_entry *bh, void *data)
- {
- struct aout_link_hash_entry *h = (struct aout_link_hash_entry *) bh;
- struct aout_final_link_info *flaginfo = (struct aout_final_link_info *) data;
- bfd *output_bfd;
- int type;
- bfd_vma val;
- struct external_nlist outsym;
- bfd_size_type indx;
- size_t amt;
- if (h->root.type == bfd_link_hash_warning)
- {
- h = (struct aout_link_hash_entry *) h->root.u.i.link;
- if (h->root.type == bfd_link_hash_new)
- return true;
- }
- output_bfd = flaginfo->output_bfd;
- if (aout_backend_info (output_bfd)->write_dynamic_symbol != NULL)
- {
- if (! ((*aout_backend_info (output_bfd)->write_dynamic_symbol)
- (output_bfd, flaginfo->info, h)))
- {
- /* FIXME: No way to handle errors. */
- abort ();
- }
- }
- if (h->written)
- return true;
- h->written = true;
- /* An indx of -2 means the symbol must be written. */
- if (h->indx != -2
- && (flaginfo->info->strip == strip_all
- || (flaginfo->info->strip == strip_some
- && bfd_hash_lookup (flaginfo->info->keep_hash, h->root.root.string,
- false, false) == NULL)))
- return true;
- switch (h->root.type)
- {
- default:
- case bfd_link_hash_warning:
- abort ();
- /* Avoid variable not initialized warnings. */
- return true;
- case bfd_link_hash_new:
- /* This can happen for set symbols when sets are not being
- built. */
- return true;
- case bfd_link_hash_undefined:
- type = N_UNDF | N_EXT;
- val = 0;
- break;
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- {
- asection *sec;
- sec = h->root.u.def.section->output_section;
- BFD_ASSERT (bfd_is_abs_section (sec)
- || sec->owner == output_bfd);
- if (sec == obj_textsec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_TEXT : N_WEAKT;
- else if (sec == obj_datasec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_DATA : N_WEAKD;
- else if (sec == obj_bsssec (output_bfd))
- type = h->root.type == bfd_link_hash_defined ? N_BSS : N_WEAKB;
- else
- type = h->root.type == bfd_link_hash_defined ? N_ABS : N_WEAKA;
- type |= N_EXT;
- val = (h->root.u.def.value
- + sec->vma
- + h->root.u.def.section->output_offset);
- }
- break;
- case bfd_link_hash_common:
- type = N_UNDF | N_EXT;
- val = h->root.u.c.size;
- break;
- case bfd_link_hash_undefweak:
- type = N_WEAKU;
- val = 0;
- break;
- case bfd_link_hash_indirect:
- /* We ignore these symbols, since the indirected symbol is
- already in the hash table. */
- return true;
- }
- H_PUT_8 (output_bfd, type, outsym.e_type);
- H_PUT_8 (output_bfd, 0, outsym.e_other);
- H_PUT_16 (output_bfd, 0, outsym.e_desc);
- indx = add_to_stringtab (output_bfd, flaginfo->strtab, h->root.root.string,
- false);
- if (indx == - (bfd_size_type) 1)
- /* FIXME: No way to handle errors. */
- abort ();
- PUT_WORD (output_bfd, indx, outsym.e_strx);
- PUT_WORD (output_bfd, val, outsym.e_value);
- amt = EXTERNAL_NLIST_SIZE;
- if (bfd_seek (output_bfd, flaginfo->symoff, SEEK_SET) != 0
- || bfd_bwrite ((void *) &outsym, amt, output_bfd) != amt)
- /* FIXME: No way to handle errors. */
- abort ();
- flaginfo->symoff += EXTERNAL_NLIST_SIZE;
- h->indx = obj_aout_external_sym_count (output_bfd);
- ++obj_aout_external_sym_count (output_bfd);
- return true;
- }
- /* Handle a link order which is supposed to generate a reloc. */
- static bool
- aout_link_reloc_link_order (struct aout_final_link_info *flaginfo,
- asection *o,
- struct bfd_link_order *p)
- {
- struct bfd_link_order_reloc *pr;
- int r_index;
- int r_extern;
- reloc_howto_type *howto;
- file_ptr *reloff_ptr = NULL;
- struct reloc_std_external srel;
- struct reloc_ext_external erel;
- void * rel_ptr;
- size_t amt;
- pr = p->u.reloc.p;
- if (p->type == bfd_section_reloc_link_order)
- {
- r_extern = 0;
- if (bfd_is_abs_section (pr->u.section))
- r_index = N_ABS | N_EXT;
- else
- {
- BFD_ASSERT (pr->u.section->owner == flaginfo->output_bfd);
- r_index = pr->u.section->target_index;
- }
- }
- else
- {
- struct aout_link_hash_entry *h;
- BFD_ASSERT (p->type == bfd_symbol_reloc_link_order);
- r_extern = 1;
- h = ((struct aout_link_hash_entry *)
- bfd_wrapped_link_hash_lookup (flaginfo->output_bfd, flaginfo->info,
- pr->u.name, false, false, true));
- if (h != NULL
- && h->indx >= 0)
- r_index = h->indx;
- else if (h != NULL)
- {
- /* We decided to strip this symbol, but it turns out that we
- can't. Note that we lose the other and desc information
- here. I don't think that will ever matter for a global
- symbol. */
- h->indx = -2;
- h->written = false;
- if (!aout_link_write_other_symbol (&h->root.root, flaginfo))
- return false;
- r_index = h->indx;
- }
- else
- {
- (*flaginfo->info->callbacks->unattached_reloc)
- (flaginfo->info, pr->u.name, NULL, NULL, (bfd_vma) 0);
- r_index = 0;
- }
- }
- howto = bfd_reloc_type_lookup (flaginfo->output_bfd, pr->reloc);
- if (howto == 0)
- {
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- if (o == obj_textsec (flaginfo->output_bfd))
- reloff_ptr = &flaginfo->treloff;
- else if (o == obj_datasec (flaginfo->output_bfd))
- reloff_ptr = &flaginfo->dreloff;
- else
- abort ();
- if (obj_reloc_entry_size (flaginfo->output_bfd) == RELOC_STD_SIZE)
- {
- #ifdef MY_put_reloc
- MY_put_reloc (flaginfo->output_bfd, r_extern, r_index, p->offset, howto,
- &srel);
- #else
- {
- int r_pcrel;
- int r_baserel;
- int r_jmptable;
- int r_relative;
- unsigned int r_length;
- r_pcrel = (int) howto->pc_relative;
- r_baserel = (howto->type & 8) != 0;
- r_jmptable = (howto->type & 16) != 0;
- r_relative = (howto->type & 32) != 0;
- if (bfd_get_reloc_size (howto) != 8)
- r_length = howto->size; /* Size as a power of two. */
- else
- r_length = 3;
- PUT_WORD (flaginfo->output_bfd, p->offset, srel.r_address);
- if (bfd_header_big_endian (flaginfo->output_bfd))
- {
- srel.r_index[0] = r_index >> 16;
- srel.r_index[1] = r_index >> 8;
- srel.r_index[2] = r_index;
- srel.r_type[0] =
- ((r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
- | (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
- | (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
- | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
- | (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
- | (r_length << RELOC_STD_BITS_LENGTH_SH_BIG));
- }
- else
- {
- srel.r_index[2] = r_index >> 16;
- srel.r_index[1] = r_index >> 8;
- srel.r_index[0] = r_index;
- srel.r_type[0] =
- ((r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
- | (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
- | (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
- | (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
- | (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
- | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE));
- }
- }
- #endif
- rel_ptr = (void *) &srel;
- /* We have to write the addend into the object file, since
- standard a.out relocs are in place. It would be more
- reliable if we had the current contents of the file here,
- rather than assuming zeroes, but we can't read the file since
- it was opened using bfd_openw. */
- if (pr->addend != 0)
- {
- bfd_size_type size;
- bfd_reloc_status_type r;
- bfd_byte *buf;
- bool ok;
- size = bfd_get_reloc_size (howto);
- buf = (bfd_byte *) bfd_zmalloc (size);
- if (buf == NULL && size != 0)
- return false;
- r = MY_relocate_contents (howto, flaginfo->output_bfd,
- (bfd_vma) pr->addend, buf);
- switch (r)
- {
- case bfd_reloc_ok:
- break;
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- (*flaginfo->info->callbacks->reloc_overflow)
- (flaginfo->info, NULL,
- (p->type == bfd_section_reloc_link_order
- ? bfd_section_name (pr->u.section)
- : pr->u.name),
- howto->name, pr->addend, NULL, NULL, (bfd_vma) 0);
- break;
- }
- ok = bfd_set_section_contents (flaginfo->output_bfd, o, (void *) buf,
- (file_ptr) p->offset, size);
- free (buf);
- if (! ok)
- return false;
- }
- }
- else
- {
- #ifdef MY_put_ext_reloc
- MY_put_ext_reloc (flaginfo->output_bfd, r_extern, r_index, p->offset,
- howto, &erel, pr->addend);
- #else
- PUT_WORD (flaginfo->output_bfd, p->offset, erel.r_address);
- if (bfd_header_big_endian (flaginfo->output_bfd))
- {
- erel.r_index[0] = r_index >> 16;
- erel.r_index[1] = r_index >> 8;
- erel.r_index[2] = r_index;
- erel.r_type[0] =
- ((r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
- | (howto->type << RELOC_EXT_BITS_TYPE_SH_BIG));
- }
- else
- {
- erel.r_index[2] = r_index >> 16;
- erel.r_index[1] = r_index >> 8;
- erel.r_index[0] = r_index;
- erel.r_type[0] =
- (r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
- | (howto->type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
- }
- PUT_WORD (flaginfo->output_bfd, (bfd_vma) pr->addend, erel.r_addend);
- #endif /* MY_put_ext_reloc */
- rel_ptr = (void *) &erel;
- }
- amt = obj_reloc_entry_size (flaginfo->output_bfd);
- if (bfd_seek (flaginfo->output_bfd, *reloff_ptr, SEEK_SET) != 0
- || bfd_bwrite (rel_ptr, amt, flaginfo->output_bfd) != amt)
- return false;
- *reloff_ptr += obj_reloc_entry_size (flaginfo->output_bfd);
- /* Assert that the relocs have not run into the symbols, and that n
- the text relocs have not run into the data relocs. */
- BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (flaginfo->output_bfd)
- && (reloff_ptr != &flaginfo->treloff
- || (*reloff_ptr
- <= obj_datasec (flaginfo->output_bfd)->rel_filepos)));
- return true;
- }
- /* Get the section corresponding to a reloc index. */
- static inline asection *
- aout_reloc_index_to_section (bfd *abfd, int indx)
- {
- switch (indx & N_TYPE)
- {
- case N_TEXT: return obj_textsec (abfd);
- case N_DATA: return obj_datasec (abfd);
- case N_BSS: return obj_bsssec (abfd);
- case N_ABS:
- case N_UNDF: return bfd_abs_section_ptr;
- default: abort ();
- }
- return NULL;
- }
- /* Relocate an a.out section using standard a.out relocs. */
- static bool
- aout_link_input_section_std (struct aout_final_link_info *flaginfo,
- bfd *input_bfd,
- asection *input_section,
- struct reloc_std_external *relocs,
- bfd_size_type rel_size,
- bfd_byte *contents)
- {
- bool (*check_dynamic_reloc)
- (struct bfd_link_info *, bfd *, asection *,
- struct aout_link_hash_entry *, void *, bfd_byte *, bool *, bfd_vma *);
- bfd *output_bfd;
- bool relocatable;
- struct external_nlist *syms;
- char *strings;
- struct aout_link_hash_entry **sym_hashes;
- int *symbol_map;
- bfd_size_type reloc_count;
- struct reloc_std_external *rel;
- struct reloc_std_external *rel_end;
- output_bfd = flaginfo->output_bfd;
- check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
- BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE);
- BFD_ASSERT (input_bfd->xvec->header_byteorder
- == output_bfd->xvec->header_byteorder);
- relocatable = bfd_link_relocatable (flaginfo->info);
- syms = obj_aout_external_syms (input_bfd);
- strings = obj_aout_external_strings (input_bfd);
- sym_hashes = obj_aout_sym_hashes (input_bfd);
- symbol_map = flaginfo->symbol_map;
- reloc_count = rel_size / RELOC_STD_SIZE;
- rel = relocs;
- rel_end = rel + reloc_count;
- for (; rel < rel_end; rel++)
- {
- bfd_vma r_addr;
- unsigned int r_index;
- int r_extern;
- int r_pcrel;
- int r_baserel = 0;
- reloc_howto_type *howto;
- struct aout_link_hash_entry *h = NULL;
- bfd_vma relocation;
- bfd_reloc_status_type r;
- r_addr = GET_SWORD (input_bfd, rel->r_address);
- #ifdef MY_reloc_howto
- howto = MY_reloc_howto (input_bfd, rel, r_index, r_extern, r_pcrel);
- #else
- {
- int r_jmptable;
- int r_relative;
- int r_length;
- unsigned int howto_idx;
- if (bfd_header_big_endian (input_bfd))
- {
- r_index = (((unsigned int) rel->r_index[0] << 16)
- | ((unsigned int) rel->r_index[1] << 8)
- | rel->r_index[2]);
- r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG));
- r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_BIG));
- r_baserel = (0 != (rel->r_type[0] & RELOC_STD_BITS_BASEREL_BIG));
- r_jmptable= (0 != (rel->r_type[0] & RELOC_STD_BITS_JMPTABLE_BIG));
- r_relative= (0 != (rel->r_type[0] & RELOC_STD_BITS_RELATIVE_BIG));
- r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_BIG)
- >> RELOC_STD_BITS_LENGTH_SH_BIG);
- }
- else
- {
- r_index = (((unsigned int) rel->r_index[2] << 16)
- | ((unsigned int) rel->r_index[1] << 8)
- | rel->r_index[0]);
- r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
- r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
- r_baserel = (0 != (rel->r_type[0]
- & RELOC_STD_BITS_BASEREL_LITTLE));
- r_jmptable= (0 != (rel->r_type[0]
- & RELOC_STD_BITS_JMPTABLE_LITTLE));
- r_relative= (0 != (rel->r_type[0]
- & RELOC_STD_BITS_RELATIVE_LITTLE));
- r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
- >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
- }
- howto_idx = (r_length + 4 * r_pcrel + 8 * r_baserel
- + 16 * r_jmptable + 32 * r_relative);
- if (howto_idx < TABLE_SIZE (howto_table_std))
- howto = howto_table_std + howto_idx;
- else
- howto = NULL;
- }
- #endif
- if (howto == NULL)
- {
- _bfd_error_handler (_("%pB: unsupported relocation type"),
- input_bfd);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- if (relocatable)
- {
- /* We are generating a relocatable output file, and must
- modify the reloc accordingly. */
- if (r_extern)
- {
- /* If we know the symbol this relocation is against,
- convert it into a relocation against a section. This
- is what the native linker does. */
- h = sym_hashes[r_index];
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- asection *output_section;
- /* Change the r_extern value. */
- if (bfd_header_big_endian (output_bfd))
- rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_BIG;
- else
- rel->r_type[0] &=~ RELOC_STD_BITS_EXTERN_LITTLE;
- /* Compute a new r_index. */
- output_section = h->root.u.def.section->output_section;
- if (output_section == obj_textsec (output_bfd))
- r_index = N_TEXT;
- else if (output_section == obj_datasec (output_bfd))
- r_index = N_DATA;
- else if (output_section == obj_bsssec (output_bfd))
- r_index = N_BSS;
- else
- r_index = N_ABS;
- /* Add the symbol value and the section VMA to the
- addend stored in the contents. */
- relocation = (h->root.u.def.value
- + output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else
- {
- /* We must change r_index according to the symbol
- map. */
- r_index = symbol_map[r_index];
- if (r_index == -1u)
- {
- if (h != NULL)
- {
- /* We decided to strip this symbol, but it
- turns out that we can't. Note that we
- lose the other and desc information here.
- I don't think that will ever matter for a
- global symbol. */
- if (h->indx < 0)
- {
- h->indx = -2;
- h->written = false;
- if (!aout_link_write_other_symbol (&h->root.root,
- flaginfo))
- return false;
- }
- r_index = h->indx;
- }
- else
- {
- const char *name;
- name = strings + GET_WORD (input_bfd,
- syms[r_index].e_strx);
- (*flaginfo->info->callbacks->unattached_reloc)
- (flaginfo->info, name,
- input_bfd, input_section, r_addr);
- r_index = 0;
- }
- }
- relocation = 0;
- }
- /* Write out the new r_index value. */
- if (bfd_header_big_endian (output_bfd))
- {
- rel->r_index[0] = r_index >> 16;
- rel->r_index[1] = r_index >> 8;
- rel->r_index[2] = r_index;
- }
- else
- {
- rel->r_index[2] = r_index >> 16;
- rel->r_index[1] = r_index >> 8;
- rel->r_index[0] = r_index;
- }
- }
- else
- {
- asection *section;
- /* This is a relocation against a section. We must
- adjust by the amount that the section moved. */
- section = aout_reloc_index_to_section (input_bfd, r_index);
- relocation = (section->output_section->vma
- + section->output_offset
- - section->vma);
- }
- /* Change the address of the relocation. */
- PUT_WORD (output_bfd,
- r_addr + input_section->output_offset,
- rel->r_address);
- /* Adjust a PC relative relocation by removing the reference
- to the original address in the section and including the
- reference to the new address. */
- if (r_pcrel)
- relocation -= (input_section->output_section->vma
- + input_section->output_offset
- - input_section->vma);
- #ifdef MY_relocatable_reloc
- MY_relocatable_reloc (howto, output_bfd, rel, relocation, r_addr);
- #endif
- if (relocation == 0)
- r = bfd_reloc_ok;
- else
- r = MY_relocate_contents (howto,
- input_bfd, relocation,
- contents + r_addr);
- }
- else
- {
- bool hundef;
- /* We are generating an executable, and must do a full
- relocation. */
- hundef = false;
- if (r_extern)
- {
- h = sym_hashes[r_index];
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- relocation = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else if (h != NULL
- && h->root.type == bfd_link_hash_undefweak)
- relocation = 0;
- else
- {
- hundef = true;
- relocation = 0;
- }
- }
- else
- {
- asection *section;
- section = aout_reloc_index_to_section (input_bfd, r_index);
- relocation = (section->output_section->vma
- + section->output_offset
- - section->vma);
- if (r_pcrel)
- relocation += input_section->vma;
- }
- if (check_dynamic_reloc != NULL)
- {
- bool skip;
- if (! ((*check_dynamic_reloc)
- (flaginfo->info, input_bfd, input_section, h,
- (void *) rel, contents, &skip, &relocation)))
- return false;
- if (skip)
- continue;
- }
- /* Now warn if a global symbol is undefined. We could not
- do this earlier, because check_dynamic_reloc might want
- to skip this reloc. */
- if (hundef && ! bfd_link_pic (flaginfo->info) && ! r_baserel)
- {
- const char *name;
- if (h != NULL)
- name = h->root.root.string;
- else
- name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
- (*flaginfo->info->callbacks->undefined_symbol)
- (flaginfo->info, name, input_bfd, input_section, r_addr, true);
- }
- r = MY_final_link_relocate (howto,
- input_bfd, input_section,
- contents, r_addr, relocation,
- (bfd_vma) 0);
- }
- if (r != bfd_reloc_ok)
- {
- switch (r)
- {
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- {
- const char *name;
- if (h != NULL)
- name = NULL;
- else if (r_extern)
- name = strings + GET_WORD (input_bfd,
- syms[r_index].e_strx);
- else
- {
- asection *s;
- s = aout_reloc_index_to_section (input_bfd, r_index);
- name = bfd_section_name (s);
- }
- (*flaginfo->info->callbacks->reloc_overflow)
- (flaginfo->info, (h ? &h->root : NULL), name, howto->name,
- (bfd_vma) 0, input_bfd, input_section, r_addr);
- }
- break;
- }
- }
- }
- return true;
- }
- /* Relocate an a.out section using extended a.out relocs. */
- static bool
- aout_link_input_section_ext (struct aout_final_link_info *flaginfo,
- bfd *input_bfd,
- asection *input_section,
- struct reloc_ext_external *relocs,
- bfd_size_type rel_size,
- bfd_byte *contents)
- {
- bool (*check_dynamic_reloc)
- (struct bfd_link_info *, bfd *, asection *,
- struct aout_link_hash_entry *, void *, bfd_byte *, bool *, bfd_vma *);
- bfd *output_bfd;
- bool relocatable;
- struct external_nlist *syms;
- char *strings;
- struct aout_link_hash_entry **sym_hashes;
- int *symbol_map;
- bfd_size_type reloc_count;
- struct reloc_ext_external *rel;
- struct reloc_ext_external *rel_end;
- output_bfd = flaginfo->output_bfd;
- check_dynamic_reloc = aout_backend_info (output_bfd)->check_dynamic_reloc;
- BFD_ASSERT (obj_reloc_entry_size (input_bfd) == RELOC_EXT_SIZE);
- BFD_ASSERT (input_bfd->xvec->header_byteorder
- == output_bfd->xvec->header_byteorder);
- relocatable = bfd_link_relocatable (flaginfo->info);
- syms = obj_aout_external_syms (input_bfd);
- strings = obj_aout_external_strings (input_bfd);
- sym_hashes = obj_aout_sym_hashes (input_bfd);
- symbol_map = flaginfo->symbol_map;
- reloc_count = rel_size / RELOC_EXT_SIZE;
- rel = relocs;
- rel_end = rel + reloc_count;
- for (; rel < rel_end; rel++)
- {
- bfd_vma r_addr;
- unsigned int r_index;
- int r_extern;
- unsigned int r_type;
- bfd_vma r_addend;
- struct aout_link_hash_entry *h = NULL;
- asection *r_section = NULL;
- bfd_vma relocation;
- r_addr = GET_SWORD (input_bfd, rel->r_address);
- if (bfd_header_big_endian (input_bfd))
- {
- r_index = (((unsigned int) rel->r_index[0] << 16)
- | ((unsigned int) rel->r_index[1] << 8)
- | rel->r_index[2]);
- r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_BIG));
- r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_BIG)
- >> RELOC_EXT_BITS_TYPE_SH_BIG);
- }
- else
- {
- r_index = (((unsigned int) rel->r_index[2] << 16)
- | ((unsigned int) rel->r_index[1] << 8)
- | rel->r_index[0]);
- r_extern = (0 != (rel->r_type[0] & RELOC_EXT_BITS_EXTERN_LITTLE));
- r_type = ((rel->r_type[0] & RELOC_EXT_BITS_TYPE_LITTLE)
- >> RELOC_EXT_BITS_TYPE_SH_LITTLE);
- }
- r_addend = GET_SWORD (input_bfd, rel->r_addend);
- if (r_type >= TABLE_SIZE (howto_table_ext))
- {
- _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
- input_bfd, r_type);
- bfd_set_error (bfd_error_bad_value);
- return false;
- }
- if (relocatable)
- {
- /* We are generating a relocatable output file, and must
- modify the reloc accordingly. */
- if (r_extern
- || r_type == (unsigned int) RELOC_BASE10
- || r_type == (unsigned int) RELOC_BASE13
- || r_type == (unsigned int) RELOC_BASE22)
- {
- /* If we know the symbol this relocation is against,
- convert it into a relocation against a section. This
- is what the native linker does. */
- if (r_type == (unsigned int) RELOC_BASE10
- || r_type == (unsigned int) RELOC_BASE13
- || r_type == (unsigned int) RELOC_BASE22)
- h = NULL;
- else
- h = sym_hashes[r_index];
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- asection *output_section;
- /* Change the r_extern value. */
- if (bfd_header_big_endian (output_bfd))
- rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_BIG;
- else
- rel->r_type[0] &=~ RELOC_EXT_BITS_EXTERN_LITTLE;
- /* Compute a new r_index. */
- output_section = h->root.u.def.section->output_section;
- if (output_section == obj_textsec (output_bfd))
- r_index = N_TEXT;
- else if (output_section == obj_datasec (output_bfd))
- r_index = N_DATA;
- else if (output_section == obj_bsssec (output_bfd))
- r_index = N_BSS;
- else
- r_index = N_ABS;
- /* Add the symbol value and the section VMA to the
- addend. */
- relocation = (h->root.u.def.value
- + output_section->vma
- + h->root.u.def.section->output_offset);
- /* Now RELOCATION is the VMA of the final
- destination. If this is a PC relative reloc,
- then ADDEND is the negative of the source VMA.
- We want to set ADDEND to the difference between
- the destination VMA and the source VMA, which
- means we must adjust RELOCATION by the change in
- the source VMA. This is done below. */
- }
- else
- {
- /* We must change r_index according to the symbol
- map. */
- r_index = symbol_map[r_index];
- if (r_index == -1u)
- {
- if (h != NULL)
- {
- /* We decided to strip this symbol, but it
- turns out that we can't. Note that we
- lose the other and desc information here.
- I don't think that will ever matter for a
- global symbol. */
- if (h->indx < 0)
- {
- h->indx = -2;
- h->written = false;
- if (!aout_link_write_other_symbol (&h->root.root,
- flaginfo))
- return false;
- }
- r_index = h->indx;
- }
- else
- {
- const char *name;
- name = strings + GET_WORD (input_bfd,
- syms[r_index].e_strx);
- (*flaginfo->info->callbacks->unattached_reloc)
- (flaginfo->info, name,
- input_bfd, input_section, r_addr);
- r_index = 0;
- }
- }
- relocation = 0;
- /* If this is a PC relative reloc, then the addend
- is the negative of the source VMA. We must
- adjust it by the change in the source VMA. This
- is done below. */
- }
- /* Write out the new r_index value. */
- if (bfd_header_big_endian (output_bfd))
- {
- rel->r_index[0] = r_index >> 16;
- rel->r_index[1] = r_index >> 8;
- rel->r_index[2] = r_index;
- }
- else
- {
- rel->r_index[2] = r_index >> 16;
- rel->r_index[1] = r_index >> 8;
- rel->r_index[0] = r_index;
- }
- }
- else
- {
- /* This is a relocation against a section. We must
- adjust by the amount that the section moved. */
- r_section = aout_reloc_index_to_section (input_bfd, r_index);
- relocation = (r_section->output_section->vma
- + r_section->output_offset
- - r_section->vma);
- /* If this is a PC relative reloc, then the addend is
- the difference in VMA between the destination and the
- source. We have just adjusted for the change in VMA
- of the destination, so we must also adjust by the
- change in VMA of the source. This is done below. */
- }
- /* As described above, we must always adjust a PC relative
- reloc by the change in VMA of the source. However, if
- pcrel_offset is set, then the addend does not include the
- location within the section, in which case we don't need
- to adjust anything. */
- if (howto_table_ext[r_type].pc_relative
- && ! howto_table_ext[r_type].pcrel_offset)
- relocation -= (input_section->output_section->vma
- + input_section->output_offset
- - input_section->vma);
- /* Change the addend if necessary. */
- if (relocation != 0)
- PUT_WORD (output_bfd, r_addend + relocation, rel->r_addend);
- /* Change the address of the relocation. */
- PUT_WORD (output_bfd,
- r_addr + input_section->output_offset,
- rel->r_address);
- }
- else
- {
- bool hundef;
- bfd_reloc_status_type r;
- /* We are generating an executable, and must do a full
- relocation. */
- hundef = false;
- if (r_extern)
- {
- h = sym_hashes[r_index];
- if (h != NULL
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak))
- {
- relocation = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
- }
- else if (h != NULL
- && h->root.type == bfd_link_hash_undefweak)
- relocation = 0;
- else
- {
- hundef = true;
- relocation = 0;
- }
- }
- else if (r_type == (unsigned int) RELOC_BASE10
- || r_type == (unsigned int) RELOC_BASE13
- || r_type == (unsigned int) RELOC_BASE22)
- {
- struct external_nlist *sym;
- int type;
- /* For base relative relocs, r_index is always an index
- into the symbol table, even if r_extern is 0. */
- sym = syms + r_index;
- type = H_GET_8 (input_bfd, sym->e_type);
- if ((type & N_TYPE) == N_TEXT
- || type == N_WEAKT)
- r_section = obj_textsec (input_bfd);
- else if ((type & N_TYPE) == N_DATA
- || type == N_WEAKD)
- r_section = obj_datasec (input_bfd);
- else if ((type & N_TYPE) == N_BSS
- || type == N_WEAKB)
- r_section = obj_bsssec (input_bfd);
- else if ((type & N_TYPE) == N_ABS
- || type == N_WEAKA)
- r_section = bfd_abs_section_ptr;
- else
- abort ();
- relocation = (r_section->output_section->vma
- + r_section->output_offset
- + (GET_WORD (input_bfd, sym->e_value)
- - r_section->vma));
- }
- else
- {
- r_section = aout_reloc_index_to_section (input_bfd, r_index);
- /* If this is a PC relative reloc, then R_ADDEND is the
- difference between the two vmas, or
- old_dest_sec + old_dest_off - (old_src_sec + old_src_off)
- where
- old_dest_sec == section->vma
- and
- old_src_sec == input_section->vma
- and
- old_src_off == r_addr
- _bfd_final_link_relocate expects RELOCATION +
- R_ADDEND to be the VMA of the destination minus
- r_addr (the minus r_addr is because this relocation
- is not pcrel_offset, which is a bit confusing and
- should, perhaps, be changed), or
- new_dest_sec
- where
- new_dest_sec == output_section->vma + output_offset
- We arrange for this to happen by setting RELOCATION to
- new_dest_sec + old_src_sec - old_dest_sec
- If this is not a PC relative reloc, then R_ADDEND is
- simply the VMA of the destination, so we set
- RELOCATION to the change in the destination VMA, or
- new_dest_sec - old_dest_sec
- */
- relocation = (r_section->output_section->vma
- + r_section->output_offset
- - r_section->vma);
- if (howto_table_ext[r_type].pc_relative)
- relocation += input_section->vma;
- }
- if (check_dynamic_reloc != NULL)
- {
- bool skip;
- if (! ((*check_dynamic_reloc)
- (flaginfo->info, input_bfd, input_section, h,
- (void *) rel, contents, &skip, &relocation)))
- return false;
- if (skip)
- continue;
- }
- /* Now warn if a global symbol is undefined. We could not
- do this earlier, because check_dynamic_reloc might want
- to skip this reloc. */
- if (hundef
- && ! bfd_link_pic (flaginfo->info)
- && r_type != (unsigned int) RELOC_BASE10
- && r_type != (unsigned int) RELOC_BASE13
- && r_type != (unsigned int) RELOC_BASE22)
- {
- const char *name;
- if (h != NULL)
- name = h->root.root.string;
- else
- name = strings + GET_WORD (input_bfd, syms[r_index].e_strx);
- (*flaginfo->info->callbacks->undefined_symbol)
- (flaginfo->info, name, input_bfd, input_section, r_addr, true);
- }
- if (r_type != (unsigned int) RELOC_SPARC_REV32)
- r = MY_final_link_relocate (howto_table_ext + r_type,
- input_bfd, input_section,
- contents, r_addr, relocation,
- r_addend);
- else
- {
- bfd_vma x;
- x = bfd_get_32 (input_bfd, contents + r_addr);
- x = x + relocation + r_addend;
- bfd_putl32 (/*input_bfd,*/ x, contents + r_addr);
- r = bfd_reloc_ok;
- }
- if (r != bfd_reloc_ok)
- {
- switch (r)
- {
- default:
- case bfd_reloc_outofrange:
- abort ();
- case bfd_reloc_overflow:
- {
- const char *name;
- if (h != NULL)
- name = NULL;
- else if (r_extern
- || r_type == (unsigned int) RELOC_BASE10
- || r_type == (unsigned int) RELOC_BASE13
- || r_type == (unsigned int) RELOC_BASE22)
- name = strings + GET_WORD (input_bfd,
- syms[r_index].e_strx);
- else
- {
- asection *s;
- s = aout_reloc_index_to_section (input_bfd, r_index);
- name = bfd_section_name (s);
- }
- (*flaginfo->info->callbacks->reloc_overflow)
- (flaginfo->info, (h ? &h->root : NULL), name,
- howto_table_ext[r_type].name,
- r_addend, input_bfd, input_section, r_addr);
- }
- break;
- }
- }
- }
- }
- return true;
- }
- /* Link an a.out section into the output file. */
- static bool
- aout_link_input_section (struct aout_final_link_info *flaginfo,
- bfd *input_bfd,
- asection *input_section,
- file_ptr *reloff_ptr,
- bfd_size_type rel_size)
- {
- bfd_size_type input_size;
- void * relocs;
- /* Get the section contents. */
- input_size = input_section->size;
- if (! bfd_get_section_contents (input_bfd, input_section,
- (void *) flaginfo->contents,
- (file_ptr) 0, input_size))
- return false;
- /* Read in the relocs if we haven't already done it. */
- if (aout_section_data (input_section) != NULL
- && aout_section_data (input_section)->relocs != NULL)
- relocs = aout_section_data (input_section)->relocs;
- else
- {
- relocs = flaginfo->relocs;
- if (rel_size > 0)
- {
- if (bfd_seek (input_bfd, input_section->rel_filepos, SEEK_SET) != 0
- || bfd_bread (relocs, rel_size, input_bfd) != rel_size)
- return false;
- }
- }
- /* Relocate the section contents. */
- if (obj_reloc_entry_size (input_bfd) == RELOC_STD_SIZE)
- {
- if (! aout_link_input_section_std (flaginfo, input_bfd, input_section,
- (struct reloc_std_external *) relocs,
- rel_size, flaginfo->contents))
- return false;
- }
- else
- {
- if (! aout_link_input_section_ext (flaginfo, input_bfd, input_section,
- (struct reloc_ext_external *) relocs,
- rel_size, flaginfo->contents))
- return false;
- }
- /* Write out the section contents. */
- if (! bfd_set_section_contents (flaginfo->output_bfd,
- input_section->output_section,
- (void *) flaginfo->contents,
- (file_ptr) input_section->output_offset,
- input_size))
- return false;
- /* If we are producing relocatable output, the relocs were
- modified, and we now write them out. */
- if (bfd_link_relocatable (flaginfo->info) && rel_size > 0)
- {
- if (bfd_seek (flaginfo->output_bfd, *reloff_ptr, SEEK_SET) != 0)
- return false;
- if (bfd_bwrite (relocs, rel_size, flaginfo->output_bfd) != rel_size)
- return false;
- *reloff_ptr += rel_size;
- /* Assert that the relocs have not run into the symbols, and
- that if these are the text relocs they have not run into the
- data relocs. */
- BFD_ASSERT (*reloff_ptr <= obj_sym_filepos (flaginfo->output_bfd)
- && (reloff_ptr != &flaginfo->treloff
- || (*reloff_ptr
- <= obj_datasec (flaginfo->output_bfd)->rel_filepos)));
- }
- return true;
- }
- /* Adjust and write out the symbols for an a.out file. Set the new
- symbol indices into a symbol_map. */
- static bool
- aout_link_write_symbols (struct aout_final_link_info *flaginfo, bfd *input_bfd)
- {
- bfd *output_bfd;
- bfd_size_type sym_count;
- char *strings;
- enum bfd_link_strip strip;
- enum bfd_link_discard discard;
- struct external_nlist *outsym;
- bfd_size_type strtab_index;
- struct external_nlist *sym;
- struct external_nlist *sym_end;
- struct aout_link_hash_entry **sym_hash;
- int *symbol_map;
- bool pass;
- bool skip_next;
- output_bfd = flaginfo->output_bfd;
- sym_count = obj_aout_external_sym_count (input_bfd);
- strings = obj_aout_external_strings (input_bfd);
- strip = flaginfo->info->strip;
- discard = flaginfo->info->discard;
- outsym = flaginfo->output_syms;
- /* First write out a symbol for this object file, unless we are
- discarding such symbols. */
- if (strip != strip_all
- && (strip != strip_some
- || bfd_hash_lookup (flaginfo->info->keep_hash,
- bfd_get_filename (input_bfd),
- false, false) != NULL)
- && discard != discard_all)
- {
- H_PUT_8 (output_bfd, N_TEXT, outsym->e_type);
- H_PUT_8 (output_bfd, 0, outsym->e_other);
- H_PUT_16 (output_bfd, 0, outsym->e_desc);
- strtab_index = add_to_stringtab (output_bfd, flaginfo->strtab,
- bfd_get_filename (input_bfd), false);
- if (strtab_index == (bfd_size_type) -1)
- return false;
- PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
- PUT_WORD (output_bfd,
- (bfd_section_vma (obj_textsec (input_bfd)->output_section)
- + obj_textsec (input_bfd)->output_offset),
- outsym->e_value);
- ++obj_aout_external_sym_count (output_bfd);
- ++outsym;
- }
- pass = false;
- skip_next = false;
- sym = obj_aout_external_syms (input_bfd);
- sym_end = sym + sym_count;
- sym_hash = obj_aout_sym_hashes (input_bfd);
- symbol_map = flaginfo->symbol_map;
- memset (symbol_map, 0, (size_t) sym_count * sizeof *symbol_map);
- for (; sym < sym_end; sym++, sym_hash++, symbol_map++)
- {
- const char *name;
- int type;
- struct aout_link_hash_entry *h;
- bool skip;
- asection *symsec;
- bfd_vma val = 0;
- bool copy;
- /* We set *symbol_map to 0 above for all symbols. If it has
- already been set to -1 for this symbol, it means that we are
- discarding it because it appears in a duplicate header file.
- See the N_BINCL code below. */
- if (*symbol_map == -1)
- continue;
- /* Initialize *symbol_map to -1, which means that the symbol was
- not copied into the output file. We will change it later if
- we do copy the symbol over. */
- *symbol_map = -1;
- type = H_GET_8 (input_bfd, sym->e_type);
- name = strings + GET_WORD (input_bfd, sym->e_strx);
- h = NULL;
- if (pass)
- {
- /* Pass this symbol through. It is the target of an
- indirect or warning symbol. */
- val = GET_WORD (input_bfd, sym->e_value);
- pass = false;
- }
- else if (skip_next)
- {
- /* Skip this symbol, which is the target of an indirect
- symbol that we have changed to no longer be an indirect
- symbol. */
- skip_next = false;
- continue;
- }
- else
- {
- struct aout_link_hash_entry *hresolve;
- /* We have saved the hash table entry for this symbol, if
- there is one. Note that we could just look it up again
- in the hash table, provided we first check that it is an
- external symbol. */
- h = *sym_hash;
- /* Use the name from the hash table, in case the symbol was
- wrapped. */
- if (h != NULL
- && h->root.type != bfd_link_hash_warning)
- name = h->root.root.string;
- /* If this is an indirect or warning symbol, then change
- hresolve to the base symbol. We also change *sym_hash so
- that the relocation routines relocate against the real
- symbol. */
- hresolve = h;
- if (h != (struct aout_link_hash_entry *) NULL
- && (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning))
- {
- hresolve = (struct aout_link_hash_entry *) h->root.u.i.link;
- while (hresolve->root.type == bfd_link_hash_indirect
- || hresolve->root.type == bfd_link_hash_warning)
- hresolve = ((struct aout_link_hash_entry *)
- hresolve->root.u.i.link);
- *sym_hash = hresolve;
- }
- /* If the symbol has already been written out, skip it. */
- if (h != NULL
- && h->written)
- {
- if ((type & N_TYPE) == N_INDR
- || type == N_WARNING)
- skip_next = true;
- *symbol_map = h->indx;
- continue;
- }
- /* See if we are stripping this symbol. */
- skip = false;
- switch (strip)
- {
- case strip_none:
- break;
- case strip_debugger:
- if ((type & N_STAB) != 0)
- skip = true;
- break;
- case strip_some:
- if (bfd_hash_lookup (flaginfo->info->keep_hash, name, false, false)
- == NULL)
- skip = true;
- break;
- case strip_all:
- skip = true;
- break;
- }
- if (skip)
- {
- if (h != NULL)
- h->written = true;
- continue;
- }
- /* Get the value of the symbol. */
- if ((type & N_TYPE) == N_TEXT
- || type == N_WEAKT)
- symsec = obj_textsec (input_bfd);
- else if ((type & N_TYPE) == N_DATA
- || type == N_WEAKD)
- symsec = obj_datasec (input_bfd);
- else if ((type & N_TYPE) == N_BSS
- || type == N_WEAKB)
- symsec = obj_bsssec (input_bfd);
- else if ((type & N_TYPE) == N_ABS
- || type == N_WEAKA)
- symsec = bfd_abs_section_ptr;
- else if (((type & N_TYPE) == N_INDR
- && (hresolve == NULL
- || (hresolve->root.type != bfd_link_hash_defined
- && hresolve->root.type != bfd_link_hash_defweak
- && hresolve->root.type != bfd_link_hash_common)))
- || type == N_WARNING)
- {
- /* Pass the next symbol through unchanged. The
- condition above for indirect symbols is so that if
- the indirect symbol was defined, we output it with
- the correct definition so the debugger will
- understand it. */
- pass = true;
- val = GET_WORD (input_bfd, sym->e_value);
- symsec = NULL;
- }
- else if ((type & N_STAB) != 0)
- {
- val = GET_WORD (input_bfd, sym->e_value);
- symsec = NULL;
- }
- else
- {
- /* If we get here with an indirect symbol, it means that
- we are outputting it with a real definition. In such
- a case we do not want to output the next symbol,
- which is the target of the indirection. */
- if ((type & N_TYPE) == N_INDR)
- skip_next = true;
- symsec = NULL;
- /* We need to get the value from the hash table. We use
- hresolve so that if we have defined an indirect
- symbol we output the final definition. */
- if (h == NULL)
- {
- switch (type & N_TYPE)
- {
- case N_SETT:
- symsec = obj_textsec (input_bfd);
- break;
- case N_SETD:
- symsec = obj_datasec (input_bfd);
- break;
- case N_SETB:
- symsec = obj_bsssec (input_bfd);
- break;
- case N_SETA:
- symsec = bfd_abs_section_ptr;
- break;
- default:
- val = 0;
- break;
- }
- }
- else if (hresolve->root.type == bfd_link_hash_defined
- || hresolve->root.type == bfd_link_hash_defweak)
- {
- asection *input_section;
- asection *output_section;
- /* This case usually means a common symbol which was
- turned into a defined symbol. */
- input_section = hresolve->root.u.def.section;
- output_section = input_section->output_section;
- BFD_ASSERT (bfd_is_abs_section (output_section)
- || output_section->owner == output_bfd);
- val = (hresolve->root.u.def.value
- + bfd_section_vma (output_section)
- + input_section->output_offset);
- /* Get the correct type based on the section. If
- this is a constructed set, force it to be
- globally visible. */
- if (type == N_SETT
- || type == N_SETD
- || type == N_SETB
- || type == N_SETA)
- type |= N_EXT;
- type &=~ N_TYPE;
- if (output_section == obj_textsec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_TEXT
- : N_WEAKT);
- else if (output_section == obj_datasec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_DATA
- : N_WEAKD);
- else if (output_section == obj_bsssec (output_bfd))
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_BSS
- : N_WEAKB);
- else
- type |= (hresolve->root.type == bfd_link_hash_defined
- ? N_ABS
- : N_WEAKA);
- }
- else if (hresolve->root.type == bfd_link_hash_common)
- val = hresolve->root.u.c.size;
- else if (hresolve->root.type == bfd_link_hash_undefweak)
- {
- val = 0;
- type = N_WEAKU;
- }
- else
- val = 0;
- }
- if (symsec != NULL)
- val = (symsec->output_section->vma
- + symsec->output_offset
- + (GET_WORD (input_bfd, sym->e_value)
- - symsec->vma));
- /* If this is a global symbol set the written flag, and if
- it is a local symbol see if we should discard it. */
- if (h != NULL)
- {
- h->written = true;
- h->indx = obj_aout_external_sym_count (output_bfd);
- }
- else if ((type & N_TYPE) != N_SETT
- && (type & N_TYPE) != N_SETD
- && (type & N_TYPE) != N_SETB
- && (type & N_TYPE) != N_SETA)
- {
- switch (discard)
- {
- case discard_none:
- case discard_sec_merge:
- break;
- case discard_l:
- if ((type & N_STAB) == 0
- && bfd_is_local_label_name (input_bfd, name))
- skip = true;
- break;
- case discard_all:
- skip = true;
- break;
- }
- if (skip)
- {
- pass = false;
- continue;
- }
- }
- /* An N_BINCL symbol indicates the start of the stabs
- entries for a header file. We need to scan ahead to the
- next N_EINCL symbol, ignoring nesting, adding up all the
- characters in the symbol names, not including the file
- numbers in types (the first number after an open
- parenthesis). */
- if (type == (int) N_BINCL)
- {
- struct external_nlist *incl_sym;
- int nest;
- struct aout_link_includes_entry *incl_entry;
- struct aout_link_includes_totals *t;
- val = 0;
- nest = 0;
- for (incl_sym = sym + 1; incl_sym < sym_end; incl_sym++)
- {
- int incl_type;
- incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
- if (incl_type == (int) N_EINCL)
- {
- if (nest == 0)
- break;
- --nest;
- }
- else if (incl_type == (int) N_BINCL)
- ++nest;
- else if (nest == 0)
- {
- const char *s;
- s = strings + GET_WORD (input_bfd, incl_sym->e_strx);
- for (; *s != '\0'; s++)
- {
- val += *s;
- if (*s == '(')
- {
- /* Skip the file number. */
- ++s;
- while (ISDIGIT (*s))
- ++s;
- --s;
- }
- }
- }
- }
- /* If we have already included a header file with the
- same value, then replace this one with an N_EXCL
- symbol. */
- copy = !flaginfo->info->keep_memory;
- incl_entry = aout_link_includes_lookup (&flaginfo->includes,
- name, true, copy);
- if (incl_entry == NULL)
- return false;
- for (t = incl_entry->totals; t != NULL; t = t->next)
- if (t->total == val)
- break;
- if (t == NULL)
- {
- /* This is the first time we have seen this header
- file with this set of stabs strings. */
- t = (struct aout_link_includes_totals *)
- bfd_hash_allocate (&flaginfo->includes.root,
- sizeof *t);
- if (t == NULL)
- return false;
- t->total = val;
- t->next = incl_entry->totals;
- incl_entry->totals = t;
- }
- else
- {
- int *incl_map;
- /* This is a duplicate header file. We must change
- it to be an N_EXCL entry, and mark all the
- included symbols to prevent outputting them. */
- type = (int) N_EXCL;
- nest = 0;
- for (incl_sym = sym + 1, incl_map = symbol_map + 1;
- incl_sym < sym_end;
- incl_sym++, incl_map++)
- {
- int incl_type;
- incl_type = H_GET_8 (input_bfd, incl_sym->e_type);
- if (incl_type == (int) N_EINCL)
- {
- if (nest == 0)
- {
- *incl_map = -1;
- break;
- }
- --nest;
- }
- else if (incl_type == (int) N_BINCL)
- ++nest;
- else if (nest == 0)
- *incl_map = -1;
- }
- }
- }
- }
- /* Copy this symbol into the list of symbols we are going to
- write out. */
- H_PUT_8 (output_bfd, type, outsym->e_type);
- H_PUT_8 (output_bfd, H_GET_8 (input_bfd, sym->e_other), outsym->e_other);
- H_PUT_16 (output_bfd, H_GET_16 (input_bfd, sym->e_desc), outsym->e_desc);
- copy = false;
- if (! flaginfo->info->keep_memory)
- {
- /* name points into a string table which we are going to
- free. If there is a hash table entry, use that string.
- Otherwise, copy name into memory. */
- if (h != NULL)
- name = h->root.root.string;
- else
- copy = true;
- }
- strtab_index = add_to_stringtab (output_bfd, flaginfo->strtab,
- name, copy);
- if (strtab_index == (bfd_size_type) -1)
- return false;
- PUT_WORD (output_bfd, strtab_index, outsym->e_strx);
- PUT_WORD (output_bfd, val, outsym->e_value);
- *symbol_map = obj_aout_external_sym_count (output_bfd);
- ++obj_aout_external_sym_count (output_bfd);
- ++outsym;
- }
- /* Write out the output symbols we have just constructed. */
- if (outsym > flaginfo->output_syms)
- {
- bfd_size_type outsym_size;
- if (bfd_seek (output_bfd, flaginfo->symoff, SEEK_SET) != 0)
- return false;
- outsym_size = outsym - flaginfo->output_syms;
- outsym_size *= EXTERNAL_NLIST_SIZE;
- if (bfd_bwrite ((void *) flaginfo->output_syms, outsym_size, output_bfd)
- != outsym_size)
- return false;
- flaginfo->symoff += outsym_size;
- }
- return true;
- }
- /* Link an a.out input BFD into the output file. */
- static bool
- aout_link_input_bfd (struct aout_final_link_info *flaginfo, bfd *input_bfd)
- {
- BFD_ASSERT (bfd_get_format (input_bfd) == bfd_object);
- /* If this is a dynamic object, it may need special handling. */
- if ((input_bfd->flags & DYNAMIC) != 0
- && aout_backend_info (input_bfd)->link_dynamic_object != NULL)
- return ((*aout_backend_info (input_bfd)->link_dynamic_object)
- (flaginfo->info, input_bfd));
- /* Get the symbols. We probably have them already, unless
- flaginfo->info->keep_memory is FALSE. */
- if (! aout_get_external_symbols (input_bfd))
- return false;
- /* Write out the symbols and get a map of the new indices. The map
- is placed into flaginfo->symbol_map. */
- if (! aout_link_write_symbols (flaginfo, input_bfd))
- return false;
- /* Relocate and write out the sections. These functions use the
- symbol map created by aout_link_write_symbols. The linker_mark
- field will be set if these sections are to be included in the
- link, which will normally be the case. */
- if (obj_textsec (input_bfd)->linker_mark)
- {
- if (! aout_link_input_section (flaginfo, input_bfd,
- obj_textsec (input_bfd),
- &flaginfo->treloff,
- exec_hdr (input_bfd)->a_trsize))
- return false;
- }
- if (obj_datasec (input_bfd)->linker_mark)
- {
- if (! aout_link_input_section (flaginfo, input_bfd,
- obj_datasec (input_bfd),
- &flaginfo->dreloff,
- exec_hdr (input_bfd)->a_drsize))
- return false;
- }
- /* If we are not keeping memory, we don't need the symbols any
- longer. We still need them if we are keeping memory, because the
- strings in the hash table point into them. */
- if (! flaginfo->info->keep_memory)
- {
- if (! aout_link_free_symbols (input_bfd))
- return false;
- }
- return true;
- }
- /* Do the final link step. This is called on the output BFD. The
- INFO structure should point to a list of BFDs linked through the
- link.next field which can be used to find each BFD which takes part
- in the output. Also, each section in ABFD should point to a list
- of bfd_link_order structures which list all the input sections for
- the output section. */
- bool
- NAME (aout, final_link) (bfd *abfd,
- struct bfd_link_info *info,
- void (*callback) (bfd *, file_ptr *, file_ptr *, file_ptr *))
- {
- struct aout_final_link_info aout_info;
- bool includes_hash_initialized = false;
- bfd *sub;
- bfd_size_type trsize, drsize;
- bfd_size_type max_contents_size;
- bfd_size_type max_relocs_size;
- bfd_size_type max_sym_count;
- struct bfd_link_order *p;
- asection *o;
- bool have_link_order_relocs;
- if (bfd_link_pic (info))
- abfd->flags |= DYNAMIC;
- aout_info.info = info;
- aout_info.output_bfd = abfd;
- aout_info.contents = NULL;
- aout_info.relocs = NULL;
- aout_info.symbol_map = NULL;
- aout_info.output_syms = NULL;
- if (!bfd_hash_table_init_n (&aout_info.includes.root,
- aout_link_includes_newfunc,
- sizeof (struct aout_link_includes_entry),
- 251))
- goto error_return;
- includes_hash_initialized = true;
- /* Figure out the largest section size. Also, if generating
- relocatable output, count the relocs. */
- trsize = 0;
- drsize = 0;
- max_contents_size = 0;
- max_relocs_size = 0;
- max_sym_count = 0;
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- {
- bfd_size_type sz;
- if (bfd_link_relocatable (info))
- {
- if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
- {
- trsize += exec_hdr (sub)->a_trsize;
- drsize += exec_hdr (sub)->a_drsize;
- }
- else
- {
- /* FIXME: We need to identify the .text and .data sections
- and call get_reloc_upper_bound and canonicalize_reloc to
- work out the number of relocs needed, and then multiply
- by the reloc size. */
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%pB: relocatable link from %s to %s not supported"),
- abfd, sub->xvec->name, abfd->xvec->name);
- bfd_set_error (bfd_error_invalid_operation);
- goto error_return;
- }
- }
- if (bfd_get_flavour (sub) == bfd_target_aout_flavour)
- {
- sz = obj_textsec (sub)->size;
- if (sz > max_contents_size)
- max_contents_size = sz;
- sz = obj_datasec (sub)->size;
- if (sz > max_contents_size)
- max_contents_size = sz;
- sz = exec_hdr (sub)->a_trsize;
- if (sz > max_relocs_size)
- max_relocs_size = sz;
- sz = exec_hdr (sub)->a_drsize;
- if (sz > max_relocs_size)
- max_relocs_size = sz;
- sz = obj_aout_external_sym_count (sub);
- if (sz > max_sym_count)
- max_sym_count = sz;
- }
- }
- if (bfd_link_relocatable (info))
- {
- if (obj_textsec (abfd) != NULL)
- trsize += (_bfd_count_link_order_relocs (obj_textsec (abfd)
- ->map_head.link_order)
- * obj_reloc_entry_size (abfd));
- if (obj_datasec (abfd) != NULL)
- drsize += (_bfd_count_link_order_relocs (obj_datasec (abfd)
- ->map_head.link_order)
- * obj_reloc_entry_size (abfd));
- }
- exec_hdr (abfd)->a_trsize = trsize;
- exec_hdr (abfd)->a_drsize = drsize;
- exec_hdr (abfd)->a_entry = bfd_get_start_address (abfd);
- /* Adjust the section sizes and vmas according to the magic number.
- This sets a_text, a_data and a_bss in the exec_hdr and sets the
- filepos for each section. */
- if (! NAME (aout, adjust_sizes_and_vmas) (abfd))
- goto error_return;
- /* The relocation and symbol file positions differ among a.out
- targets. We are passed a callback routine from the backend
- specific code to handle this.
- FIXME: At this point we do not know how much space the symbol
- table will require. This will not work for any (nonstandard)
- a.out target that needs to know the symbol table size before it
- can compute the relocation file positions. */
- (*callback) (abfd, &aout_info.treloff, &aout_info.dreloff,
- &aout_info.symoff);
- obj_textsec (abfd)->rel_filepos = aout_info.treloff;
- obj_datasec (abfd)->rel_filepos = aout_info.dreloff;
- obj_sym_filepos (abfd) = aout_info.symoff;
- /* We keep a count of the symbols as we output them. */
- obj_aout_external_sym_count (abfd) = 0;
- /* We accumulate the string table as we write out the symbols. */
- aout_info.strtab = _bfd_stringtab_init ();
- if (aout_info.strtab == NULL)
- goto error_return;
- /* Allocate buffers to hold section contents and relocs. */
- aout_info.contents = (bfd_byte *) bfd_malloc (max_contents_size);
- aout_info.relocs = bfd_malloc (max_relocs_size);
- aout_info.symbol_map = (int *) bfd_malloc (max_sym_count * sizeof (int));
- aout_info.output_syms = (struct external_nlist *)
- bfd_malloc ((max_sym_count + 1) * sizeof (struct external_nlist));
- if ((aout_info.contents == NULL && max_contents_size != 0)
- || (aout_info.relocs == NULL && max_relocs_size != 0)
- || (aout_info.symbol_map == NULL && max_sym_count != 0)
- || aout_info.output_syms == NULL)
- goto error_return;
- /* If we have a symbol named __DYNAMIC, force it out now. This is
- required by SunOS. Doing this here rather than in sunos.c is a
- hack, but it's easier than exporting everything which would be
- needed. */
- {
- struct aout_link_hash_entry *h;
- h = aout_link_hash_lookup (aout_hash_table (info), "__DYNAMIC",
- false, false, false);
- if (h != NULL)
- aout_link_write_other_symbol (&h->root.root, &aout_info);
- }
- /* The most time efficient way to do the link would be to read all
- the input object files into memory and then sort out the
- information into the output file. Unfortunately, that will
- probably use too much memory. Another method would be to step
- through everything that composes the text section and write it
- out, and then everything that composes the data section and write
- it out, and then write out the relocs, and then write out the
- symbols. Unfortunately, that requires reading stuff from each
- input file several times, and we will not be able to keep all the
- input files open simultaneously, and reopening them will be slow.
- What we do is basically process one input file at a time. We do
- everything we need to do with an input file once--copy over the
- section contents, handle the relocation information, and write
- out the symbols--and then we throw away the information we read
- from it. This approach requires a lot of lseeks of the output
- file, which is unfortunate but still faster than reopening a lot
- of files.
- We use the output_has_begun field of the input BFDs to see
- whether we have already handled it. */
- for (sub = info->input_bfds; sub != NULL; sub = sub->link.next)
- sub->output_has_begun = false;
- /* Mark all sections which are to be included in the link. This
- will normally be every section. We need to do this so that we
- can identify any sections which the linker has decided to not
- include. */
- 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;
- }
- have_link_order_relocs = false;
- 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
- && (bfd_get_flavour (p->u.indirect.section->owner)
- == bfd_target_aout_flavour))
- {
- bfd *input_bfd;
- input_bfd = p->u.indirect.section->owner;
- if (! input_bfd->output_has_begun)
- {
- if (! aout_link_input_bfd (&aout_info, input_bfd))
- goto error_return;
- input_bfd->output_has_begun = true;
- }
- }
- else if (p->type == bfd_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- {
- /* These are handled below. */
- have_link_order_relocs = true;
- }
- else
- {
- if (! _bfd_default_link_order (abfd, info, o, p))
- goto error_return;
- }
- }
- }
- /* Write out any symbols that we have not already written out. */
- bfd_hash_traverse (&info->hash->table,
- aout_link_write_other_symbol,
- &aout_info);
- /* Now handle any relocs we were asked to create by the linker.
- These did not come from any input file. We must do these after
- we have written out all the symbols, so that we know the symbol
- indices to use. */
- if (have_link_order_relocs)
- {
- 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_section_reloc_link_order
- || p->type == bfd_symbol_reloc_link_order)
- {
- if (! aout_link_reloc_link_order (&aout_info, o, p))
- goto error_return;
- }
- }
- }
- }
- free (aout_info.contents);
- aout_info.contents = NULL;
- free (aout_info.relocs);
- aout_info.relocs = NULL;
- free (aout_info.symbol_map);
- aout_info.symbol_map = NULL;
- free (aout_info.output_syms);
- aout_info.output_syms = NULL;
- if (includes_hash_initialized)
- {
- bfd_hash_table_free (&aout_info.includes.root);
- includes_hash_initialized = false;
- }
- /* Finish up any dynamic linking we may be doing. */
- if (aout_backend_info (abfd)->finish_dynamic_link != NULL)
- {
- if (! (*aout_backend_info (abfd)->finish_dynamic_link) (abfd, info))
- goto error_return;
- }
- /* Update the header information. */
- abfd->symcount = obj_aout_external_sym_count (abfd);
- exec_hdr (abfd)->a_syms = abfd->symcount * EXTERNAL_NLIST_SIZE;
- obj_str_filepos (abfd) = obj_sym_filepos (abfd) + exec_hdr (abfd)->a_syms;
- obj_textsec (abfd)->reloc_count =
- exec_hdr (abfd)->a_trsize / obj_reloc_entry_size (abfd);
- obj_datasec (abfd)->reloc_count =
- exec_hdr (abfd)->a_drsize / obj_reloc_entry_size (abfd);
- /* Write out the string table, unless there are no symbols. */
- if (bfd_seek (abfd, obj_str_filepos (abfd), SEEK_SET) != 0)
- goto error_return;
- if (abfd->symcount > 0)
- {
- if (!emit_stringtab (abfd, aout_info.strtab))
- goto error_return;
- }
- else
- {
- bfd_byte b[BYTES_IN_WORD];
- memset (b, 0, BYTES_IN_WORD);
- if (bfd_bwrite (b, (bfd_size_type) BYTES_IN_WORD, abfd) != BYTES_IN_WORD)
- goto error_return;
- }
- return true;
- error_return:
- free (aout_info.contents);
- free (aout_info.relocs);
- free (aout_info.symbol_map);
- free (aout_info.output_syms);
- if (includes_hash_initialized)
- bfd_hash_table_free (&aout_info.includes.root);
- return false;
- }
|