123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439 |
- /* stabs.c -- Parse stabs debugging information
- Copyright (C) 1995-2015 Free Software Foundation, Inc.
- Written by Ian Lance Taylor <ian@cygnus.com>.
- This file is part of GNU Binutils.
- 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. */
- /* This file contains code which parses stabs debugging information.
- The organization of this code is based on the gdb stabs reading
- code. The job it does is somewhat different, because it is not
- trying to identify the correct address for anything. */
- #include "sysdep.h"
- #include "bfd.h"
- #include "libiberty.h"
- #include "safe-ctype.h"
- #include "demangle.h"
- #include "debug.h"
- #include "budbg.h"
- #include "filenames.h"
- #include "aout/aout64.h"
- #include "aout/stab_gnu.h"
- /* The number of predefined XCOFF types. */
- #define XCOFF_TYPE_COUNT 34
- /* This structure is used as a handle so that the stab parsing doesn't
- need to use any static variables. */
- struct stab_handle
- {
- /* The BFD. */
- bfd *abfd;
- /* TRUE if this is stabs in sections. */
- bfd_boolean sections;
- /* The symbol table. */
- asymbol **syms;
- /* The number of symbols. */
- long symcount;
- /* The accumulated file name string. */
- char *so_string;
- /* The value of the last N_SO symbol. */
- bfd_vma so_value;
- /* The value of the start of the file, so that we can handle file
- relative N_LBRAC and N_RBRAC symbols. */
- bfd_vma file_start_offset;
- /* The offset of the start of the function, so that we can handle
- function relative N_LBRAC and N_RBRAC symbols. */
- bfd_vma function_start_offset;
- /* The version number of gcc which compiled the current compilation
- unit, 0 if not compiled by gcc. */
- int gcc_compiled;
- /* Whether an N_OPT symbol was seen that was not generated by gcc,
- so that we can detect the SunPRO compiler. */
- bfd_boolean n_opt_found;
- /* The main file name. */
- char *main_filename;
- /* A stack of unfinished N_BINCL files. */
- struct bincl_file *bincl_stack;
- /* A list of finished N_BINCL files. */
- struct bincl_file *bincl_list;
- /* Whether we are inside a function or not. */
- bfd_boolean within_function;
- /* The address of the end of the function, used if we have seen an
- N_FUN symbol while in a function. This is -1 if we have not seen
- an N_FUN (the normal case). */
- bfd_vma function_end;
- /* The depth of block nesting. */
- int block_depth;
- /* List of pending variable definitions. */
- struct stab_pending_var *pending;
- /* Number of files for which we have types. */
- unsigned int files;
- /* Lists of types per file. */
- struct stab_types **file_types;
- /* Predefined XCOFF types. */
- debug_type xcoff_types[XCOFF_TYPE_COUNT];
- /* Undefined tags. */
- struct stab_tag *tags;
- /* Set by parse_stab_type if it sees a structure defined as a cross
- reference to itself. Reset by parse_stab_type otherwise. */
- bfd_boolean self_crossref;
- };
- /* A list of these structures is used to hold pending variable
- definitions seen before the N_LBRAC of a block. */
- struct stab_pending_var
- {
- /* Next pending variable definition. */
- struct stab_pending_var *next;
- /* Name. */
- const char *name;
- /* Type. */
- debug_type type;
- /* Kind. */
- enum debug_var_kind kind;
- /* Value. */
- bfd_vma val;
- };
- /* A list of these structures is used to hold the types for a single
- file. */
- struct stab_types
- {
- /* Next set of slots for this file. */
- struct stab_types *next;
- /* Types indexed by type number. */
- #define STAB_TYPES_SLOTS (16)
- debug_type types[STAB_TYPES_SLOTS];
- };
- /* We keep a list of undefined tags that we encounter, so that we can
- fill them in if the tag is later defined. */
- struct stab_tag
- {
- /* Next undefined tag. */
- struct stab_tag *next;
- /* Tag name. */
- const char *name;
- /* Type kind. */
- enum debug_type_kind kind;
- /* Slot to hold real type when we discover it. If we don't, we fill
- in an undefined tag type. */
- debug_type slot;
- /* Indirect type we have created to point at slot. */
- debug_type type;
- };
- static char *savestring (const char *, int);
- static bfd_vma parse_number (const char **, bfd_boolean *);
- static void bad_stab (const char *);
- static void warn_stab (const char *, const char *);
- static bfd_boolean parse_stab_string
- (void *, struct stab_handle *, int, int, bfd_vma, const char *);
- static debug_type parse_stab_type
- (void *, struct stab_handle *, const char *, const char **, debug_type **);
- static bfd_boolean parse_stab_type_number (const char **, int *);
- static debug_type parse_stab_range_type
- (void *, struct stab_handle *, const char *, const char **, const int *);
- static debug_type parse_stab_sun_builtin_type (void *, const char **);
- static debug_type parse_stab_sun_floating_type (void *, const char **);
- static debug_type parse_stab_enum_type (void *, const char **);
- static debug_type parse_stab_struct_type
- (void *, struct stab_handle *, const char *, const char **,
- bfd_boolean, const int *);
- static bfd_boolean parse_stab_baseclasses
- (void *, struct stab_handle *, const char **, debug_baseclass **);
- static bfd_boolean parse_stab_struct_fields
- (void *, struct stab_handle *, const char **, debug_field **, bfd_boolean *);
- static bfd_boolean parse_stab_cpp_abbrev
- (void *, struct stab_handle *, const char **, debug_field *);
- static bfd_boolean parse_stab_one_struct_field
- (void *, struct stab_handle *, const char **, const char *,
- debug_field *, bfd_boolean *);
- static bfd_boolean parse_stab_members
- (void *, struct stab_handle *, const char *, const char **, const int *,
- debug_method **);
- static debug_type parse_stab_argtypes
- (void *, struct stab_handle *, debug_type, const char *, const char *,
- debug_type, const char *, bfd_boolean, bfd_boolean, const char **);
- static bfd_boolean parse_stab_tilde_field
- (void *, struct stab_handle *, const char **, const int *, debug_type *,
- bfd_boolean *);
- static debug_type parse_stab_array_type
- (void *, struct stab_handle *, const char **, bfd_boolean);
- static void push_bincl (struct stab_handle *, const char *, bfd_vma);
- static const char *pop_bincl (struct stab_handle *);
- static bfd_boolean find_excl (struct stab_handle *, const char *, bfd_vma);
- static bfd_boolean stab_record_variable
- (void *, struct stab_handle *, const char *, debug_type,
- enum debug_var_kind, bfd_vma);
- static bfd_boolean stab_emit_pending_vars (void *, struct stab_handle *);
- static debug_type *stab_find_slot (struct stab_handle *, const int *);
- static debug_type stab_find_type (void *, struct stab_handle *, const int *);
- static bfd_boolean stab_record_type
- (void *, struct stab_handle *, const int *, debug_type);
- static debug_type stab_xcoff_builtin_type
- (void *, struct stab_handle *, int);
- static debug_type stab_find_tagged_type
- (void *, struct stab_handle *, const char *, int, enum debug_type_kind);
- static debug_type *stab_demangle_argtypes
- (void *, struct stab_handle *, const char *, bfd_boolean *, unsigned int);
- static debug_type *stab_demangle_v3_argtypes
- (void *, struct stab_handle *, const char *, bfd_boolean *);
- static debug_type *stab_demangle_v3_arglist
- (void *, struct stab_handle *, struct demangle_component *, bfd_boolean *);
- static debug_type stab_demangle_v3_arg
- (void *, struct stab_handle *, struct demangle_component *, debug_type,
- bfd_boolean *);
- /* Save a string in memory. */
- static char *
- savestring (const char *start, int len)
- {
- char *ret;
- ret = (char *) xmalloc (len + 1);
- memcpy (ret, start, len);
- ret[len] = '\0';
- return ret;
- }
- /* Read a number from a string. */
- static bfd_vma
- parse_number (const char **pp, bfd_boolean *poverflow)
- {
- unsigned long ul;
- const char *orig;
- if (poverflow != NULL)
- *poverflow = FALSE;
- orig = *pp;
- errno = 0;
- ul = strtoul (*pp, (char **) pp, 0);
- if (ul + 1 != 0 || errno == 0)
- {
- /* If bfd_vma is larger than unsigned long, and the number is
- meant to be negative, we have to make sure that we sign
- extend properly. */
- if (*orig == '-')
- return (bfd_vma) (bfd_signed_vma) (long) ul;
- return (bfd_vma) ul;
- }
- /* Note that even though strtoul overflowed, it should have set *pp
- to the end of the number, which is where we want it. */
- if (sizeof (bfd_vma) > sizeof (unsigned long))
- {
- const char *p;
- bfd_boolean neg;
- int base;
- bfd_vma over, lastdig;
- bfd_boolean overflow;
- bfd_vma v;
- /* Our own version of strtoul, for a bfd_vma. */
- p = orig;
- neg = FALSE;
- if (*p == '+')
- ++p;
- else if (*p == '-')
- {
- neg = TRUE;
- ++p;
- }
- base = 10;
- if (*p == '0')
- {
- if (p[1] == 'x' || p[1] == 'X')
- {
- base = 16;
- p += 2;
- }
- else
- {
- base = 8;
- ++p;
- }
- }
- over = ((bfd_vma) (bfd_signed_vma) -1) / (bfd_vma) base;
- lastdig = ((bfd_vma) (bfd_signed_vma) -1) % (bfd_vma) base;
- overflow = FALSE;
- v = 0;
- while (1)
- {
- int d;
- d = *p++;
- if (ISDIGIT (d))
- d -= '0';
- else if (ISUPPER (d))
- d -= 'A';
- else if (ISLOWER (d))
- d -= 'a';
- else
- break;
- if (d >= base)
- break;
- if (v > over || (v == over && (bfd_vma) d > lastdig))
- {
- overflow = TRUE;
- break;
- }
- }
- if (! overflow)
- {
- if (neg)
- v = - v;
- return v;
- }
- }
- /* If we get here, the number is too large to represent in a
- bfd_vma. */
- if (poverflow != NULL)
- *poverflow = TRUE;
- else
- warn_stab (orig, _("numeric overflow"));
- return 0;
- }
- /* Give an error for a bad stab string. */
- static void
- bad_stab (const char *p)
- {
- fprintf (stderr, _("Bad stab: %s\n"), p);
- }
- /* Warn about something in a stab string. */
- static void
- warn_stab (const char *p, const char *err)
- {
- fprintf (stderr, _("Warning: %s: %s\n"), err, p);
- }
- /* Create a handle to parse stabs symbols with. */
- void *
- start_stab (void *dhandle ATTRIBUTE_UNUSED, bfd *abfd, bfd_boolean sections,
- asymbol **syms, long symcount)
- {
- struct stab_handle *ret;
- ret = (struct stab_handle *) xmalloc (sizeof *ret);
- memset (ret, 0, sizeof *ret);
- ret->abfd = abfd;
- ret->sections = sections;
- ret->syms = syms;
- ret->symcount = symcount;
- ret->files = 1;
- ret->file_types = (struct stab_types **) xmalloc (sizeof *ret->file_types);
- ret->file_types[0] = NULL;
- ret->function_end = (bfd_vma) -1;
- return (void *) ret;
- }
- /* When we have processed all the stabs information, we need to go
- through and fill in all the undefined tags. */
- bfd_boolean
- finish_stab (void *dhandle, void *handle)
- {
- struct stab_handle *info = (struct stab_handle *) handle;
- struct stab_tag *st;
- if (info->within_function)
- {
- if (! stab_emit_pending_vars (dhandle, info)
- || ! debug_end_function (dhandle, info->function_end))
- return FALSE;
- info->within_function = FALSE;
- info->function_end = (bfd_vma) -1;
- }
- for (st = info->tags; st != NULL; st = st->next)
- {
- enum debug_type_kind kind;
- kind = st->kind;
- if (kind == DEBUG_KIND_ILLEGAL)
- kind = DEBUG_KIND_STRUCT;
- st->slot = debug_make_undefined_tagged_type (dhandle, st->name, kind);
- if (st->slot == DEBUG_TYPE_NULL)
- return FALSE;
- }
- return TRUE;
- }
- /* Handle a single stabs symbol. */
- bfd_boolean
- parse_stab (void *dhandle, void *handle, int type, int desc, bfd_vma value,
- const char *string)
- {
- struct stab_handle *info = (struct stab_handle *) handle;
- /* gcc will emit two N_SO strings per compilation unit, one for the
- directory name and one for the file name. We just collect N_SO
- strings as we see them, and start the new compilation unit when
- we see a non N_SO symbol. */
- if (info->so_string != NULL
- && (type != N_SO || *string == '\0' || value != info->so_value))
- {
- if (! debug_set_filename (dhandle, info->so_string))
- return FALSE;
- info->main_filename = info->so_string;
- info->gcc_compiled = 0;
- info->n_opt_found = FALSE;
- /* Generally, for stabs in the symbol table, the N_LBRAC and
- N_RBRAC symbols are relative to the N_SO symbol value. */
- if (! info->sections)
- info->file_start_offset = info->so_value;
- /* We need to reset the mapping from type numbers to types. We
- can't free the old mapping, because of the use of
- debug_make_indirect_type. */
- info->files = 1;
- info->file_types = ((struct stab_types **)
- xmalloc (sizeof *info->file_types));
- info->file_types[0] = NULL;
- info->so_string = NULL;
- /* Now process whatever type we just got. */
- }
- switch (type)
- {
- case N_FN:
- case N_FN_SEQ:
- break;
- case N_LBRAC:
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (info->n_opt_found && desc == 1)
- break;
- if (! info->within_function)
- {
- fprintf (stderr, _("N_LBRAC not within function\n"));
- return FALSE;
- }
- /* Start an inner lexical block. */
- if (! debug_start_block (dhandle,
- (value
- + info->file_start_offset
- + info->function_start_offset)))
- return FALSE;
- /* Emit any pending variable definitions. */
- if (! stab_emit_pending_vars (dhandle, info))
- return FALSE;
- ++info->block_depth;
- break;
- case N_RBRAC:
- /* Ignore extra outermost context from SunPRO cc and acc. */
- if (info->n_opt_found && desc == 1)
- break;
- /* We shouldn't have any pending variable definitions here, but,
- if we do, we probably need to emit them before closing the
- block. */
- if (! stab_emit_pending_vars (dhandle, info))
- return FALSE;
- /* End an inner lexical block. */
- if (! debug_end_block (dhandle,
- (value
- + info->file_start_offset
- + info->function_start_offset)))
- return FALSE;
- --info->block_depth;
- if (info->block_depth < 0)
- {
- fprintf (stderr, _("Too many N_RBRACs\n"));
- return FALSE;
- }
- break;
- case N_SO:
- /* This always ends a function. */
- if (info->within_function)
- {
- bfd_vma endval;
- endval = value;
- if (*string != '\0'
- && info->function_end != (bfd_vma) -1
- && info->function_end < endval)
- endval = info->function_end;
- if (! stab_emit_pending_vars (dhandle, info)
- || ! debug_end_function (dhandle, endval))
- return FALSE;
- info->within_function = FALSE;
- info->function_end = (bfd_vma) -1;
- }
- /* An empty string is emitted by gcc at the end of a compilation
- unit. */
- if (*string == '\0')
- return TRUE;
- /* Just accumulate strings until we see a non N_SO symbol. If
- the string starts with a directory separator or some other
- form of absolute path specification, we discard the previously
- accumulated strings. */
- if (info->so_string == NULL)
- info->so_string = xstrdup (string);
- else
- {
- char *f;
- f = info->so_string;
- if (IS_ABSOLUTE_PATH (string))
- info->so_string = xstrdup (string);
- else
- info->so_string = concat (info->so_string, string,
- (const char *) NULL);
- free (f);
- }
- info->so_value = value;
- break;
- case N_SOL:
- /* Start an include file. */
- if (! debug_start_source (dhandle, string))
- return FALSE;
- break;
- case N_BINCL:
- /* Start an include file which may be replaced. */
- push_bincl (info, string, value);
- if (! debug_start_source (dhandle, string))
- return FALSE;
- break;
- case N_EINCL:
- /* End an N_BINCL include. */
- if (! debug_start_source (dhandle, pop_bincl (info)))
- return FALSE;
- break;
- case N_EXCL:
- /* This is a duplicate of a header file named by N_BINCL which
- was eliminated by the linker. */
- if (! find_excl (info, string, value))
- return FALSE;
- break;
- case N_SLINE:
- if (! debug_record_line (dhandle, desc,
- value + (info->within_function
- ? info->function_start_offset : 0)))
- return FALSE;
- break;
- case N_BCOMM:
- if (! debug_start_common_block (dhandle, string))
- return FALSE;
- break;
- case N_ECOMM:
- if (! debug_end_common_block (dhandle, string))
- return FALSE;
- break;
- case N_FUN:
- if (*string == '\0')
- {
- if (info->within_function)
- {
- /* This always marks the end of a function; we don't
- need to worry about info->function_end. */
- if (info->sections)
- value += info->function_start_offset;
- if (! stab_emit_pending_vars (dhandle, info)
- || ! debug_end_function (dhandle, value))
- return FALSE;
- info->within_function = FALSE;
- info->function_end = (bfd_vma) -1;
- }
- break;
- }
- /* A const static symbol in the .text section will have an N_FUN
- entry. We need to use these to mark the end of the function,
- in case we are looking at gcc output before it was changed to
- always emit an empty N_FUN. We can't call debug_end_function
- here, because it might be a local static symbol. */
- if (info->within_function
- && (info->function_end == (bfd_vma) -1
- || value < info->function_end))
- info->function_end = value;
- /* Fall through. */
- /* FIXME: gdb checks the string for N_STSYM, N_LCSYM or N_ROSYM
- symbols, and if it does not start with :S, gdb relocates the
- value to the start of the section. gcc always seems to use
- :S, so we don't worry about this. */
- /* Fall through. */
- default:
- {
- const char *colon;
- colon = strchr (string, ':');
- if (colon != NULL
- && (colon[1] == 'f' || colon[1] == 'F'))
- {
- if (info->within_function)
- {
- bfd_vma endval;
- endval = value;
- if (info->function_end != (bfd_vma) -1
- && info->function_end < endval)
- endval = info->function_end;
- if (! stab_emit_pending_vars (dhandle, info)
- || ! debug_end_function (dhandle, endval))
- return FALSE;
- info->function_end = (bfd_vma) -1;
- }
- /* For stabs in sections, line numbers and block addresses
- are offsets from the start of the function. */
- if (info->sections)
- info->function_start_offset = value;
- info->within_function = TRUE;
- }
- if (! parse_stab_string (dhandle, info, type, desc, value, string))
- return FALSE;
- }
- break;
- case N_OPT:
- if (string != NULL && strcmp (string, "gcc2_compiled.") == 0)
- info->gcc_compiled = 2;
- else if (string != NULL && strcmp (string, "gcc_compiled.") == 0)
- info->gcc_compiled = 1;
- else
- info->n_opt_found = TRUE;
- break;
- case N_OBJ:
- case N_ENDM:
- case N_MAIN:
- case N_WARNING:
- break;
- }
- return TRUE;
- }
- /* Parse the stabs string. */
- static bfd_boolean
- parse_stab_string (void *dhandle, struct stab_handle *info, int stabtype,
- int desc ATTRIBUTE_UNUSED, bfd_vma value, const char *string)
- {
- const char *p;
- char *name;
- int type;
- debug_type dtype;
- bfd_boolean synonym;
- bfd_boolean self_crossref;
- debug_type *slot;
- p = strchr (string, ':');
- if (p == NULL)
- return TRUE;
- while (p[1] == ':')
- {
- p += 2;
- p = strchr (p, ':');
- if (p == NULL)
- {
- bad_stab (string);
- return FALSE;
- }
- }
- /* FIXME: Sometimes the special C++ names start with '.'. */
- name = NULL;
- if (string[0] == '$')
- {
- switch (string[1])
- {
- case 't':
- name = "this";
- break;
- case 'v':
- /* Was: name = "vptr"; */
- break;
- case 'e':
- name = "eh_throw";
- break;
- case '_':
- /* This was an anonymous type that was never fixed up. */
- break;
- case 'X':
- /* SunPRO (3.0 at least) static variable encoding. */
- break;
- default:
- warn_stab (string, _("unknown C++ encoded name"));
- break;
- }
- }
- if (name == NULL)
- {
- if (p == string || (string[0] == ' ' && p == string + 1))
- name = NULL;
- else
- name = savestring (string, p - string);
- }
- ++p;
- if (ISDIGIT (*p) || *p == '(' || *p == '-')
- type = 'l';
- else
- type = *p++;
- switch (type)
- {
- case 'c':
- /* c is a special case, not followed by a type-number.
- SYMBOL:c=iVALUE for an integer constant symbol.
- SYMBOL:c=rVALUE for a floating constant symbol.
- SYMBOL:c=eTYPE,INTVALUE for an enum constant symbol.
- e.g. "b:c=e6,0" for "const b = blob1"
- (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
- if (*p != '=')
- {
- bad_stab (string);
- return FALSE;
- }
- ++p;
- switch (*p++)
- {
- case 'r':
- /* Floating point constant. */
- if (! debug_record_float_const (dhandle, name, atof (p)))
- return FALSE;
- break;
- case 'i':
- /* Integer constant. */
- /* Defining integer constants this way is kind of silly,
- since 'e' constants allows the compiler to give not only
- the value, but the type as well. C has at least int,
- long, unsigned int, and long long as constant types;
- other languages probably should have at least unsigned as
- well as signed constants. */
- if (! debug_record_int_const (dhandle, name, atoi (p)))
- return FALSE;
- break;
- case 'e':
- /* SYMBOL:c=eTYPE,INTVALUE for a constant symbol whose value
- can be represented as integral.
- e.g. "b:c=e6,0" for "const b = blob1"
- (where type 6 is defined by "blobs:t6=eblob1:0,blob2:1,;"). */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (*p != ',')
- {
- bad_stab (string);
- return FALSE;
- }
- if (! debug_record_typed_const (dhandle, name, dtype, atoi (p)))
- return FALSE;
- break;
- default:
- bad_stab (string);
- return FALSE;
- }
- break;
- case 'C':
- /* The name of a caught exception. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- &p, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_label (dhandle, name, dtype, value))
- return FALSE;
- break;
- case 'f':
- case 'F':
- /* A function definition. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_function (dhandle, name, dtype, type == 'F', value))
- return FALSE;
- /* Sun acc puts declared types of arguments here. We don't care
- about their actual types (FIXME -- we should remember the whole
- function prototype), but the list may define some new types
- that we have to remember, so we must scan it now. */
- while (*p == ';')
- {
- ++p;
- if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
- == DEBUG_TYPE_NULL)
- return FALSE;
- }
- break;
- case 'G':
- {
- asymbol **ps;
- /* A global symbol. The value must be extracted from the
- symbol table. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (name != NULL)
- {
- char leading;
- long c;
- leading = bfd_get_symbol_leading_char (info->abfd);
- for (c = info->symcount, ps = info->syms; c > 0; --c, ++ps)
- {
- const char *n;
- n = bfd_asymbol_name (*ps);
- if (leading != '\0' && *n == leading)
- ++n;
- if (*n == *name && strcmp (n, name) == 0)
- break;
- }
- if (c > 0)
- value = bfd_asymbol_value (*ps);
- }
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_GLOBAL,
- value))
- return FALSE;
- }
- break;
- /* This case is faked by a conditional above, when there is no
- code letter in the dbx data. Dbx data never actually
- contains 'l'. */
- case 'l':
- case 's':
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
- value))
- return FALSE;
- break;
- case 'p':
- /* A function parameter. */
- if (*p != 'F')
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- else
- {
- /* pF is a two-letter code that means a function parameter in
- Fortran. The type-number specifies the type of the return
- value. Translate it into a pointer-to-function type. */
- ++p;
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype != DEBUG_TYPE_NULL)
- {
- debug_type ftype;
- ftype = debug_make_function_type (dhandle, dtype,
- (debug_type *) NULL, FALSE);
- dtype = debug_make_pointer_type (dhandle, ftype);
- }
- }
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_STACK,
- value))
- return FALSE;
- /* FIXME: At this point gdb considers rearranging the parameter
- address on a big endian machine if it is smaller than an int.
- We have no way to do that, since we don't really know much
- about the target. */
- break;
- case 'P':
- if (stabtype == N_FUN)
- {
- /* Prototype of a function referenced by this file. */
- while (*p == ';')
- {
- ++p;
- if (parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL)
- == DEBUG_TYPE_NULL)
- return FALSE;
- }
- break;
- }
- /* Fall through. */
- case 'R':
- /* Parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REG,
- value))
- return FALSE;
- break;
- case 'r':
- /* Register variable (either global or local). */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_REGISTER,
- value))
- return FALSE;
- /* FIXME: At this point gdb checks to combine pairs of 'p' and
- 'r' stabs into a single 'P' stab. */
- break;
- case 'S':
- /* Static symbol at top level of file. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_STATIC,
- value))
- return FALSE;
- break;
- case 't':
- /* A typedef. */
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (name == NULL)
- {
- /* A nameless type. Nothing to do. */
- return TRUE;
- }
- dtype = debug_name_type (dhandle, name, dtype);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (slot != NULL)
- *slot = dtype;
- break;
- case 'T':
- /* Struct, union, or enum tag. For GNU C++, this can be be followed
- by 't' which means we are typedef'ing it as well. */
- if (*p != 't')
- {
- synonym = FALSE;
- /* FIXME: gdb sets synonym to TRUE if the current language
- is C++. */
- }
- else
- {
- synonym = TRUE;
- ++p;
- }
- dtype = parse_stab_type (dhandle, info, name, &p, &slot);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (name == NULL)
- return TRUE;
- /* INFO->SELF_CROSSREF is set by parse_stab_type if this type is
- a cross reference to itself. These are generated by some
- versions of g++. */
- self_crossref = info->self_crossref;
- dtype = debug_tag_type (dhandle, name, dtype);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (slot != NULL)
- *slot = dtype;
- /* See if we have a cross reference to this tag which we can now
- fill in. Avoid filling in a cross reference to ourselves,
- because that would lead to circular debugging information. */
- if (! self_crossref)
- {
- register struct stab_tag **pst;
- for (pst = &info->tags; *pst != NULL; pst = &(*pst)->next)
- {
- if ((*pst)->name[0] == name[0]
- && strcmp ((*pst)->name, name) == 0)
- {
- (*pst)->slot = dtype;
- *pst = (*pst)->next;
- break;
- }
- }
- }
- if (synonym)
- {
- dtype = debug_name_type (dhandle, name, dtype);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (slot != NULL)
- *slot = dtype;
- }
- break;
- case 'V':
- /* Static symbol of local scope */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- /* FIXME: gdb checks os9k_stabs here. */
- if (! stab_record_variable (dhandle, info, name, dtype,
- DEBUG_LOCAL_STATIC, value))
- return FALSE;
- break;
- case 'v':
- /* Reference parameter. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REFERENCE,
- value))
- return FALSE;
- break;
- case 'a':
- /* Reference parameter which is in a register. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! debug_record_parameter (dhandle, name, dtype, DEBUG_PARM_REF_REG,
- value))
- return FALSE;
- break;
- case 'X':
- /* This is used by Sun FORTRAN for "function result value".
- Sun claims ("dbx and dbxtool interfaces", 2nd ed)
- that Pascal uses it too, but when I tried it Pascal used
- "x:3" (local symbol) instead. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL, &p,
- (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return FALSE;
- if (! stab_record_variable (dhandle, info, name, dtype, DEBUG_LOCAL,
- value))
- return FALSE;
- break;
- case 'Y':
- /* SUNPro C++ Namespace =Yn0. */
- /* Skip the namespace mapping, as it is not used now. */
- if (*(++p) == 'n' && *(++p) == '0')
- {
- /* =Yn0name; */
- while (*p != ';')
- ++p;
- ++p;
- return TRUE;
- }
- /* TODO SUNPro C++ support:
- Support default arguments after F,P parameters
- Ya = Anonymous unions
- YM,YD = Pointers to class members
- YT,YI = Templates
- YR = Run-time type information (RTTI) */
- /* Fall through. */
- default:
- bad_stab (string);
- return FALSE;
- }
- /* FIXME: gdb converts structure values to structure pointers in a
- couple of cases, depending upon the target. */
- return TRUE;
- }
- /* Parse a stabs type. The typename argument is non-NULL if this is a
- typedef or a tag definition. The pp argument points to the stab
- string, and is updated. The slotp argument points to a place to
- store the slot used if the type is being defined. */
- static debug_type
- parse_stab_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, debug_type **slotp)
- {
- const char *orig;
- int typenums[2];
- int size;
- bfd_boolean stringp;
- int descriptor;
- debug_type dtype;
- if (slotp != NULL)
- *slotp = NULL;
- orig = *pp;
- size = -1;
- stringp = FALSE;
- info->self_crossref = FALSE;
- /* Read type number if present. The type number may be omitted.
- for instance in a two-dimensional array declared with type
- "ar1;1;10;ar1;1;10;4". */
- if (! ISDIGIT (**pp) && **pp != '(' && **pp != '-')
- {
- /* 'typenums=' not present, type is anonymous. Read and return
- the definition, but don't put it in the type vector. */
- typenums[0] = typenums[1] = -1;
- }
- else
- {
- if (! parse_stab_type_number (pp, typenums))
- return DEBUG_TYPE_NULL;
- if (**pp != '=')
- /* Type is not being defined here. Either it already
- exists, or this is a forward reference to it. */
- return stab_find_type (dhandle, info, typenums);
- /* Only set the slot if the type is being defined. This means
- that the mapping from type numbers to types will only record
- the name of the typedef which defines a type. If we don't do
- this, then something like
- typedef int foo;
- int i;
- will record that i is of type foo. Unfortunately, stabs
- information is ambiguous about variable types. For this code,
- typedef int foo;
- int i;
- foo j;
- the stabs information records both i and j as having the same
- type. This could be fixed by patching the compiler. */
- if (slotp != NULL && typenums[0] >= 0 && typenums[1] >= 0)
- *slotp = stab_find_slot (info, typenums);
- /* Type is being defined here. */
- /* Skip the '='. */
- ++*pp;
- while (**pp == '@')
- {
- const char *p = *pp + 1;
- const char *attr;
- if (ISDIGIT (*p) || *p == '(' || *p == '-')
- /* Member type. */
- break;
- /* Type attributes. */
- attr = p;
- for (; *p != ';'; ++p)
- {
- if (*p == '\0')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- }
- *pp = p + 1;
- switch (*attr)
- {
- case 's':
- size = atoi (attr + 1);
- size /= 8; /* Size is in bits. We store it in bytes. */
- if (size <= 0)
- size = -1;
- break;
- case 'S':
- stringp = TRUE;
- break;
- default:
- /* Ignore unrecognized type attributes, so future
- compilers can invent new ones. */
- break;
- }
- }
- }
- descriptor = **pp;
- ++*pp;
- switch (descriptor)
- {
- case 'x':
- {
- enum debug_type_kind code;
- const char *q1, *q2, *p;
- /* A cross reference to another type. */
- switch (**pp)
- {
- case 's':
- code = DEBUG_KIND_STRUCT;
- break;
- case 'u':
- code = DEBUG_KIND_UNION;
- break;
- case 'e':
- code = DEBUG_KIND_ENUM;
- break;
- default:
- /* Complain and keep going, so compilers can invent new
- cross-reference types. */
- warn_stab (orig, _("unrecognized cross reference type"));
- code = DEBUG_KIND_STRUCT;
- break;
- }
- ++*pp;
- q1 = strchr (*pp, '<');
- p = strchr (*pp, ':');
- if (p == NULL)
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- if (q1 != NULL && p > q1 && p[1] == ':')
- {
- int nest = 0;
- for (q2 = q1; *q2 != '\0'; ++q2)
- {
- if (*q2 == '<')
- ++nest;
- else if (*q2 == '>')
- --nest;
- else if (*q2 == ':' && nest == 0)
- break;
- }
- p = q2;
- if (*p != ':')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- }
- /* Some versions of g++ can emit stabs like
- fleep:T20=xsfleep:
- which define structures in terms of themselves. We need to
- tell the caller to avoid building a circular structure. */
- if (type_name != NULL
- && strncmp (type_name, *pp, p - *pp) == 0
- && type_name[p - *pp] == '\0')
- info->self_crossref = TRUE;
- dtype = stab_find_tagged_type (dhandle, info, *pp, p - *pp, code);
- *pp = p + 1;
- }
- break;
- case '-':
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- case '(':
- {
- const char *hold;
- int xtypenums[2];
- /* This type is defined as another type. */
- (*pp)--;
- hold = *pp;
- /* Peek ahead at the number to detect void. */
- if (! parse_stab_type_number (pp, xtypenums))
- return DEBUG_TYPE_NULL;
- if (typenums[0] == xtypenums[0] && typenums[1] == xtypenums[1])
- {
- /* This type is being defined as itself, which means that
- it is void. */
- dtype = debug_make_void_type (dhandle);
- }
- else
- {
- *pp = hold;
- /* Go back to the number and have parse_stab_type get it.
- This means that we can deal with something like
- t(1,2)=(3,4)=... which the Lucid compiler uses. */
- dtype = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (dtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- }
- if (typenums[0] != -1)
- {
- if (! stab_record_type (dhandle, info, typenums, dtype))
- return DEBUG_TYPE_NULL;
- }
- break;
- }
- case '*':
- dtype = debug_make_pointer_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL));
- break;
- case '&':
- /* Reference to another type. */
- dtype = (debug_make_reference_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
- break;
- case 'f':
- /* Function returning another type. */
- /* FIXME: gdb checks os9k_stabs here. */
- dtype = (debug_make_function_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL),
- (debug_type *) NULL, FALSE));
- break;
- case 'k':
- /* Const qualifier on some type (Sun). */
- /* FIXME: gdb accepts 'c' here if os9k_stabs. */
- dtype = debug_make_const_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL));
- break;
- case 'B':
- /* Volatile qual on some type (Sun). */
- /* FIXME: gdb accepts 'i' here if os9k_stabs. */
- dtype = (debug_make_volatile_type
- (dhandle,
- parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL)));
- break;
- case '@':
- /* Offset (class & variable) type. This is used for a pointer
- relative to an object. */
- {
- debug_type domain;
- debug_type memtype;
- /* Member type. */
- domain = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (domain == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- memtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (memtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- dtype = debug_make_offset_type (dhandle, domain, memtype);
- }
- break;
- case '#':
- /* Method (class & fn) type. */
- if (**pp == '#')
- {
- debug_type return_type;
- ++*pp;
- return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (return_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- dtype = debug_make_method_type (dhandle, return_type,
- DEBUG_TYPE_NULL,
- (debug_type *) NULL, FALSE);
- }
- else
- {
- debug_type domain;
- debug_type return_type;
- debug_type *args;
- unsigned int n;
- unsigned int alloc;
- bfd_boolean varargs;
- domain = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (domain == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- return_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (return_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- alloc = 10;
- args = (debug_type *) xmalloc (alloc * sizeof *args);
- n = 0;
- while (**pp != ';')
- {
- if (**pp != ',')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- if (n + 1 >= alloc)
- {
- alloc += 10;
- args = ((debug_type *)
- xrealloc (args, alloc * sizeof *args));
- }
- args[n] = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (args[n] == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- ++n;
- }
- ++*pp;
- /* If the last type is not void, then this function takes a
- variable number of arguments. Otherwise, we must strip
- the void type. */
- if (n == 0
- || debug_get_type_kind (dhandle, args[n - 1]) != DEBUG_KIND_VOID)
- varargs = TRUE;
- else
- {
- --n;
- varargs = FALSE;
- }
- args[n] = DEBUG_TYPE_NULL;
- dtype = debug_make_method_type (dhandle, return_type, domain, args,
- varargs);
- }
- break;
- case 'r':
- /* Range type. */
- dtype = parse_stab_range_type (dhandle, info, type_name, pp, typenums);
- break;
- case 'b':
- /* FIXME: gdb checks os9k_stabs here. */
- /* Sun ACC builtin int type. */
- dtype = parse_stab_sun_builtin_type (dhandle, pp);
- break;
- case 'R':
- /* Sun ACC builtin float type. */
- dtype = parse_stab_sun_floating_type (dhandle, pp);
- break;
- case 'e':
- /* Enumeration type. */
- dtype = parse_stab_enum_type (dhandle, pp);
- break;
- case 's':
- case 'u':
- /* Struct or union type. */
- dtype = parse_stab_struct_type (dhandle, info, type_name, pp,
- descriptor == 's', typenums);
- break;
- case 'a':
- /* Array type. */
- if (**pp != 'r')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- dtype = parse_stab_array_type (dhandle, info, pp, stringp);
- break;
- case 'S':
- dtype = debug_make_set_type (dhandle,
- parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL),
- stringp);
- break;
- default:
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- if (dtype == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (typenums[0] != -1)
- {
- if (! stab_record_type (dhandle, info, typenums, dtype))
- return DEBUG_TYPE_NULL;
- }
- if (size != -1)
- {
- if (! debug_record_type_size (dhandle, dtype, (unsigned int) size))
- return DEBUG_TYPE_NULL;
- }
- return dtype;
- }
- /* Read a number by which a type is referred to in dbx data, or
- perhaps read a pair (FILENUM, TYPENUM) in parentheses. Just a
- single number N is equivalent to (0,N). Return the two numbers by
- storing them in the vector TYPENUMS. */
- static bfd_boolean
- parse_stab_type_number (const char **pp, int *typenums)
- {
- const char *orig;
- orig = *pp;
- if (**pp != '(')
- {
- typenums[0] = 0;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
- }
- else
- {
- ++*pp;
- typenums[0] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- typenums[1] = (int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ')')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- }
- return TRUE;
- }
- /* Parse a range type. */
- static debug_type
- parse_stab_range_type (void *dhandle, struct stab_handle *info, const char *type_name, const char **pp, const int *typenums)
- {
- const char *orig;
- int rangenums[2];
- bfd_boolean self_subrange;
- debug_type index_type;
- const char *s2, *s3;
- bfd_signed_vma n2, n3;
- bfd_boolean ov2, ov3;
- orig = *pp;
- index_type = DEBUG_TYPE_NULL;
- /* First comes a type we are a subrange of.
- In C it is usually 0, 1 or the type being defined. */
- if (! parse_stab_type_number (pp, rangenums))
- return DEBUG_TYPE_NULL;
- self_subrange = (rangenums[0] == typenums[0]
- && rangenums[1] == typenums[1]);
- if (**pp == '=')
- {
- *pp = orig;
- index_type = parse_stab_type (dhandle, info, (const char *) NULL,
- pp, (debug_type **) NULL);
- if (index_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- }
- if (**pp == ';')
- ++*pp;
- /* The remaining two operands are usually lower and upper bounds of
- the range. But in some special cases they mean something else. */
- s2 = *pp;
- n2 = parse_number (pp, &ov2);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- s3 = *pp;
- n3 = parse_number (pp, &ov3);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- if (ov2 || ov3)
- {
- /* gcc will emit range stabs for long long types. Handle this
- as a special case. FIXME: This needs to be more general. */
- #define LLLOW "01000000000000000000000;"
- #define LLHIGH "0777777777777777777777;"
- #define ULLHIGH "01777777777777777777777;"
- if (index_type == DEBUG_TYPE_NULL)
- {
- if (CONST_STRNEQ (s2, LLLOW)
- && CONST_STRNEQ (s3, LLHIGH))
- return debug_make_int_type (dhandle, 8, FALSE);
- if (! ov2
- && n2 == 0
- && CONST_STRNEQ (s3, ULLHIGH))
- return debug_make_int_type (dhandle, 8, TRUE);
- }
- warn_stab (orig, _("numeric overflow"));
- }
- if (index_type == DEBUG_TYPE_NULL)
- {
- /* A type defined as a subrange of itself, with both bounds 0,
- is void. */
- if (self_subrange && n2 == 0 && n3 == 0)
- return debug_make_void_type (dhandle);
- /* A type defined as a subrange of itself, with n2 positive and
- n3 zero, is a complex type, and n2 is the number of bytes. */
- if (self_subrange && n3 == 0 && n2 > 0)
- return debug_make_complex_type (dhandle, n2);
- /* If n3 is zero and n2 is positive, this is a floating point
- type, and n2 is the number of bytes. */
- if (n3 == 0 && n2 > 0)
- return debug_make_float_type (dhandle, n2);
- /* If the upper bound is -1, this is an unsigned int. */
- if (n2 == 0 && n3 == -1)
- {
- /* When gcc is used with -gstabs, but not -gstabs+, it will emit
- long long int:t6=r1;0;-1;
- long long unsigned int:t7=r1;0;-1;
- We hack here to handle this reasonably. */
- if (type_name != NULL)
- {
- if (strcmp (type_name, "long long int") == 0)
- return debug_make_int_type (dhandle, 8, FALSE);
- else if (strcmp (type_name, "long long unsigned int") == 0)
- return debug_make_int_type (dhandle, 8, TRUE);
- }
- /* FIXME: The size here really depends upon the target. */
- return debug_make_int_type (dhandle, 4, TRUE);
- }
- /* A range of 0 to 127 is char. */
- if (self_subrange && n2 == 0 && n3 == 127)
- return debug_make_int_type (dhandle, 1, FALSE);
- /* FIXME: gdb checks for the language CHILL here. */
- if (n2 == 0)
- {
- if (n3 < 0)
- return debug_make_int_type (dhandle, - n3, TRUE);
- else if (n3 == 0xff)
- return debug_make_int_type (dhandle, 1, TRUE);
- else if (n3 == 0xffff)
- return debug_make_int_type (dhandle, 2, TRUE);
- else if (n3 == (bfd_signed_vma) 0xffffffff)
- return debug_make_int_type (dhandle, 4, TRUE);
- #ifdef BFD64
- else if (n3 == (bfd_signed_vma) 0xffffffffffffffffLL)
- return debug_make_int_type (dhandle, 8, TRUE);
- #endif
- }
- else if (n3 == 0
- && n2 < 0
- && (self_subrange || n2 == -8))
- return debug_make_int_type (dhandle, - n2, TRUE);
- else if (n2 == - n3 - 1 || n2 == n3 + 1)
- {
- if (n3 == 0x7f)
- return debug_make_int_type (dhandle, 1, FALSE);
- else if (n3 == 0x7fff)
- return debug_make_int_type (dhandle, 2, FALSE);
- else if (n3 == 0x7fffffff)
- return debug_make_int_type (dhandle, 4, FALSE);
- #ifdef BFD64
- else if (n3 == ((((bfd_vma) 0x7fffffff) << 32) | 0xffffffff))
- return debug_make_int_type (dhandle, 8, FALSE);
- #endif
- }
- }
- /* At this point I don't have the faintest idea how to deal with a
- self_subrange type; I'm going to assume that this is used as an
- idiom, and that all of them are special cases. So . . . */
- if (self_subrange)
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- index_type = stab_find_type (dhandle, info, rangenums);
- if (index_type == DEBUG_TYPE_NULL)
- {
- /* Does this actually ever happen? Is that why we are worrying
- about dealing with it rather than just calling error_type? */
- warn_stab (orig, _("missing index type"));
- index_type = debug_make_int_type (dhandle, 4, FALSE);
- }
- return debug_make_range_type (dhandle, index_type, n2, n3);
- }
- /* Sun's ACC uses a somewhat saner method for specifying the builtin
- typedefs in every file (for int, long, etc):
- type = b <signed> <width>; <offset>; <nbits>
- signed = u or s. Possible c in addition to u or s (for char?).
- offset = offset from high order bit to start bit of type.
- width is # bytes in object of this type, nbits is # bits in type.
- The width/offset stuff appears to be for small objects stored in
- larger ones (e.g. `shorts' in `int' registers). We ignore it for now,
- FIXME. */
- static debug_type
- parse_stab_sun_builtin_type (void *dhandle, const char **pp)
- {
- const char *orig;
- bfd_boolean unsignedp;
- bfd_vma bits;
- orig = *pp;
- switch (**pp)
- {
- case 's':
- unsignedp = FALSE;
- break;
- case 'u':
- unsignedp = TRUE;
- break;
- default:
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- /* OpenSolaris source code indicates that one of "cbv" characters
- can come next and specify the intrinsic 'iformat' encoding.
- 'c' is character encoding, 'b' is boolean encoding, and 'v' is
- varargs encoding. This field can be safely ignored because
- the type of the field is determined from the bitwidth extracted
- below. */
- if (**pp == 'c' || **pp == 'b' || **pp == 'v')
- ++*pp;
- /* The first number appears to be the number of bytes occupied
- by this type, except that unsigned short is 4 instead of 2.
- Since this information is redundant with the third number,
- we will ignore it. */
- (void) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- /* The second number is always 0, so ignore it too. */
- (void) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- /* The third number is the number of bits for this type. */
- bits = parse_number (pp, (bfd_boolean *) NULL);
- /* The type *should* end with a semicolon. If it are embedded
- in a larger type the semicolon may be the only way to know where
- the type ends. If this type is at the end of the stabstring we
- can deal with the omitted semicolon (but we don't have to like
- it). Don't bother to complain(), Sun's compiler omits the semicolon
- for "void". */
- if (**pp == ';')
- ++*pp;
- if (bits == 0)
- return debug_make_void_type (dhandle);
- return debug_make_int_type (dhandle, bits / 8, unsignedp);
- }
- /* Parse a builtin floating type generated by the Sun compiler. */
- static debug_type
- parse_stab_sun_floating_type (void *dhandle, const char **pp)
- {
- const char *orig;
- bfd_vma details;
- bfd_vma bytes;
- orig = *pp;
- /* The first number has more details about the type, for example
- FN_COMPLEX. */
- details = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- /* The second number is the number of bytes occupied by this type */
- bytes = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- if (details == NF_COMPLEX
- || details == NF_COMPLEX16
- || details == NF_COMPLEX32)
- return debug_make_complex_type (dhandle, bytes);
- return debug_make_float_type (dhandle, bytes);
- }
- /* Handle an enum type. */
- static debug_type
- parse_stab_enum_type (void *dhandle, const char **pp)
- {
- const char *orig;
- const char **names;
- bfd_signed_vma *values;
- unsigned int n;
- unsigned int alloc;
- orig = *pp;
- /* FIXME: gdb checks os9k_stabs here. */
- /* The aix4 compiler emits an extra field before the enum members;
- my guess is it's a type of some sort. Just ignore it. */
- if (**pp == '-')
- {
- while (**pp != ':')
- ++*pp;
- ++*pp;
- }
- /* Read the value-names and their values.
- The input syntax is NAME:VALUE,NAME:VALUE, and so on.
- A semicolon or comma instead of a NAME means the end. */
- alloc = 10;
- names = (const char **) xmalloc (alloc * sizeof *names);
- values = (bfd_signed_vma *) xmalloc (alloc * sizeof *values);
- n = 0;
- while (**pp != '\0' && **pp != ';' && **pp != ',')
- {
- const char *p;
- char *name;
- bfd_signed_vma val;
- p = *pp;
- while (*p != ':')
- ++p;
- name = savestring (*pp, p - *pp);
- *pp = p + 1;
- val = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- free (name);
- free (names);
- free (values);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- if (n + 1 >= alloc)
- {
- alloc += 10;
- names = ((const char **)
- xrealloc (names, alloc * sizeof *names));
- values = ((bfd_signed_vma *)
- xrealloc (values, alloc * sizeof *values));
- }
- names[n] = name;
- values[n] = val;
- ++n;
- }
- names[n] = NULL;
- values[n] = 0;
- if (**pp == ';')
- ++*pp;
- return debug_make_enum_type (dhandle, names, values);
- }
- /* Read the description of a structure (or union type) and return an object
- describing the type.
- PP points to a character pointer that points to the next unconsumed token
- in the stabs string. For example, given stabs "A:T4=s4a:1,0,32;;",
- *PP will point to "4a:1,0,32;;". */
- static debug_type
- parse_stab_struct_type (void *dhandle, struct stab_handle *info,
- const char *tagname, const char **pp,
- bfd_boolean structp, const int *typenums)
- {
- bfd_vma size;
- debug_baseclass *baseclasses;
- debug_field *fields = NULL;
- bfd_boolean statics;
- debug_method *methods;
- debug_type vptrbase;
- bfd_boolean ownvptr;
- /* Get the size. */
- size = parse_number (pp, (bfd_boolean *) NULL);
- /* Get the other information. */
- if (! parse_stab_baseclasses (dhandle, info, pp, &baseclasses)
- || ! parse_stab_struct_fields (dhandle, info, pp, &fields, &statics)
- || ! parse_stab_members (dhandle, info, tagname, pp, typenums, &methods)
- || ! parse_stab_tilde_field (dhandle, info, pp, typenums, &vptrbase,
- &ownvptr))
- {
- if (fields != NULL)
- free (fields);
- return DEBUG_TYPE_NULL;
- }
- if (! statics
- && baseclasses == NULL
- && methods == NULL
- && vptrbase == DEBUG_TYPE_NULL
- && ! ownvptr)
- return debug_make_struct_type (dhandle, structp, size, fields);
- return debug_make_object_type (dhandle, structp, size, fields, baseclasses,
- methods, vptrbase, ownvptr);
- }
- /* The stabs for C++ derived classes contain baseclass information which
- is marked by a '!' character after the total size. This function is
- called when we encounter the baseclass marker, and slurps up all the
- baseclass information.
- Immediately following the '!' marker is the number of base classes that
- the class is derived from, followed by information for each base class.
- For each base class, there are two visibility specifiers, a bit offset
- to the base class information within the derived class, a reference to
- the type for the base class, and a terminating semicolon.
- A typical example, with two base classes, would be "!2,020,19;0264,21;".
- ^^ ^ ^ ^ ^ ^ ^
- Baseclass information marker __________________|| | | | | | |
- Number of baseclasses __________________________| | | | | | |
- Visibility specifiers (2) ________________________| | | | | |
- Offset in bits from start of class _________________| | | | |
- Type number for base class ___________________________| | | |
- Visibility specifiers (2) _______________________________| | |
- Offset in bits from start of class ________________________| |
- Type number of base class ____________________________________|
- Return TRUE for success, FALSE for failure. */
- static bfd_boolean
- parse_stab_baseclasses (void *dhandle, struct stab_handle *info,
- const char **pp, debug_baseclass **retp)
- {
- const char *orig;
- unsigned int c, i;
- debug_baseclass *classes;
- *retp = NULL;
- orig = *pp;
- if (**pp != '!')
- {
- /* No base classes. */
- return TRUE;
- }
- ++*pp;
- c = (unsigned int) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- classes = (debug_baseclass *) xmalloc ((c + 1) * sizeof (**retp));
- for (i = 0; i < c; i++)
- {
- bfd_boolean is_virtual;
- enum debug_visibility visibility;
- bfd_vma bitpos;
- debug_type type;
- switch (**pp)
- {
- case '0':
- is_virtual = FALSE;
- break;
- case '1':
- is_virtual = TRUE;
- break;
- default:
- warn_stab (orig, _("unknown virtual character for baseclass"));
- is_virtual = FALSE;
- break;
- }
- ++*pp;
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- case '2':
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- default:
- warn_stab (orig, _("unknown visibility character for baseclass"));
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
- /* The remaining value is the bit offset of the portion of the
- object corresponding to this baseclass. Always zero in the
- absence of multiple inheritance. */
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
- classes[i] = debug_make_baseclass (dhandle, type, bitpos, is_virtual,
- visibility);
- if (classes[i] == DEBUG_BASECLASS_NULL)
- return FALSE;
- if (**pp != ';')
- return FALSE;
- ++*pp;
- }
- classes[i] = DEBUG_BASECLASS_NULL;
- *retp = classes;
- return TRUE;
- }
- /* Read struct or class data fields. They have the form:
- NAME : [VISIBILITY] TYPENUM , BITPOS , BITSIZE ;
- At the end, we see a semicolon instead of a field.
- In C++, this may wind up being NAME:?TYPENUM:PHYSNAME; for
- a static field.
- The optional VISIBILITY is one of:
- '/0' (VISIBILITY_PRIVATE)
- '/1' (VISIBILITY_PROTECTED)
- '/2' (VISIBILITY_PUBLIC)
- '/9' (VISIBILITY_IGNORE)
- or nothing, for C style fields with public visibility.
- Returns 1 for success, 0 for failure. */
- static bfd_boolean
- parse_stab_struct_fields (void *dhandle, struct stab_handle *info,
- const char **pp, debug_field **retp,
- bfd_boolean *staticsp)
- {
- const char *orig;
- const char *p;
- debug_field *fields;
- unsigned int c;
- unsigned int alloc;
- *retp = NULL;
- *staticsp = FALSE;
- orig = *pp;
- c = 0;
- alloc = 10;
- fields = (debug_field *) xmalloc (alloc * sizeof *fields);
- while (**pp != ';')
- {
- /* FIXME: gdb checks os9k_stabs here. */
- p = *pp;
- /* Add 1 to c to leave room for NULL pointer at end. */
- if (c + 1 >= alloc)
- {
- alloc += 10;
- fields = ((debug_field *)
- xrealloc (fields, alloc * sizeof *fields));
- }
- /* If it starts with CPLUS_MARKER it is a special abbreviation,
- unless the CPLUS_MARKER is followed by an underscore, in
- which case it is just the name of an anonymous type, which we
- should handle like any other type name. We accept either '$'
- or '.', because a field name can never contain one of these
- characters except as a CPLUS_MARKER. */
- if ((*p == '$' || *p == '.') && p[1] != '_')
- {
- ++*pp;
- if (! parse_stab_cpp_abbrev (dhandle, info, pp, fields + c))
- {
- free (fields);
- return FALSE;
- }
- ++c;
- continue;
- }
- /* Look for the ':' that separates the field name from the field
- values. Data members are delimited by a single ':', while member
- functions are delimited by a pair of ':'s. When we hit the member
- functions (if any), terminate scan loop and return. */
- p = strchr (p, ':');
- if (p == NULL)
- {
- bad_stab (orig);
- free (fields);
- return FALSE;
- }
- if (p[1] == ':')
- break;
- if (! parse_stab_one_struct_field (dhandle, info, pp, p, fields + c,
- staticsp))
- return FALSE;
- ++c;
- }
- fields[c] = DEBUG_FIELD_NULL;
- *retp = fields;
- return TRUE;
- }
- /* Special GNU C++ name. */
- static bfd_boolean
- parse_stab_cpp_abbrev (void *dhandle, struct stab_handle *info,
- const char **pp, debug_field *retp)
- {
- const char *orig;
- int cpp_abbrev;
- debug_type context;
- const char *name;
- const char *type_name;
- debug_type type;
- bfd_vma bitpos;
- *retp = DEBUG_FIELD_NULL;
- orig = *pp;
- if (**pp != 'v')
- {
- bad_stab (*pp);
- return FALSE;
- }
- ++*pp;
- cpp_abbrev = **pp;
- ++*pp;
- /* At this point, *pp points to something like "22:23=*22...", where
- the type number before the ':' is the "context" and everything
- after is a regular type definition. Lookup the type, find it's
- name, and construct the field name. */
- context = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (context == DEBUG_TYPE_NULL)
- return FALSE;
- switch (cpp_abbrev)
- {
- case 'f':
- /* $vf -- a virtual function table pointer. */
- name = "_vptr$";
- break;
- case 'b':
- /* $vb -- a virtual bsomethingorother */
- type_name = debug_get_type_name (dhandle, context);
- if (type_name == NULL)
- {
- warn_stab (orig, _("unnamed $vb type"));
- type_name = "FOO";
- }
- name = concat ("_vb$", type_name, (const char *) NULL);
- break;
- default:
- warn_stab (orig, _("unrecognized C++ abbreviation"));
- name = "INVALID_CPLUSPLUS_ABBREV";
- break;
- }
- if (**pp != ':')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
- ++*pp;
- *retp = debug_make_field (dhandle, name, type, bitpos, 0,
- DEBUG_VISIBILITY_PRIVATE);
- if (*retp == DEBUG_FIELD_NULL)
- return FALSE;
- return TRUE;
- }
- /* Parse a single field in a struct or union. */
- static bfd_boolean
- parse_stab_one_struct_field (void *dhandle, struct stab_handle *info,
- const char **pp, const char *p,
- debug_field *retp, bfd_boolean *staticsp)
- {
- const char *orig;
- char *name;
- enum debug_visibility visibility;
- debug_type type;
- bfd_vma bitpos;
- bfd_vma bitsize;
- orig = *pp;
- /* FIXME: gdb checks ARM_DEMANGLING here. */
- name = savestring (*pp, p - *pp);
- *pp = p + 1;
- if (**pp != '/')
- visibility = DEBUG_VISIBILITY_PUBLIC;
- else
- {
- ++*pp;
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- case '2':
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- default:
- warn_stab (orig, _("unknown visibility character for field"));
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
- }
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- {
- free (name);
- return FALSE;
- }
- if (**pp == ':')
- {
- char *varname;
- /* This is a static class member. */
- ++*pp;
- p = strchr (*pp, ';');
- if (p == NULL)
- {
- bad_stab (orig);
- free (name);
- return FALSE;
- }
- varname = savestring (*pp, p - *pp);
- *pp = p + 1;
- *retp = debug_make_static_member (dhandle, name, type, varname,
- visibility);
- *staticsp = TRUE;
- return TRUE;
- }
- if (**pp != ',')
- {
- bad_stab (orig);
- free (name);
- return FALSE;
- }
- ++*pp;
- bitpos = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ',')
- {
- bad_stab (orig);
- free (name);
- return FALSE;
- }
- ++*pp;
- bitsize = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- free (name);
- return FALSE;
- }
- ++*pp;
- if (bitpos == 0 && bitsize == 0)
- {
- /* This can happen in two cases: (1) at least for gcc 2.4.5 or
- so, it is a field which has been optimized out. The correct
- stab for this case is to use VISIBILITY_IGNORE, but that is a
- recent invention. (2) It is a 0-size array. For example
- union { int num; char str[0]; } foo. Printing "<no value>"
- for str in "p foo" is OK, since foo.str (and thus foo.str[3])
- will continue to work, and a 0-size array as a whole doesn't
- have any contents to print.
- I suspect this probably could also happen with gcc -gstabs
- (not -gstabs+) for static fields, and perhaps other C++
- extensions. Hopefully few people use -gstabs with gdb, since
- it is intended for dbx compatibility. */
- visibility = DEBUG_VISIBILITY_IGNORE;
- }
- /* FIXME: gdb does some stuff here to mark fields as unpacked. */
- *retp = debug_make_field (dhandle, name, type, bitpos, bitsize, visibility);
- return TRUE;
- }
- /* Read member function stabs info for C++ classes. The form of each member
- function data is:
- NAME :: TYPENUM[=type definition] ARGS : PHYSNAME ;
- An example with two member functions is:
- afunc1::20=##15;:i;2A.;afunc2::20:i;2A.;
- For the case of overloaded operators, the format is op$::*.funcs, where
- $ is the CPLUS_MARKER (usually '$'), `*' holds the place for an operator
- name (such as `+=') and `.' marks the end of the operator name. */
- static bfd_boolean
- parse_stab_members (void *dhandle, struct stab_handle *info,
- const char *tagname, const char **pp,
- const int *typenums, debug_method **retp)
- {
- const char *orig;
- debug_method *methods;
- unsigned int c;
- unsigned int alloc;
- char *name = NULL;
- debug_method_variant *variants = NULL;
- char *argtypes = NULL;
- *retp = NULL;
- orig = *pp;
- alloc = 0;
- methods = NULL;
- c = 0;
- while (**pp != ';')
- {
- const char *p;
- unsigned int cvars;
- unsigned int allocvars;
- debug_type look_ahead_type;
- p = strchr (*pp, ':');
- if (p == NULL || p[1] != ':')
- break;
- /* FIXME: Some systems use something other than '$' here. */
- if ((*pp)[0] != 'o' || (*pp)[1] != 'p' || (*pp)[2] != '$')
- {
- name = savestring (*pp, p - *pp);
- *pp = p + 2;
- }
- else
- {
- /* This is a completely weird case. In order to stuff in the
- names that might contain colons (the usual name delimiter),
- Mike Tiemann defined a different name format which is
- signalled if the identifier is "op$". In that case, the
- format is "op$::XXXX." where XXXX is the name. This is
- used for names like "+" or "=". YUUUUUUUK! FIXME! */
- *pp = p + 2;
- for (p = *pp; *p != '.' && *p != '\0'; p++)
- ;
- if (*p != '.')
- {
- bad_stab (orig);
- goto fail;
- }
- name = savestring (*pp, p - *pp);
- *pp = p + 1;
- }
- allocvars = 10;
- variants = ((debug_method_variant *)
- xmalloc (allocvars * sizeof *variants));
- cvars = 0;
- look_ahead_type = DEBUG_TYPE_NULL;
- do
- {
- debug_type type;
- bfd_boolean stub;
- enum debug_visibility visibility;
- bfd_boolean constp, volatilep, staticp;
- bfd_vma voffset;
- debug_type context;
- const char *physname;
- bfd_boolean varargs;
- if (look_ahead_type != DEBUG_TYPE_NULL)
- {
- /* g++ version 1 kludge */
- type = look_ahead_type;
- look_ahead_type = DEBUG_TYPE_NULL;
- }
- else
- {
- type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (type == DEBUG_TYPE_NULL)
- goto fail;
- if (**pp != ':')
- {
- bad_stab (orig);
- goto fail;
- }
- }
- ++*pp;
- p = strchr (*pp, ';');
- if (p == NULL)
- {
- bad_stab (orig);
- goto fail;
- }
- stub = FALSE;
- if (debug_get_type_kind (dhandle, type) == DEBUG_KIND_METHOD
- && debug_get_parameter_types (dhandle, type, &varargs) == NULL)
- stub = TRUE;
- argtypes = savestring (*pp, p - *pp);
- *pp = p + 1;
- switch (**pp)
- {
- case '0':
- visibility = DEBUG_VISIBILITY_PRIVATE;
- break;
- case '1':
- visibility = DEBUG_VISIBILITY_PROTECTED;
- break;
- default:
- visibility = DEBUG_VISIBILITY_PUBLIC;
- break;
- }
- ++*pp;
- constp = FALSE;
- volatilep = FALSE;
- switch (**pp)
- {
- case 'A':
- /* Normal function. */
- ++*pp;
- break;
- case 'B':
- /* const member function. */
- constp = TRUE;
- ++*pp;
- break;
- case 'C':
- /* volatile member function. */
- volatilep = TRUE;
- ++*pp;
- break;
- case 'D':
- /* const volatile member function. */
- constp = TRUE;
- volatilep = TRUE;
- ++*pp;
- break;
- case '*':
- case '?':
- case '.':
- /* File compiled with g++ version 1; no information. */
- break;
- default:
- warn_stab (orig, _("const/volatile indicator missing"));
- break;
- }
- staticp = FALSE;
- switch (**pp)
- {
- case '*':
- /* virtual member function, followed by index. The sign
- bit is supposedly set to distinguish
- pointers-to-methods from virtual function indicies. */
- ++*pp;
- voffset = parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- goto fail;
- }
- ++*pp;
- voffset &= 0x7fffffff;
- if (**pp == ';' || *pp == '\0')
- {
- /* Must be g++ version 1. */
- context = DEBUG_TYPE_NULL;
- }
- else
- {
- /* Figure out from whence this virtual function
- came. It may belong to virtual function table of
- one of its baseclasses. */
- look_ahead_type = parse_stab_type (dhandle, info,
- (const char *) NULL,
- pp,
- (debug_type **) NULL);
- if (**pp == ':')
- {
- /* g++ version 1 overloaded methods. */
- context = DEBUG_TYPE_NULL;
- }
- else
- {
- context = look_ahead_type;
- look_ahead_type = DEBUG_TYPE_NULL;
- if (**pp != ';')
- {
- bad_stab (orig);
- goto fail;
- }
- ++*pp;
- }
- }
- break;
- case '?':
- /* static member function. */
- ++*pp;
- staticp = TRUE;
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- if (strncmp (argtypes, name, strlen (name)) != 0)
- stub = TRUE;
- break;
- default:
- warn_stab (orig, "member function type missing");
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- break;
- case '.':
- ++*pp;
- voffset = 0;
- context = DEBUG_TYPE_NULL;
- break;
- }
- /* If the type is not a stub, then the argtypes string is
- the physical name of the function. Otherwise the
- argtypes string is the mangled form of the argument
- types, and the full type and the physical name must be
- extracted from them. */
- physname = argtypes;
- if (stub)
- {
- debug_type class_type, return_type;
- class_type = stab_find_type (dhandle, info, typenums);
- if (class_type == DEBUG_TYPE_NULL)
- goto fail;
- return_type = debug_get_return_type (dhandle, type);
- if (return_type == DEBUG_TYPE_NULL)
- {
- bad_stab (orig);
- goto fail;
- }
- type = parse_stab_argtypes (dhandle, info, class_type, name,
- tagname, return_type, argtypes,
- constp, volatilep, &physname);
- if (type == DEBUG_TYPE_NULL)
- goto fail;
- }
- if (cvars + 1 >= allocvars)
- {
- allocvars += 10;
- variants = ((debug_method_variant *)
- xrealloc (variants,
- allocvars * sizeof *variants));
- }
- if (! staticp)
- variants[cvars] = debug_make_method_variant (dhandle, physname,
- type, visibility,
- constp, volatilep,
- voffset, context);
- else
- variants[cvars] = debug_make_static_method_variant (dhandle,
- physname,
- type,
- visibility,
- constp,
- volatilep);
- if (variants[cvars] == DEBUG_METHOD_VARIANT_NULL)
- goto fail;
- ++cvars;
- }
- while (**pp != ';' && **pp != '\0');
- variants[cvars] = DEBUG_METHOD_VARIANT_NULL;
- if (**pp != '\0')
- ++*pp;
- if (c + 1 >= alloc)
- {
- alloc += 10;
- methods = ((debug_method *)
- xrealloc (methods, alloc * sizeof *methods));
- }
- methods[c] = debug_make_method (dhandle, name, variants);
- ++c;
- }
- if (methods != NULL)
- methods[c] = DEBUG_METHOD_NULL;
- *retp = methods;
- return TRUE;
- fail:
- if (name != NULL)
- free (name);
- if (variants != NULL)
- free (variants);
- if (argtypes != NULL)
- free (argtypes);
- return FALSE;
- }
- /* Parse a string representing argument types for a method. Stabs
- tries to save space by packing argument types into a mangled
- string. This string should give us enough information to extract
- both argument types and the physical name of the function, given
- the tag name. */
- static debug_type
- parse_stab_argtypes (void *dhandle, struct stab_handle *info,
- debug_type class_type, const char *fieldname,
- const char *tagname, debug_type return_type,
- const char *argtypes, bfd_boolean constp,
- bfd_boolean volatilep, const char **pphysname)
- {
- bfd_boolean is_full_physname_constructor;
- bfd_boolean is_constructor;
- bfd_boolean is_destructor;
- bfd_boolean is_v3;
- debug_type *args;
- bfd_boolean varargs;
- unsigned int physname_len = 0;
- /* Constructors are sometimes handled specially. */
- is_full_physname_constructor = ((argtypes[0] == '_'
- && argtypes[1] == '_'
- && (ISDIGIT (argtypes[2])
- || argtypes[2] == 'Q'
- || argtypes[2] == 't'))
- || CONST_STRNEQ (argtypes, "__ct"));
- is_constructor = (is_full_physname_constructor
- || (tagname != NULL
- && strcmp (fieldname, tagname) == 0));
- is_destructor = ((argtypes[0] == '_'
- && (argtypes[1] == '$' || argtypes[1] == '.')
- && argtypes[2] == '_')
- || CONST_STRNEQ (argtypes, "__dt"));
- is_v3 = argtypes[0] == '_' && argtypes[1] == 'Z';
- if (!(is_destructor || is_full_physname_constructor || is_v3))
- {
- unsigned int len;
- const char *const_prefix;
- const char *volatile_prefix;
- char buf[20];
- unsigned int mangled_name_len;
- char *physname;
- len = tagname == NULL ? 0 : strlen (tagname);
- const_prefix = constp ? "C" : "";
- volatile_prefix = volatilep ? "V" : "";
- if (len == 0)
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
- else if (tagname != NULL && strchr (tagname, '<') != NULL)
- {
- /* Template methods are fully mangled. */
- sprintf (buf, "__%s%s", const_prefix, volatile_prefix);
- tagname = NULL;
- len = 0;
- }
- else
- sprintf (buf, "__%s%s%d", const_prefix, volatile_prefix, len);
- mangled_name_len = ((is_constructor ? 0 : strlen (fieldname))
- + strlen (buf)
- + len
- + strlen (argtypes)
- + 1);
- if (fieldname[0] == 'o'
- && fieldname[1] == 'p'
- && (fieldname[2] == '$' || fieldname[2] == '.'))
- {
- const char *opname;
- opname = cplus_mangle_opname (fieldname + 3, 0);
- if (opname == NULL)
- {
- fprintf (stderr, _("No mangling for \"%s\"\n"), fieldname);
- return DEBUG_TYPE_NULL;
- }
- mangled_name_len += strlen (opname);
- physname = (char *) xmalloc (mangled_name_len);
- strncpy (physname, fieldname, 3);
- strcpy (physname + 3, opname);
- }
- else
- {
- physname = (char *) xmalloc (mangled_name_len);
- if (is_constructor)
- physname[0] = '\0';
- else
- strcpy (physname, fieldname);
- }
- physname_len = strlen (physname);
- strcat (physname, buf);
- if (tagname != NULL)
- strcat (physname, tagname);
- strcat (physname, argtypes);
- *pphysname = physname;
- }
- if (*argtypes == '\0' || is_destructor)
- {
- args = (debug_type *) xmalloc (sizeof *args);
- *args = NULL;
- return debug_make_method_type (dhandle, return_type, class_type, args,
- FALSE);
- }
- args = stab_demangle_argtypes (dhandle, info, *pphysname, &varargs, physname_len);
- if (args == NULL)
- return DEBUG_TYPE_NULL;
- return debug_make_method_type (dhandle, return_type, class_type, args,
- varargs);
- }
- /* The tail end of stabs for C++ classes that contain a virtual function
- pointer contains a tilde, a %, and a type number.
- The type number refers to the base class (possibly this class itself) which
- contains the vtable pointer for the current class.
- This function is called when we have parsed all the method declarations,
- so we can look for the vptr base class info. */
- static bfd_boolean
- parse_stab_tilde_field (void *dhandle, struct stab_handle *info,
- const char **pp, const int *typenums,
- debug_type *retvptrbase, bfd_boolean *retownvptr)
- {
- const char *orig;
- const char *hold;
- int vtypenums[2];
- *retvptrbase = DEBUG_TYPE_NULL;
- *retownvptr = FALSE;
- orig = *pp;
- /* If we are positioned at a ';', then skip it. */
- if (**pp == ';')
- ++*pp;
- if (**pp != '~')
- return TRUE;
- ++*pp;
- if (**pp == '=' || **pp == '+' || **pp == '-')
- {
- /* Obsolete flags that used to indicate the presence of
- constructors and/or destructors. */
- ++*pp;
- }
- if (**pp != '%')
- return TRUE;
- ++*pp;
- hold = *pp;
- /* The next number is the type number of the base class (possibly
- our own class) which supplies the vtable for this class. */
- if (! parse_stab_type_number (pp, vtypenums))
- return FALSE;
- if (vtypenums[0] == typenums[0]
- && vtypenums[1] == typenums[1])
- *retownvptr = TRUE;
- else
- {
- debug_type vtype;
- const char *p;
- *pp = hold;
- vtype = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- for (p = *pp; *p != ';' && *p != '\0'; p++)
- ;
- if (*p != ';')
- {
- bad_stab (orig);
- return FALSE;
- }
- *retvptrbase = vtype;
- *pp = p + 1;
- }
- return TRUE;
- }
- /* Read a definition of an array type. */
- static debug_type
- parse_stab_array_type (void *dhandle, struct stab_handle *info,
- const char **pp, bfd_boolean stringp)
- {
- const char *orig;
- const char *p;
- int typenums[2];
- debug_type index_type;
- bfd_boolean adjustable;
- bfd_signed_vma lower, upper;
- debug_type element_type;
- /* Format of an array type:
- "ar<index type>;lower;upper;<array_contents_type>".
- OS9000: "arlower,upper;<array_contents_type>".
- Fortran adjustable arrays use Adigits or Tdigits for lower or upper;
- for these, produce a type like float[][]. */
- orig = *pp;
- /* FIXME: gdb checks os9k_stabs here. */
- /* If the index type is type 0, we take it as int. */
- p = *pp;
- if (! parse_stab_type_number (&p, typenums))
- return DEBUG_TYPE_NULL;
- if (typenums[0] == 0 && typenums[1] == 0 && **pp != '=')
- {
- index_type = debug_find_named_type (dhandle, "int");
- if (index_type == DEBUG_TYPE_NULL)
- {
- index_type = debug_make_int_type (dhandle, 4, FALSE);
- if (index_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- }
- *pp = p;
- }
- else
- {
- index_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- }
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- adjustable = FALSE;
- if (! ISDIGIT (**pp) && **pp != '-')
- {
- ++*pp;
- adjustable = TRUE;
- }
- lower = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- if (! ISDIGIT (**pp) && **pp != '-')
- {
- ++*pp;
- adjustable = TRUE;
- }
- upper = (bfd_signed_vma) parse_number (pp, (bfd_boolean *) NULL);
- if (**pp != ';')
- {
- bad_stab (orig);
- return DEBUG_TYPE_NULL;
- }
- ++*pp;
- element_type = parse_stab_type (dhandle, info, (const char *) NULL, pp,
- (debug_type **) NULL);
- if (element_type == DEBUG_TYPE_NULL)
- return DEBUG_TYPE_NULL;
- if (adjustable)
- {
- lower = 0;
- upper = -1;
- }
- return debug_make_array_type (dhandle, element_type, index_type, lower,
- upper, stringp);
- }
- /* This struct holds information about files we have seen using
- N_BINCL. */
- struct bincl_file
- {
- /* The next N_BINCL file. */
- struct bincl_file *next;
- /* The next N_BINCL on the stack. */
- struct bincl_file *next_stack;
- /* The file name. */
- const char *name;
- /* The hash value. */
- bfd_vma hash;
- /* The file index. */
- unsigned int file;
- /* The list of types defined in this file. */
- struct stab_types *file_types;
- };
- /* Start a new N_BINCL file, pushing it onto the stack. */
- static void
- push_bincl (struct stab_handle *info, const char *name, bfd_vma hash)
- {
- struct bincl_file *n;
- n = (struct bincl_file *) xmalloc (sizeof *n);
- n->next = info->bincl_list;
- n->next_stack = info->bincl_stack;
- n->name = name;
- n->hash = hash;
- n->file = info->files;
- n->file_types = NULL;
- info->bincl_list = n;
- info->bincl_stack = n;
- ++info->files;
- info->file_types = ((struct stab_types **)
- xrealloc (info->file_types,
- (info->files
- * sizeof *info->file_types)));
- info->file_types[n->file] = NULL;
- }
- /* Finish an N_BINCL file, at an N_EINCL, popping the name off the
- stack. */
- static const char *
- pop_bincl (struct stab_handle *info)
- {
- struct bincl_file *o;
- o = info->bincl_stack;
- if (o == NULL)
- return info->main_filename;
- info->bincl_stack = o->next_stack;
- o->file_types = info->file_types[o->file];
- if (info->bincl_stack == NULL)
- return info->main_filename;
- return info->bincl_stack->name;
- }
- /* Handle an N_EXCL: get the types from the corresponding N_BINCL. */
- static bfd_boolean
- find_excl (struct stab_handle *info, const char *name, bfd_vma hash)
- {
- struct bincl_file *l;
- ++info->files;
- info->file_types = ((struct stab_types **)
- xrealloc (info->file_types,
- (info->files
- * sizeof *info->file_types)));
- for (l = info->bincl_list; l != NULL; l = l->next)
- if (l->hash == hash && strcmp (l->name, name) == 0)
- break;
- if (l == NULL)
- {
- warn_stab (name, _("Undefined N_EXCL"));
- info->file_types[info->files - 1] = NULL;
- return TRUE;
- }
- info->file_types[info->files - 1] = l->file_types;
- return TRUE;
- }
- /* Handle a variable definition. gcc emits variable definitions for a
- block before the N_LBRAC, so we must hold onto them until we see
- it. The SunPRO compiler emits variable definitions after the
- N_LBRAC, so we can call debug_record_variable immediately. */
- static bfd_boolean
- stab_record_variable (void *dhandle, struct stab_handle *info,
- const char *name, debug_type type,
- enum debug_var_kind kind, bfd_vma val)
- {
- struct stab_pending_var *v;
- if ((kind == DEBUG_GLOBAL || kind == DEBUG_STATIC)
- || ! info->within_function
- || (info->gcc_compiled == 0 && info->n_opt_found))
- return debug_record_variable (dhandle, name, type, kind, val);
- v = (struct stab_pending_var *) xmalloc (sizeof *v);
- memset (v, 0, sizeof *v);
- v->next = info->pending;
- v->name = name;
- v->type = type;
- v->kind = kind;
- v->val = val;
- info->pending = v;
- return TRUE;
- }
- /* Emit pending variable definitions. This is called after we see the
- N_LBRAC that starts the block. */
- static bfd_boolean
- stab_emit_pending_vars (void *dhandle, struct stab_handle *info)
- {
- struct stab_pending_var *v;
- v = info->pending;
- while (v != NULL)
- {
- struct stab_pending_var *next;
- if (! debug_record_variable (dhandle, v->name, v->type, v->kind, v->val))
- return FALSE;
- next = v->next;
- free (v);
- v = next;
- }
- info->pending = NULL;
- return TRUE;
- }
- /* Find the slot for a type in the database. */
- static debug_type *
- stab_find_slot (struct stab_handle *info, const int *typenums)
- {
- int filenum;
- int tindex;
- struct stab_types **ps;
- filenum = typenums[0];
- tindex = typenums[1];
- if (filenum < 0 || (unsigned int) filenum >= info->files)
- {
- fprintf (stderr, _("Type file number %d out of range\n"), filenum);
- return NULL;
- }
- if (tindex < 0)
- {
- fprintf (stderr, _("Type index number %d out of range\n"), tindex);
- return NULL;
- }
- ps = info->file_types + filenum;
- while (tindex >= STAB_TYPES_SLOTS)
- {
- if (*ps == NULL)
- {
- *ps = (struct stab_types *) xmalloc (sizeof **ps);
- memset (*ps, 0, sizeof **ps);
- }
- ps = &(*ps)->next;
- tindex -= STAB_TYPES_SLOTS;
- }
- if (*ps == NULL)
- {
- *ps = (struct stab_types *) xmalloc (sizeof **ps);
- memset (*ps, 0, sizeof **ps);
- }
- return (*ps)->types + tindex;
- }
- /* Find a type given a type number. If the type has not been
- allocated yet, create an indirect type. */
- static debug_type
- stab_find_type (void *dhandle, struct stab_handle *info, const int *typenums)
- {
- debug_type *slot;
- if (typenums[0] == 0 && typenums[1] < 0)
- {
- /* A negative type number indicates an XCOFF builtin type. */
- return stab_xcoff_builtin_type (dhandle, info, typenums[1]);
- }
- slot = stab_find_slot (info, typenums);
- if (slot == NULL)
- return DEBUG_TYPE_NULL;
- if (*slot == DEBUG_TYPE_NULL)
- return debug_make_indirect_type (dhandle, slot, (const char *) NULL);
- return *slot;
- }
- /* Record that a given type number refers to a given type. */
- static bfd_boolean
- stab_record_type (void *dhandle ATTRIBUTE_UNUSED, struct stab_handle *info,
- const int *typenums, debug_type type)
- {
- debug_type *slot;
- slot = stab_find_slot (info, typenums);
- if (slot == NULL)
- return FALSE;
- /* gdb appears to ignore type redefinitions, so we do as well. */
- *slot = type;
- return TRUE;
- }
- /* Return an XCOFF builtin type. */
- static debug_type
- stab_xcoff_builtin_type (void *dhandle, struct stab_handle *info,
- int typenum)
- {
- debug_type rettype;
- const char *name;
- if (typenum >= 0 || typenum < -XCOFF_TYPE_COUNT)
- {
- fprintf (stderr, _("Unrecognized XCOFF type %d\n"), typenum);
- return DEBUG_TYPE_NULL;
- }
- if (info->xcoff_types[-typenum] != NULL)
- return info->xcoff_types[-typenum];
- switch (-typenum)
- {
- case 1:
- /* The size of this and all the other types are fixed, defined
- by the debugging format. */
- name = "int";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 2:
- name = "char";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 3:
- name = "short";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 4:
- name = "long";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 5:
- name = "unsigned char";
- rettype = debug_make_int_type (dhandle, 1, TRUE);
- break;
- case 6:
- name = "signed char";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 7:
- name = "unsigned short";
- rettype = debug_make_int_type (dhandle, 2, TRUE);
- break;
- case 8:
- name = "unsigned int";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- break;
- case 9:
- name = "unsigned";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- case 10:
- name = "unsigned long";
- rettype = debug_make_int_type (dhandle, 4, TRUE);
- break;
- case 11:
- name = "void";
- rettype = debug_make_void_type (dhandle);
- break;
- case 12:
- /* IEEE single precision (32 bit). */
- name = "float";
- rettype = debug_make_float_type (dhandle, 4);
- break;
- case 13:
- /* IEEE double precision (64 bit). */
- name = "double";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 14:
- /* This is an IEEE double on the RS/6000, and different machines
- with different sizes for "long double" should use different
- negative type numbers. See stabs.texinfo. */
- name = "long double";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 15:
- name = "integer";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 16:
- name = "boolean";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 17:
- name = "short real";
- rettype = debug_make_float_type (dhandle, 4);
- break;
- case 18:
- name = "real";
- rettype = debug_make_float_type (dhandle, 8);
- break;
- case 19:
- /* FIXME */
- name = "stringptr";
- rettype = NULL;
- break;
- case 20:
- /* FIXME */
- name = "character";
- rettype = debug_make_int_type (dhandle, 1, TRUE);
- break;
- case 21:
- name = "logical*1";
- rettype = debug_make_bool_type (dhandle, 1);
- break;
- case 22:
- name = "logical*2";
- rettype = debug_make_bool_type (dhandle, 2);
- break;
- case 23:
- name = "logical*4";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 24:
- name = "logical";
- rettype = debug_make_bool_type (dhandle, 4);
- break;
- case 25:
- /* Complex type consisting of two IEEE single precision values. */
- name = "complex";
- rettype = debug_make_complex_type (dhandle, 8);
- break;
- case 26:
- /* Complex type consisting of two IEEE double precision values. */
- name = "double complex";
- rettype = debug_make_complex_type (dhandle, 16);
- break;
- case 27:
- name = "integer*1";
- rettype = debug_make_int_type (dhandle, 1, FALSE);
- break;
- case 28:
- name = "integer*2";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 29:
- name = "integer*4";
- rettype = debug_make_int_type (dhandle, 4, FALSE);
- break;
- case 30:
- /* FIXME */
- name = "wchar";
- rettype = debug_make_int_type (dhandle, 2, FALSE);
- break;
- case 31:
- name = "long long";
- rettype = debug_make_int_type (dhandle, 8, FALSE);
- break;
- case 32:
- name = "unsigned long long";
- rettype = debug_make_int_type (dhandle, 8, TRUE);
- break;
- case 33:
- name = "logical*8";
- rettype = debug_make_bool_type (dhandle, 8);
- break;
- case 34:
- name = "integer*8";
- rettype = debug_make_int_type (dhandle, 8, FALSE);
- break;
- default:
- abort ();
- }
- rettype = debug_name_type (dhandle, name, rettype);
- info->xcoff_types[-typenum] = rettype;
- return rettype;
- }
- /* Find or create a tagged type. */
- static debug_type
- stab_find_tagged_type (void *dhandle, struct stab_handle *info,
- const char *p, int len, enum debug_type_kind kind)
- {
- char *name;
- debug_type dtype;
- struct stab_tag *st;
- name = savestring (p, len);
- /* We pass DEBUG_KIND_ILLEGAL because we want all tags in the same
- namespace. This is right for C, and I don't know how to handle
- other languages. FIXME. */
- dtype = debug_find_tagged_type (dhandle, name, DEBUG_KIND_ILLEGAL);
- if (dtype != DEBUG_TYPE_NULL)
- {
- free (name);
- return dtype;
- }
- /* We need to allocate an entry on the undefined tag list. */
- for (st = info->tags; st != NULL; st = st->next)
- {
- if (st->name[0] == name[0]
- && strcmp (st->name, name) == 0)
- {
- if (st->kind == DEBUG_KIND_ILLEGAL)
- st->kind = kind;
- free (name);
- break;
- }
- }
- if (st == NULL)
- {
- st = (struct stab_tag *) xmalloc (sizeof *st);
- memset (st, 0, sizeof *st);
- st->next = info->tags;
- st->name = name;
- st->kind = kind;
- st->slot = DEBUG_TYPE_NULL;
- st->type = debug_make_indirect_type (dhandle, &st->slot, name);
- info->tags = st;
- }
- return st->type;
- }
- /* In order to get the correct argument types for a stubbed method, we
- need to extract the argument types from a C++ mangled string.
- Since the argument types can refer back to the return type, this
- means that we must demangle the entire physical name. In gdb this
- is done by calling cplus_demangle and running the results back
- through the C++ expression parser. Since we have no expression
- parser, we must duplicate much of the work of cplus_demangle here.
- We assume that GNU style demangling is used, since this is only
- done for method stubs, and only g++ should output that form of
- debugging information. */
- /* This structure is used to hold a pointer to type information which
- demangling a string. */
- struct stab_demangle_typestring
- {
- /* The start of the type. This is not null terminated. */
- const char *typestring;
- /* The length of the type. */
- unsigned int len;
- };
- /* This structure is used to hold information while demangling a
- string. */
- struct stab_demangle_info
- {
- /* The debugging information handle. */
- void *dhandle;
- /* The stab information handle. */
- struct stab_handle *info;
- /* The array of arguments we are building. */
- debug_type *args;
- /* Whether the method takes a variable number of arguments. */
- bfd_boolean varargs;
- /* The array of types we have remembered. */
- struct stab_demangle_typestring *typestrings;
- /* The number of typestrings. */
- unsigned int typestring_count;
- /* The number of typestring slots we have allocated. */
- unsigned int typestring_alloc;
- };
- static void stab_bad_demangle (const char *);
- static unsigned int stab_demangle_count (const char **);
- static bfd_boolean stab_demangle_get_count (const char **, unsigned int *);
- static bfd_boolean stab_demangle_prefix
- (struct stab_demangle_info *, const char **, unsigned int);
- static bfd_boolean stab_demangle_function_name
- (struct stab_demangle_info *, const char **, const char *);
- static bfd_boolean stab_demangle_signature
- (struct stab_demangle_info *, const char **);
- static bfd_boolean stab_demangle_qualified
- (struct stab_demangle_info *, const char **, debug_type *);
- static bfd_boolean stab_demangle_template
- (struct stab_demangle_info *, const char **, char **);
- static bfd_boolean stab_demangle_class
- (struct stab_demangle_info *, const char **, const char **);
- static bfd_boolean stab_demangle_args
- (struct stab_demangle_info *, const char **, debug_type **, bfd_boolean *);
- static bfd_boolean stab_demangle_arg
- (struct stab_demangle_info *, const char **, debug_type **,
- unsigned int *, unsigned int *);
- static bfd_boolean stab_demangle_type
- (struct stab_demangle_info *, const char **, debug_type *);
- static bfd_boolean stab_demangle_fund_type
- (struct stab_demangle_info *, const char **, debug_type *);
- static bfd_boolean stab_demangle_remember_type
- (struct stab_demangle_info *, const char *, int);
- /* Warn about a bad demangling. */
- static void
- stab_bad_demangle (const char *s)
- {
- fprintf (stderr, _("bad mangled name `%s'\n"), s);
- }
- /* Get a count from a stab string. */
- static unsigned int
- stab_demangle_count (const char **pp)
- {
- unsigned int count;
- count = 0;
- while (ISDIGIT (**pp))
- {
- count *= 10;
- count += **pp - '0';
- ++*pp;
- }
- return count;
- }
- /* Require a count in a string. The count may be multiple digits, in
- which case it must end in an underscore. */
- static bfd_boolean
- stab_demangle_get_count (const char **pp, unsigned int *pi)
- {
- if (! ISDIGIT (**pp))
- return FALSE;
- *pi = **pp - '0';
- ++*pp;
- if (ISDIGIT (**pp))
- {
- unsigned int count;
- const char *p;
- count = *pi;
- p = *pp;
- do
- {
- count *= 10;
- count += *p - '0';
- ++p;
- }
- while (ISDIGIT (*p));
- if (*p == '_')
- {
- *pp = p + 1;
- *pi = count;
- }
- }
- return TRUE;
- }
- /* This function demangles a physical name, returning a NULL
- terminated array of argument types. */
- static debug_type *
- stab_demangle_argtypes (void *dhandle, struct stab_handle *info,
- const char *physname, bfd_boolean *pvarargs,
- unsigned int physname_len)
- {
- struct stab_demangle_info minfo;
- /* Check for the g++ V3 ABI. */
- if (physname[0] == '_' && physname[1] == 'Z')
- return stab_demangle_v3_argtypes (dhandle, info, physname, pvarargs);
- minfo.dhandle = dhandle;
- minfo.info = info;
- minfo.args = NULL;
- minfo.varargs = FALSE;
- minfo.typestring_alloc = 10;
- minfo.typestrings = ((struct stab_demangle_typestring *)
- xmalloc (minfo.typestring_alloc
- * sizeof *minfo.typestrings));
- minfo.typestring_count = 0;
- /* cplus_demangle checks for special GNU mangled forms, but we can't
- see any of them in mangled method argument types. */
- if (! stab_demangle_prefix (&minfo, &physname, physname_len))
- goto error_return;
- if (*physname != '\0')
- {
- if (! stab_demangle_signature (&minfo, &physname))
- goto error_return;
- }
- free (minfo.typestrings);
- minfo.typestrings = NULL;
- if (minfo.args == NULL)
- fprintf (stderr, _("no argument types in mangled string\n"));
- *pvarargs = minfo.varargs;
- return minfo.args;
- error_return:
- if (minfo.typestrings != NULL)
- free (minfo.typestrings);
- return NULL;
- }
- /* Demangle the prefix of the mangled name. */
- static bfd_boolean
- stab_demangle_prefix (struct stab_demangle_info *minfo, const char **pp,
- unsigned int physname_len)
- {
- const char *scan;
- unsigned int i;
- /* cplus_demangle checks for global constructors and destructors,
- but we can't see them in mangled argument types. */
- if (physname_len)
- scan = *pp + physname_len;
- else
- {
- /* Look for `__'. */
- scan = *pp;
- do
- scan = strchr (scan, '_');
- while (scan != NULL && *++scan != '_');
- if (scan == NULL)
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
- --scan;
- /* We found `__'; move ahead to the last contiguous `__' pair. */
- i = strspn (scan, "_");
- if (i > 2)
- scan += i - 2;
- }
- if (scan == *pp
- && (ISDIGIT (scan[2])
- || scan[2] == 'Q'
- || scan[2] == 't'))
- {
- /* This is a GNU style constructor name. */
- *pp = scan + 2;
- return TRUE;
- }
- else if (scan == *pp
- && ! ISDIGIT (scan[2])
- && scan[2] != 't')
- {
- /* Look for the `__' that separates the prefix from the
- signature. */
- while (*scan == '_')
- ++scan;
- scan = strstr (scan, "__");
- if (scan == NULL || scan[2] == '\0')
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
- return stab_demangle_function_name (minfo, pp, scan);
- }
- else if (scan[2] != '\0')
- {
- /* The name doesn't start with `__', but it does contain `__'. */
- return stab_demangle_function_name (minfo, pp, scan);
- }
- else
- {
- stab_bad_demangle (*pp);
- return FALSE;
- }
- /*NOTREACHED*/
- }
- /* Demangle a function name prefix. The scan argument points to the
- double underscore which separates the function name from the
- signature. */
- static bfd_boolean
- stab_demangle_function_name (struct stab_demangle_info *minfo,
- const char **pp, const char *scan)
- {
- const char *name;
- /* The string from *pp to scan is the name of the function. We
- don't care about the name, since we just looking for argument
- types. However, for conversion operators, the name may include a
- type which we must remember in order to handle backreferences. */
- name = *pp;
- *pp = scan + 2;
- if (*pp - name >= 5
- && CONST_STRNEQ (name, "type")
- && (name[4] == '$' || name[4] == '.'))
- {
- const char *tem;
- /* This is a type conversion operator. */
- tem = name + 5;
- if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return FALSE;
- }
- else if (name[0] == '_'
- && name[1] == '_'
- && name[2] == 'o'
- && name[3] == 'p')
- {
- const char *tem;
- /* This is a type conversion operator. */
- tem = name + 4;
- if (! stab_demangle_type (minfo, &tem, (debug_type *) NULL))
- return FALSE;
- }
- return TRUE;
- }
- /* Demangle the signature. This is where the argument types are
- found. */
- static bfd_boolean
- stab_demangle_signature (struct stab_demangle_info *minfo, const char **pp)
- {
- const char *orig;
- bfd_boolean expect_func, func_done;
- const char *hold;
- orig = *pp;
- expect_func = FALSE;
- func_done = FALSE;
- hold = NULL;
- while (**pp != '\0')
- {
- switch (**pp)
- {
- case 'Q':
- hold = *pp;
- if (! stab_demangle_qualified (minfo, pp, (debug_type *) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- expect_func = TRUE;
- hold = NULL;
- break;
- case 'S':
- /* Static member function. FIXME: Can this happen? */
- if (hold == NULL)
- hold = *pp;
- ++*pp;
- break;
- case 'C':
- /* Const member function. */
- if (hold == NULL)
- hold = *pp;
- ++*pp;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if (hold == NULL)
- hold = *pp;
- if (! stab_demangle_class (minfo, pp, (const char **) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- expect_func = TRUE;
- hold = NULL;
- break;
- case 'F':
- /* Function. I don't know if this actually happens with g++
- output. */
- hold = NULL;
- func_done = TRUE;
- ++*pp;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- break;
- case 't':
- /* Template. */
- if (hold == NULL)
- hold = *pp;
- if (! stab_demangle_template (minfo, pp, (char **) NULL)
- || ! stab_demangle_remember_type (minfo, hold, *pp - hold))
- return FALSE;
- hold = NULL;
- expect_func = TRUE;
- break;
- case '_':
- /* At the outermost level, we cannot have a return type
- specified, so if we run into another '_' at this point we
- are dealing with a mangled name that is either bogus, or
- has been mangled by some algorithm we don't know how to
- deal with. So just reject the entire demangling. */
- stab_bad_demangle (orig);
- return FALSE;
- default:
- /* Assume we have stumbled onto the first outermost function
- argument token, and start processing args. */
- func_done = TRUE;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- break;
- }
- if (expect_func)
- {
- func_done = TRUE;
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- }
- }
- if (! func_done)
- {
- /* With GNU style demangling, bar__3foo is 'foo::bar(void)', and
- bar__3fooi is 'foo::bar(int)'. We get here when we find the
- first case, and need to ensure that the '(void)' gets added
- to the current declp. */
- if (! stab_demangle_args (minfo, pp, &minfo->args, &minfo->varargs))
- return FALSE;
- }
- return TRUE;
- }
- /* Demangle a qualified name, such as "Q25Outer5Inner" which is the
- mangled form of "Outer::Inner". */
- static bfd_boolean
- stab_demangle_qualified (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
- {
- const char *orig;
- const char *p;
- unsigned int qualifiers;
- debug_type context;
- orig = *pp;
- switch ((*pp)[1])
- {
- case '_':
- /* GNU mangled name with more than 9 classes. The count is
- preceded by an underscore (to distinguish it from the <= 9
- case) and followed by an underscore. */
- p = *pp + 2;
- if (! ISDIGIT (*p) || *p == '0')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- qualifiers = atoi (p);
- while (ISDIGIT (*p))
- ++p;
- if (*p != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp = p + 1;
- break;
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- qualifiers = (*pp)[1] - '0';
- /* Skip an optional underscore after the count. */
- if ((*pp)[2] == '_')
- ++*pp;
- *pp += 2;
- break;
- case '0':
- default:
- stab_bad_demangle (orig);
- return FALSE;
- }
- context = DEBUG_TYPE_NULL;
- /* Pick off the names. */
- while (qualifiers-- > 0)
- {
- if (**pp == '_')
- ++*pp;
- if (**pp == 't')
- {
- char *name;
- if (! stab_demangle_template (minfo, pp,
- ptype != NULL ? &name : NULL))
- return FALSE;
- if (ptype != NULL)
- {
- context = stab_find_tagged_type (minfo->dhandle, minfo->info,
- name, strlen (name),
- DEBUG_KIND_CLASS);
- free (name);
- if (context == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- else
- {
- unsigned int len;
- len = stab_demangle_count (pp);
- if (strlen (*pp) < len)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (ptype != NULL)
- {
- const debug_field *fields;
- fields = NULL;
- if (context != DEBUG_TYPE_NULL)
- fields = debug_get_fields (minfo->dhandle, context);
- context = DEBUG_TYPE_NULL;
- if (fields != NULL)
- {
- char *name;
- /* Try to find the type by looking through the
- fields of context until we find a field with the
- same type. This ought to work for a class
- defined within a class, but it won't work for,
- e.g., an enum defined within a class. stabs does
- not give us enough information to figure out the
- latter case. */
- name = savestring (*pp, len);
- for (; *fields != DEBUG_FIELD_NULL; fields++)
- {
- debug_type ft;
- const char *dn;
- ft = debug_get_field_type (minfo->dhandle, *fields);
- if (ft == NULL)
- {
- free (name);
- return FALSE;
- }
- dn = debug_get_type_name (minfo->dhandle, ft);
- if (dn != NULL && strcmp (dn, name) == 0)
- {
- context = ft;
- break;
- }
- }
- free (name);
- }
- if (context == DEBUG_TYPE_NULL)
- {
- /* We have to fall back on finding the type by name.
- If there are more types to come, then this must
- be a class. Otherwise, it could be anything. */
- if (qualifiers == 0)
- {
- char *name;
- name = savestring (*pp, len);
- context = debug_find_named_type (minfo->dhandle,
- name);
- free (name);
- }
- if (context == DEBUG_TYPE_NULL)
- {
- context = stab_find_tagged_type (minfo->dhandle,
- minfo->info,
- *pp, len,
- (qualifiers == 0
- ? DEBUG_KIND_ILLEGAL
- : DEBUG_KIND_CLASS));
- if (context == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- }
- *pp += len;
- }
- }
- if (ptype != NULL)
- *ptype = context;
- return TRUE;
- }
- /* Demangle a template. If PNAME is not NULL, this sets *PNAME to a
- string representation of the template. */
- static bfd_boolean
- stab_demangle_template (struct stab_demangle_info *minfo, const char **pp,
- char **pname)
- {
- const char *orig;
- unsigned int r, i;
- orig = *pp;
- ++*pp;
- /* Skip the template name. */
- r = stab_demangle_count (pp);
- if (r == 0 || strlen (*pp) < r)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp += r;
- /* Get the size of the parameter list. */
- if (stab_demangle_get_count (pp, &r) == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- for (i = 0; i < r; i++)
- {
- if (**pp == 'Z')
- {
- /* This is a type parameter. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return FALSE;
- }
- else
- {
- const char *old_p;
- bfd_boolean pointerp, realp, integralp, charp, boolp;
- bfd_boolean done;
- old_p = *pp;
- pointerp = FALSE;
- realp = FALSE;
- integralp = FALSE;
- charp = FALSE;
- boolp = FALSE;
- done = FALSE;
- /* This is a value parameter. */
- if (! stab_demangle_type (minfo, pp, (debug_type *) NULL))
- return FALSE;
- while (*old_p != '\0' && ! done)
- {
- switch (*old_p)
- {
- case 'P':
- case 'p':
- case 'R':
- pointerp = TRUE;
- done = TRUE;
- break;
- case 'C': /* Const. */
- case 'S': /* Signed. */
- case 'U': /* Unsigned. */
- case 'V': /* Volatile. */
- case 'F': /* Function. */
- case 'M': /* Member function. */
- case 'O': /* ??? */
- ++old_p;
- break;
- case 'Q': /* Qualified name. */
- integralp = TRUE;
- done = TRUE;
- break;
- case 'T': /* Remembered type. */
- abort ();
- case 'v': /* Void. */
- abort ();
- case 'x': /* Long long. */
- case 'l': /* Long. */
- case 'i': /* Int. */
- case 's': /* Short. */
- case 'w': /* Wchar_t. */
- integralp = TRUE;
- done = TRUE;
- break;
- case 'b': /* Bool. */
- boolp = TRUE;
- done = TRUE;
- break;
- case 'c': /* Char. */
- charp = TRUE;
- done = TRUE;
- break;
- case 'r': /* Long double. */
- case 'd': /* Double. */
- case 'f': /* Float. */
- realp = TRUE;
- done = TRUE;
- break;
- default:
- /* Assume it's a user defined integral type. */
- integralp = TRUE;
- done = TRUE;
- break;
- }
- }
- if (integralp)
- {
- if (**pp == 'm')
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- else if (charp)
- {
- unsigned int val;
- if (**pp == 'm')
- ++*pp;
- val = stab_demangle_count (pp);
- if (val == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
- else if (boolp)
- {
- unsigned int val;
- val = stab_demangle_count (pp);
- if (val != 0 && val != 1)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
- else if (realp)
- {
- if (**pp == 'm')
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- if (**pp == '.')
- {
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- if (**pp == 'e')
- {
- ++*pp;
- while (ISDIGIT (**pp))
- ++*pp;
- }
- }
- else if (pointerp)
- {
- unsigned int len;
- len = stab_demangle_count (pp);
- if (len == 0)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- *pp += len;
- }
- }
- }
- /* We can translate this to a string fairly easily by invoking the
- regular demangling routine. */
- if (pname != NULL)
- {
- char *s1, *s2, *s3, *s4 = NULL;
- char *from, *to;
- s1 = savestring (orig, *pp - orig);
- s2 = concat ("NoSuchStrinG__", s1, (const char *) NULL);
- free (s1);
- s3 = cplus_demangle (s2, DMGL_ANSI);
- free (s2);
- if (s3 != NULL)
- s4 = strstr (s3, "::NoSuchStrinG");
- if (s3 == NULL || s4 == NULL)
- {
- stab_bad_demangle (orig);
- if (s3 != NULL)
- free (s3);
- return FALSE;
- }
- /* Eliminating all spaces, except those between > characters,
- makes it more likely that the demangled name will match the
- name which g++ used as the structure name. */
- for (from = to = s3; from != s4; ++from)
- if (*from != ' '
- || (from[1] == '>' && from > s3 && from[-1] == '>'))
- *to++ = *from;
- *pname = savestring (s3, to - s3);
- free (s3);
- }
- return TRUE;
- }
- /* Demangle a class name. */
- static bfd_boolean
- stab_demangle_class (struct stab_demangle_info *minfo ATTRIBUTE_UNUSED,
- const char **pp, const char **pstart)
- {
- const char *orig;
- unsigned int n;
- orig = *pp;
- n = stab_demangle_count (pp);
- if (strlen (*pp) < n)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (pstart != NULL)
- *pstart = *pp;
- *pp += n;
- return TRUE;
- }
- /* Demangle function arguments. If the pargs argument is not NULL, it
- is set to a NULL terminated array holding the arguments. */
- static bfd_boolean
- stab_demangle_args (struct stab_demangle_info *minfo, const char **pp,
- debug_type **pargs, bfd_boolean *pvarargs)
- {
- const char *orig;
- unsigned int alloc, count;
- orig = *pp;
- alloc = 10;
- if (pargs != NULL)
- {
- *pargs = (debug_type *) xmalloc (alloc * sizeof **pargs);
- *pvarargs = FALSE;
- }
- count = 0;
- while (**pp != '_' && **pp != '\0' && **pp != 'e')
- {
- if (**pp == 'N' || **pp == 'T')
- {
- char temptype;
- unsigned int r, t;
- temptype = **pp;
- ++*pp;
- if (temptype == 'T')
- r = 1;
- else
- {
- if (! stab_demangle_get_count (pp, &r))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- }
- if (! stab_demangle_get_count (pp, &t))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (t >= minfo->typestring_count)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- while (r-- > 0)
- {
- const char *tem;
- tem = minfo->typestrings[t].typestring;
- if (! stab_demangle_arg (minfo, &tem, pargs, &count, &alloc))
- return FALSE;
- }
- }
- else
- {
- if (! stab_demangle_arg (minfo, pp, pargs, &count, &alloc))
- return FALSE;
- }
- }
- if (pargs != NULL)
- (*pargs)[count] = DEBUG_TYPE_NULL;
- if (**pp == 'e')
- {
- if (pargs != NULL)
- *pvarargs = TRUE;
- ++*pp;
- }
- return TRUE;
- }
- /* Demangle a single argument. */
- static bfd_boolean
- stab_demangle_arg (struct stab_demangle_info *minfo, const char **pp,
- debug_type **pargs, unsigned int *pcount,
- unsigned int *palloc)
- {
- const char *start;
- debug_type type;
- start = *pp;
- if (! stab_demangle_type (minfo, pp,
- pargs == NULL ? (debug_type *) NULL : &type)
- || ! stab_demangle_remember_type (minfo, start, *pp - start))
- return FALSE;
- if (pargs != NULL)
- {
- if (type == DEBUG_TYPE_NULL)
- return FALSE;
- if (*pcount + 1 >= *palloc)
- {
- *palloc += 10;
- *pargs = ((debug_type *)
- xrealloc (*pargs, *palloc * sizeof **pargs));
- }
- (*pargs)[*pcount] = type;
- ++*pcount;
- }
- return TRUE;
- }
- /* Demangle a type. If the ptype argument is not NULL, *ptype is set
- to the newly allocated type. */
- static bfd_boolean
- stab_demangle_type (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
- {
- const char *orig;
- orig = *pp;
- switch (**pp)
- {
- case 'P':
- case 'p':
- /* A pointer type. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_pointer_type (minfo->dhandle, *ptype);
- break;
- case 'R':
- /* A reference type. */
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_reference_type (minfo->dhandle, *ptype);
- break;
- case 'A':
- /* An array. */
- {
- unsigned long high;
- ++*pp;
- high = 0;
- while (**pp != '\0' && **pp != '_')
- {
- if (! ISDIGIT (**pp))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- high *= 10;
- high += **pp - '0';
- ++*pp;
- }
- if (**pp != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- {
- debug_type int_type;
- int_type = debug_find_named_type (minfo->dhandle, "int");
- if (int_type == NULL)
- int_type = debug_make_int_type (minfo->dhandle, 4, FALSE);
- *ptype = debug_make_array_type (minfo->dhandle, *ptype, int_type,
- 0, high, FALSE);
- }
- }
- break;
- case 'T':
- /* A back reference to a remembered type. */
- {
- unsigned int i;
- const char *p;
- ++*pp;
- if (! stab_demangle_get_count (pp, &i))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (i >= minfo->typestring_count)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- p = minfo->typestrings[i].typestring;
- if (! stab_demangle_type (minfo, &p, ptype))
- return FALSE;
- }
- break;
- case 'F':
- /* A function. */
- {
- debug_type *args;
- bfd_boolean varargs;
- ++*pp;
- if (! stab_demangle_args (minfo, pp,
- (ptype == NULL
- ? (debug_type **) NULL
- : &args),
- (ptype == NULL
- ? (bfd_boolean *) NULL
- : &varargs)))
- return FALSE;
- if (**pp != '_')
- {
- /* cplus_demangle will accept a function without a return
- type, but I don't know when that will happen, or what
- to do if it does. */
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_function_type (minfo->dhandle, *ptype, args,
- varargs);
- }
- break;
- case 'M':
- case 'O':
- {
- bfd_boolean memberp;
- debug_type class_type = DEBUG_TYPE_NULL;
- debug_type *args;
- bfd_boolean varargs;
- unsigned int n;
- const char *name;
- memberp = **pp == 'M';
- args = NULL;
- varargs = FALSE;
- ++*pp;
- if (ISDIGIT (**pp))
- {
- n = stab_demangle_count (pp);
- if (strlen (*pp) < n)
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- name = *pp;
- *pp += n;
- if (ptype != NULL)
- {
- class_type = stab_find_tagged_type (minfo->dhandle,
- minfo->info,
- name, (int) n,
- DEBUG_KIND_CLASS);
- if (class_type == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- else if (**pp == 'Q')
- {
- if (! stab_demangle_qualified (minfo, pp,
- (ptype == NULL
- ? (debug_type *) NULL
- : &class_type)))
- return FALSE;
- }
- else
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (memberp)
- {
- if (**pp == 'C')
- {
- ++*pp;
- }
- else if (**pp == 'V')
- {
- ++*pp;
- }
- if (**pp != 'F')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
- if (! stab_demangle_args (minfo, pp,
- (ptype == NULL
- ? (debug_type **) NULL
- : &args),
- (ptype == NULL
- ? (bfd_boolean *) NULL
- : &varargs)))
- return FALSE;
- }
- if (**pp != '_')
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- {
- if (! memberp)
- *ptype = debug_make_offset_type (minfo->dhandle, class_type,
- *ptype);
- else
- {
- /* FIXME: We have no way to record constp or
- volatilep. */
- *ptype = debug_make_method_type (minfo->dhandle, *ptype,
- class_type, args, varargs);
- }
- }
- }
- break;
- case 'G':
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- break;
- case 'C':
- ++*pp;
- if (! stab_demangle_type (minfo, pp, ptype))
- return FALSE;
- if (ptype != NULL)
- *ptype = debug_make_const_type (minfo->dhandle, *ptype);
- break;
- case 'Q':
- {
- if (! stab_demangle_qualified (minfo, pp, ptype))
- return FALSE;
- }
- break;
- default:
- if (! stab_demangle_fund_type (minfo, pp, ptype))
- return FALSE;
- break;
- }
- return TRUE;
- }
- /* Demangle a fundamental type. If the ptype argument is not NULL,
- *ptype is set to the newly allocated type. */
- static bfd_boolean
- stab_demangle_fund_type (struct stab_demangle_info *minfo, const char **pp,
- debug_type *ptype)
- {
- const char *orig;
- bfd_boolean constp, volatilep, unsignedp, signedp;
- bfd_boolean done;
- orig = *pp;
- constp = FALSE;
- volatilep = FALSE;
- unsignedp = FALSE;
- signedp = FALSE;
- done = FALSE;
- while (! done)
- {
- switch (**pp)
- {
- case 'C':
- constp = TRUE;
- ++*pp;
- break;
- case 'U':
- unsignedp = TRUE;
- ++*pp;
- break;
- case 'S':
- signedp = TRUE;
- ++*pp;
- break;
- case 'V':
- volatilep = TRUE;
- ++*pp;
- break;
- default:
- done = TRUE;
- break;
- }
- }
- switch (**pp)
- {
- case '\0':
- case '_':
- /* cplus_demangle permits this, but I don't know what it means. */
- stab_bad_demangle (orig);
- break;
- case 'v': /* void */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "void");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_void_type (minfo->dhandle);
- }
- ++*pp;
- break;
- case 'x': /* long long */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "long long unsigned int"
- : "long long int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 8, unsignedp);
- }
- ++*pp;
- break;
- case 'l': /* long */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "long unsigned int"
- : "long int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
- }
- ++*pp;
- break;
- case 'i': /* int */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "unsigned int"
- : "int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 4, unsignedp);
- }
- ++*pp;
- break;
- case 's': /* short */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "short unsigned int"
- : "short int"));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 2, unsignedp);
- }
- ++*pp;
- break;
- case 'b': /* bool */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "bool");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_bool_type (minfo->dhandle, 4);
- }
- ++*pp;
- break;
- case 'c': /* char */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle,
- (unsignedp
- ? "unsigned char"
- : (signedp
- ? "signed char"
- : "char")));
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 1, unsignedp);
- }
- ++*pp;
- break;
- case 'w': /* wchar_t */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "__wchar_t");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_int_type (minfo->dhandle, 2, TRUE);
- }
- ++*pp;
- break;
- case 'r': /* long double */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "long double");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 8);
- }
- ++*pp;
- break;
- case 'd': /* double */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "double");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 8);
- }
- ++*pp;
- break;
- case 'f': /* float */
- if (ptype != NULL)
- {
- *ptype = debug_find_named_type (minfo->dhandle, "float");
- if (*ptype == DEBUG_TYPE_NULL)
- *ptype = debug_make_float_type (minfo->dhandle, 4);
- }
- ++*pp;
- break;
- case 'G':
- ++*pp;
- if (! ISDIGIT (**pp))
- {
- stab_bad_demangle (orig);
- return FALSE;
- }
- /* Fall through. */
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- const char *hold;
- if (! stab_demangle_class (minfo, pp, &hold))
- return FALSE;
- if (ptype != NULL)
- {
- char *name;
- name = savestring (hold, *pp - hold);
- *ptype = debug_find_named_type (minfo->dhandle, name);
- free (name);
- if (*ptype == DEBUG_TYPE_NULL)
- {
- /* FIXME: It is probably incorrect to assume that
- undefined types are tagged types. */
- *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
- hold, *pp - hold,
- DEBUG_KIND_ILLEGAL);
- if (*ptype == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- }
- break;
- case 't':
- {
- char *name;
- if (! stab_demangle_template (minfo, pp,
- ptype != NULL ? &name : NULL))
- return FALSE;
- if (ptype != NULL)
- {
- *ptype = stab_find_tagged_type (minfo->dhandle, minfo->info,
- name, strlen (name),
- DEBUG_KIND_CLASS);
- free (name);
- if (*ptype == DEBUG_TYPE_NULL)
- return FALSE;
- }
- }
- break;
- default:
- stab_bad_demangle (orig);
- return FALSE;
- }
- if (ptype != NULL)
- {
- if (constp)
- *ptype = debug_make_const_type (minfo->dhandle, *ptype);
- if (volatilep)
- *ptype = debug_make_volatile_type (minfo->dhandle, *ptype);
- }
- return TRUE;
- }
- /* Remember a type string in a demangled string. */
- static bfd_boolean
- stab_demangle_remember_type (struct stab_demangle_info *minfo,
- const char *p, int len)
- {
- if (minfo->typestring_count >= minfo->typestring_alloc)
- {
- minfo->typestring_alloc += 10;
- minfo->typestrings = ((struct stab_demangle_typestring *)
- xrealloc (minfo->typestrings,
- (minfo->typestring_alloc
- * sizeof *minfo->typestrings)));
- }
- minfo->typestrings[minfo->typestring_count].typestring = p;
- minfo->typestrings[minfo->typestring_count].len = (unsigned int) len;
- ++minfo->typestring_count;
- return TRUE;
- }
- /* Demangle names encoded using the g++ V3 ABI. The newer versions of
- g++ which use this ABI do not encode ordinary method argument types
- in a mangled name; they simply output the argument types. However,
- for a static method, g++ simply outputs the return type and the
- physical name. So in that case we need to demangle the name here.
- Here PHYSNAME is the physical name of the function, and we set the
- variable pointed at by PVARARGS to indicate whether this function
- is varargs. This returns NULL, or a NULL terminated array of
- argument types. */
- static debug_type *
- stab_demangle_v3_argtypes (void *dhandle, struct stab_handle *info,
- const char *physname, bfd_boolean *pvarargs)
- {
- struct demangle_component *dc;
- void *mem;
- debug_type *pargs;
- dc = cplus_demangle_v3_components (physname, DMGL_PARAMS | DMGL_ANSI, &mem);
- if (dc == NULL)
- {
- stab_bad_demangle (physname);
- return NULL;
- }
- /* We expect to see TYPED_NAME, and the right subtree describes the
- function type. */
- if (dc->type != DEMANGLE_COMPONENT_TYPED_NAME
- || dc->u.s_binary.right->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
- {
- fprintf (stderr, _("Demangled name is not a function\n"));
- free (mem);
- return NULL;
- }
- pargs = stab_demangle_v3_arglist (dhandle, info,
- dc->u.s_binary.right->u.s_binary.right,
- pvarargs);
- free (mem);
- return pargs;
- }
- /* Demangle an argument list in a struct demangle_component tree.
- Returns a DEBUG_TYPE_NULL terminated array of argument types, and
- sets *PVARARGS to indicate whether this is a varargs function. */
- static debug_type *
- stab_demangle_v3_arglist (void *dhandle, struct stab_handle *info,
- struct demangle_component *arglist,
- bfd_boolean *pvarargs)
- {
- struct demangle_component *dc;
- unsigned int alloc, count;
- debug_type *pargs;
- alloc = 10;
- pargs = (debug_type *) xmalloc (alloc * sizeof *pargs);
- *pvarargs = FALSE;
- count = 0;
- for (dc = arglist;
- dc != NULL;
- dc = dc->u.s_binary.right)
- {
- debug_type arg;
- bfd_boolean varargs;
- if (dc->type != DEMANGLE_COMPONENT_ARGLIST)
- {
- fprintf (stderr, _("Unexpected type in v3 arglist demangling\n"));
- free (pargs);
- return NULL;
- }
- /* PR 13925: Cope if the demangler returns an empty
- context for a function with no arguments. */
- if (dc->u.s_binary.left == NULL)
- break;
- arg = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
- NULL, &varargs);
- if (arg == NULL)
- {
- if (varargs)
- {
- *pvarargs = TRUE;
- continue;
- }
- free (pargs);
- return NULL;
- }
- if (count + 1 >= alloc)
- {
- alloc += 10;
- pargs = (debug_type *) xrealloc (pargs, alloc * sizeof *pargs);
- }
- pargs[count] = arg;
- ++count;
- }
- pargs[count] = DEBUG_TYPE_NULL;
- return pargs;
- }
- /* Convert a struct demangle_component tree describing an argument
- type into a debug_type. */
- static debug_type
- stab_demangle_v3_arg (void *dhandle, struct stab_handle *info,
- struct demangle_component *dc, debug_type context,
- bfd_boolean *pvarargs)
- {
- debug_type dt;
- if (pvarargs != NULL)
- *pvarargs = FALSE;
- switch (dc->type)
- {
- /* FIXME: These are demangle component types which we probably
- need to handle one way or another. */
- case DEMANGLE_COMPONENT_LOCAL_NAME:
- case DEMANGLE_COMPONENT_TYPED_NAME:
- case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
- case DEMANGLE_COMPONENT_CTOR:
- case DEMANGLE_COMPONENT_DTOR:
- case DEMANGLE_COMPONENT_JAVA_CLASS:
- case DEMANGLE_COMPONENT_RESTRICT_THIS:
- case DEMANGLE_COMPONENT_VOLATILE_THIS:
- case DEMANGLE_COMPONENT_CONST_THIS:
- case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
- case DEMANGLE_COMPONENT_COMPLEX:
- case DEMANGLE_COMPONENT_IMAGINARY:
- case DEMANGLE_COMPONENT_VENDOR_TYPE:
- case DEMANGLE_COMPONENT_ARRAY_TYPE:
- case DEMANGLE_COMPONENT_PTRMEM_TYPE:
- case DEMANGLE_COMPONENT_ARGLIST:
- default:
- fprintf (stderr, _("Unrecognized demangle component %d\n"),
- (int) dc->type);
- return NULL;
- case DEMANGLE_COMPONENT_NAME:
- if (context != NULL)
- {
- const debug_field *fields;
- fields = debug_get_fields (dhandle, context);
- if (fields != NULL)
- {
- /* Try to find this type by looking through the context
- class. */
- for (; *fields != DEBUG_FIELD_NULL; fields++)
- {
- debug_type ft;
- const char *dn;
- ft = debug_get_field_type (dhandle, *fields);
- if (ft == NULL)
- return NULL;
- dn = debug_get_type_name (dhandle, ft);
- if (dn != NULL
- && (int) strlen (dn) == dc->u.s_name.len
- && strncmp (dn, dc->u.s_name.s, dc->u.s_name.len) == 0)
- return ft;
- }
- }
- }
- return stab_find_tagged_type (dhandle, info, dc->u.s_name.s,
- dc->u.s_name.len, DEBUG_KIND_ILLEGAL);
- case DEMANGLE_COMPONENT_QUAL_NAME:
- context = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left,
- context, NULL);
- if (context == NULL)
- return NULL;
- return stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.right,
- context, NULL);
- case DEMANGLE_COMPONENT_TEMPLATE:
- {
- char *p;
- size_t alc;
- /* We print this component to get a class name which we can
- use. FIXME: This probably won't work if the template uses
- template parameters which refer to an outer template. */
- p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
- if (p == NULL)
- {
- fprintf (stderr, _("Failed to print demangled template\n"));
- return NULL;
- }
- dt = stab_find_tagged_type (dhandle, info, p, strlen (p),
- DEBUG_KIND_CLASS);
- free (p);
- return dt;
- }
- case DEMANGLE_COMPONENT_SUB_STD:
- return stab_find_tagged_type (dhandle, info, dc->u.s_string.string,
- dc->u.s_string.len, DEBUG_KIND_ILLEGAL);
- case DEMANGLE_COMPONENT_RESTRICT:
- case DEMANGLE_COMPONENT_VOLATILE:
- case DEMANGLE_COMPONENT_CONST:
- case DEMANGLE_COMPONENT_POINTER:
- case DEMANGLE_COMPONENT_REFERENCE:
- dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
- NULL);
- if (dt == NULL)
- return NULL;
- switch (dc->type)
- {
- default:
- abort ();
- case DEMANGLE_COMPONENT_RESTRICT:
- /* FIXME: We have no way to represent restrict. */
- return dt;
- case DEMANGLE_COMPONENT_VOLATILE:
- return debug_make_volatile_type (dhandle, dt);
- case DEMANGLE_COMPONENT_CONST:
- return debug_make_const_type (dhandle, dt);
- case DEMANGLE_COMPONENT_POINTER:
- return debug_make_pointer_type (dhandle, dt);
- case DEMANGLE_COMPONENT_REFERENCE:
- return debug_make_reference_type (dhandle, dt);
- }
- case DEMANGLE_COMPONENT_FUNCTION_TYPE:
- {
- debug_type *pargs;
- bfd_boolean varargs;
- if (dc->u.s_binary.left == NULL)
- {
- /* In this case the return type is actually unknown.
- However, I'm not sure this will ever arise in practice;
- normally an unknown return type would only appear at
- the top level, which is handled above. */
- dt = debug_make_void_type (dhandle);
- }
- else
- dt = stab_demangle_v3_arg (dhandle, info, dc->u.s_binary.left, NULL,
- NULL);
- if (dt == NULL)
- return NULL;
- pargs = stab_demangle_v3_arglist (dhandle, info,
- dc->u.s_binary.right,
- &varargs);
- if (pargs == NULL)
- return NULL;
- return debug_make_function_type (dhandle, dt, pargs, varargs);
- }
- case DEMANGLE_COMPONENT_BUILTIN_TYPE:
- {
- char *p;
- size_t alc;
- debug_type ret;
- /* We print this component in order to find out the type name.
- FIXME: Should we instead expose the
- demangle_builtin_type_info structure? */
- p = cplus_demangle_print (DMGL_PARAMS | DMGL_ANSI, dc, 20, &alc);
- if (p == NULL)
- {
- fprintf (stderr, _("Couldn't get demangled builtin type\n"));
- return NULL;
- }
- /* The mangling is based on the type, but does not itself
- indicate what the sizes are. So we have to guess. */
- if (strcmp (p, "signed char") == 0)
- ret = debug_make_int_type (dhandle, 1, FALSE);
- else if (strcmp (p, "bool") == 0)
- ret = debug_make_bool_type (dhandle, 1);
- else if (strcmp (p, "char") == 0)
- ret = debug_make_int_type (dhandle, 1, FALSE);
- else if (strcmp (p, "double") == 0)
- ret = debug_make_float_type (dhandle, 8);
- else if (strcmp (p, "long double") == 0)
- ret = debug_make_float_type (dhandle, 8);
- else if (strcmp (p, "float") == 0)
- ret = debug_make_float_type (dhandle, 4);
- else if (strcmp (p, "__float128") == 0)
- ret = debug_make_float_type (dhandle, 16);
- else if (strcmp (p, "unsigned char") == 0)
- ret = debug_make_int_type (dhandle, 1, TRUE);
- else if (strcmp (p, "int") == 0)
- ret = debug_make_int_type (dhandle, 4, FALSE);
- else if (strcmp (p, "unsigned int") == 0)
- ret = debug_make_int_type (dhandle, 4, TRUE);
- else if (strcmp (p, "long") == 0)
- ret = debug_make_int_type (dhandle, 4, FALSE);
- else if (strcmp (p, "unsigned long") == 0)
- ret = debug_make_int_type (dhandle, 4, TRUE);
- else if (strcmp (p, "__int128") == 0)
- ret = debug_make_int_type (dhandle, 16, FALSE);
- else if (strcmp (p, "unsigned __int128") == 0)
- ret = debug_make_int_type (dhandle, 16, TRUE);
- else if (strcmp (p, "short") == 0)
- ret = debug_make_int_type (dhandle, 2, FALSE);
- else if (strcmp (p, "unsigned short") == 0)
- ret = debug_make_int_type (dhandle, 2, TRUE);
- else if (strcmp (p, "void") == 0)
- ret = debug_make_void_type (dhandle);
- else if (strcmp (p, "wchar_t") == 0)
- ret = debug_make_int_type (dhandle, 4, TRUE);
- else if (strcmp (p, "long long") == 0)
- ret = debug_make_int_type (dhandle, 8, FALSE);
- else if (strcmp (p, "unsigned long long") == 0)
- ret = debug_make_int_type (dhandle, 8, TRUE);
- else if (strcmp (p, "...") == 0)
- {
- if (pvarargs == NULL)
- fprintf (stderr, _("Unexpected demangled varargs\n"));
- else
- *pvarargs = TRUE;
- ret = NULL;
- }
- else
- {
- fprintf (stderr, _("Unrecognized demangled builtin type\n"));
- ret = NULL;
- }
- free (p);
- return ret;
- }
- }
- }
|