12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067 |
- /* symbols.c - core analysis suite
- *
- * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
- * Copyright (C) 2002-2014 David Anderson
- * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved.
- *
- * 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 2 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.
- */
- #include "defs.h"
- #include <elf.h>
- #ifdef GDB_7_6
- #define __CONFIG_H__ 1
- #include "config.h"
- #endif
- #include "bfd.h"
- static void store_symbols(bfd *, int, void *, long, unsigned int);
- static void store_sysmap_symbols(void);
- static ulong relocate(ulong, char *, int);
- static int relocate_force(ulong, char *);
- static void kaslr_init(void);
- static ulong symbol_value_from_proc_kallsyms(char *);
- static void strip_module_symbol_end(char *s);
- static int compare_syms(const void *, const void *);
- static int compare_mods(const void *, const void *);
- static int compare_prios(const void *v1, const void *v2);
- static asection *get_kernel_section(char *);
- static char * get_section(ulong vaddr, char *buf);
- static void symbol_dump(ulong, char *);
- static void check_for_dups(struct load_module *);
- static int symbol_name_count(char *);
- static struct syment *kallsyms_module_symbol(struct load_module *, symbol_info *);
- static void store_load_module_symbols \
- (bfd *, int, void *, long, uint, ulong, char *);
- static int load_module_index(struct syment *);
- static void section_header_info(bfd *, asection *, void *);
- static void store_section_data(struct load_module *, bfd *, asection *);
- static void calculate_load_order_v1(struct load_module *, bfd *);
- static void calculate_load_order_v2(struct load_module *, bfd *, int,
- void *, long, unsigned int);
- static void check_insmod_builtin(struct load_module *, int, ulong *);
- static int is_insmod_builtin(struct load_module *, struct syment *);
- struct load_module;
- static int add_symbol_file(struct load_module *);
- static int add_symbol_file_kallsyms(struct load_module *, struct gnu_request *);
- static void find_mod_etext(struct load_module *);
- static long rodata_search(ulong *, ulong);
- static int ascii_long(ulong word);
- static int is_bfd_format(char *);
- static int is_binary_stripped(char *);
- static int namespace_ctl(int, struct symbol_namespace *, void *, void *);
- static void symval_hash_init(void);
- static struct syment *symval_hash_search(ulong);
- static void symname_hash_init(void);
- static void symname_hash_install(struct syment *);
- static struct syment *symname_hash_search(char *);
- static void gnu_qsort(bfd *, void *, long, unsigned int, asymbol *, asymbol *);
- static int check_gnu_debuglink(bfd *);
- static int separate_debug_file_exists(const char *, unsigned long, int *);
- static int store_module_kallsyms_v1(struct load_module *, int, int, char *);
- static int store_module_kallsyms_v2(struct load_module *, int, int, char *);
- static void datatype_error(void **, char *, char *, char *, int);
- static char *get_thisfile(void);
- struct elf_common;
- static void Elf32_Sym_to_common(Elf32_Sym *, struct elf_common *);
- static void Elf64_Sym_to_common(Elf64_Sym *, struct elf_common *);
- static void cmd_datatype_common(ulong);
- static void do_datatype_addr(struct datatype_member *, ulong, int,
- ulong, char **, int);
- static void process_gdb_output(char *, unsigned, const char *, int);
- static int display_per_cpu_info(struct syment *, int, char *);
- static struct load_module *get_module_percpu_sym_owner(struct syment *);
- static int is_percpu_symbol(struct syment *);
- static void dump_percpu_symbols(struct load_module *);
- static void print_struct_with_dereference(ulong, struct datatype_member *, ulong);
- static int dereference_pointer(ulong, struct datatype_member *, ulong);
- #define KERNEL_SECTIONS (void *)(1)
- #define MODULE_SECTIONS (void *)(2)
- #define VERIFY_SECTIONS (void *)(3)
- #define EV_DWARFEXTRACT 101010101
- #define PARSE_FOR_DATA (1)
- #define PARSE_FOR_DECLARATION (2)
- static void parse_for_member(struct datatype_member *, ulong);
- static int show_member_offset(FILE *, struct datatype_member *, char *);
- /*
- * structure/union printing stuff
- */
- #define UINT8 (0x1)
- #define INT8 (0x2)
- #define UINT16 (0x4)
- #define INT16 (0x8)
- #define UINT32 (0x10)
- #define INT32 (0x20)
- #define UINT64 (0x40)
- #define INT64 (0x80)
- #define POINTER (0x100)
- #define FUNCTION (0x200)
- #define UNION_REQUEST (0x400)
- #define STRUCT_REQUEST (0x800)
- #define ARRAY (0x1000)
- #define ENUM (0x2000)
- #define TYPEDEF (0x4000)
- #define STRUCT_VERBOSE (0x8000)
- #define SHOW_OFFSET (0x10000)
- #define IN_UNION (0x20000)
- #define IN_STRUCT (0x40000)
- #define DATATYPE_QUERY (0x80000)
- #define ANON_MEMBER_QUERY (0x100000)
- #define SHOW_RAW_DATA (0x200000)
- #define DEREF_POINTERS (0x400000)
- #define INTEGER_TYPE (UINT8|INT8|UINT16|INT16|UINT32|INT32|UINT64|INT64)
- #define INITIAL_INDENT (4)
- #define INDENT_INCR (2)
- static void whatis_datatype(char *, ulong, FILE *);
- static void whatis_variable(struct syment *);
- static void print_struct(char *, ulong);
- static void print_union(char *, ulong);
- static void dump_datatype_member(FILE *, struct datatype_member *);
- static void dump_datatype_flags(ulong, FILE *);
- static long anon_member_offset(char *, char *);
- static int gdb_whatis(char *);
- static void do_datatype_declaration(struct datatype_member *, ulong);
- static int member_to_datatype(char *, struct datatype_member *, ulong);
- #define DEBUGINFO_ERROR_MESSAGE1 \
- "the use of a System.map file requires that the accompanying namelist\nargument is a kernel file built with the -g CFLAG. The namelist argument\nsupplied in this case is a debuginfo file, which must be accompanied by the\nkernel file from which it was derived.\n"
- #define DEBUGINFO_ERROR_MESSAGE2 \
- "The namelist argument supplied in this case is a debuginfo file,\nwhich must be accompanied by the kernel file from which it was derived.\n"
- /*
- * This routine scours the namelist for kernel text and data symbols,
- * sorts, and stores, them in a static table for quick reference.
- */
- void
- symtab_init(void)
- {
- char **matching;
- long symcount;
- void *minisyms;
- unsigned int size;
- asymbol *sort_x;
- asymbol *sort_y;
- if ((st->bfd = bfd_openr(pc->namelist, NULL)) == NULL)
- error(FATAL, "cannot open object file: %s\n", pc->namelist);
- if (!bfd_check_format_matches(st->bfd, bfd_object, &matching))
- error(FATAL, "cannot determine object file format: %s\n",
- pc->namelist);
- /*
- * Check whether the namelist is a kerntypes file built by
- * dwarfextract, which places a magic number in e_version.
- */
- if (file_elf_version(pc->namelist) == EV_DWARFEXTRACT)
- pc->flags |= KERNTYPES;
- if (pc->flags & SYSMAP) {
- bfd_map_over_sections(st->bfd, section_header_info,
- VERIFY_SECTIONS);
- if ((st->flags & (NO_SEC_LOAD|NO_SEC_CONTENTS)) ==
- (NO_SEC_LOAD|NO_SEC_CONTENTS)) {
- error(INFO, "%s: no text and data contents\n",
- pc->namelist);
- error(FATAL, pc->flags & SYSMAP_ARG ?
- DEBUGINFO_ERROR_MESSAGE1 :
- DEBUGINFO_ERROR_MESSAGE2);
- }
- store_sysmap_symbols();
- return;
- } else if (LKCD_KERNTYPES())
- error(FATAL, "%s: use of kerntypes requires a system map\n",
- pc->namelist);
- /*
- * Pull a bait-and-switch on st->bfd if we've got a separate
- * .gnu_debuglink file that matches the CRC. Not done for kerntypes.
- */
- if (!(LKCD_KERNTYPES()) &&
- !(bfd_get_file_flags(st->bfd) & HAS_SYMS)) {
- if (!check_gnu_debuglink(st->bfd))
- no_debugging_data(FATAL);
- }
-
- /*
- * Gather references to the kernel sections.
- */
- if ((st->sections = (struct sec *)
- malloc(st->bfd->section_count * sizeof(struct sec *))) == NULL)
- error(FATAL, "symbol table section array malloc: %s\n",
- strerror(errno));
- BZERO(st->sections, st->bfd->section_count * sizeof(struct sec *));
- st->first_section_start = st->last_section_end = 0;
- bfd_map_over_sections(st->bfd, section_header_info, KERNEL_SECTIONS);
- if ((st->flags & (NO_SEC_LOAD|NO_SEC_CONTENTS)) ==
- (NO_SEC_LOAD|NO_SEC_CONTENTS)) {
- if (!pc->namelist_debug && !pc->debuginfo_file) {
- error(INFO, "%s: no text and data contents\n",
- pc->namelist);
- error(FATAL, DEBUGINFO_ERROR_MESSAGE2);
- }
- }
- symcount = bfd_read_minisymbols(st->bfd, FALSE, &minisyms, &size);
- if (symcount <= 0)
- no_debugging_data(FATAL);
- sort_x = bfd_make_empty_symbol(st->bfd);
- sort_y = bfd_make_empty_symbol(st->bfd);
- if (sort_x == NULL || sort_y == NULL)
- error(FATAL, "bfd_make_empty_symbol() failed\n");
- kaslr_init();
- gnu_qsort(st->bfd, minisyms, symcount, size, sort_x, sort_y);
- store_symbols(st->bfd, FALSE, minisyms, symcount, size);
- free(minisyms);
- symname_hash_init();
- symval_hash_init();
- }
- /*
- * Adapted from gdb's get_debug_link_info()
- *
- * Look in: current directory
- * basename-of-namelist/.debug directory
- * /usr/lib/debug/boot (since we know it's a Red Hat kernel)
- */
- static int
- check_gnu_debuglink(bfd *bfd)
- {
- int i, exists, found;
- asection *sect;
- bfd_size_type debuglink_size;
- char *contents;
- int crc_offset;
- unsigned long crc32;
- char *dirname;
- char *namelist_debug;
- char **matching;
- sect = bfd_get_section_by_name(bfd, ".gnu_debuglink");
- if (!sect) {
- error(INFO, "%s: no .gnu_debuglink section\n", pc->namelist);
- return FALSE;
- }
- debuglink_size = bfd_section_size(bfd, sect);
- contents = GETBUF(debuglink_size);
- bfd_get_section_contents(bfd, sect, contents,
- (file_ptr)0, (bfd_size_type)debuglink_size);
- crc_offset = strlen (contents) + 1;
- crc_offset = (crc_offset + 3) & ~3;
- crc32 = bfd_get_32(bfd, (bfd_byte *)(contents + crc_offset));
- if (CRASHDEBUG(1))
- error(NOTE, "gnu_debuglink file: %s\ncrc32: %lx\n",
- contents, crc32);
- if ((pc->debuginfo_file = (char *)
- malloc(((strlen(pc->namelist) + strlen("/.debug/") +
- + strlen(".debug") + strlen(" /usr/lib/debug/boot/ "))*10)
- + strlen(pc->namelist_debug ? pc->namelist_debug : " "))) == NULL)
- error(FATAL, "debuginfo file name malloc: %s\n",
- strerror(errno));
- dirname = GETBUF(strlen(pc->namelist)+1);
- strcpy(dirname, pc->namelist);
- for (i = strlen(dirname)-1; i >= 0; i--)
- {
- if (dirname[i] == '/')
- break;
- }
- dirname[i+1] = NULLCHAR;
- if (!strlen(dirname))
- sprintf(dirname, ".");
- namelist_debug = NULL;
- if (pc->namelist_debug) {
- sprintf(pc->debuginfo_file, "%s", pc->namelist_debug);
- if (separate_debug_file_exists(pc->debuginfo_file,
- crc32, &exists)) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: CRC matches\n",
- pc->debuginfo_file);
- st->flags |= CRC_MATCHES;
- goto reset_bfd;
- } else {
- if ((st->flags & FORCE_DEBUGINFO) && exists) {
- error(WARNING,
- "%s:\n CRC value does not match\n\n",
- pc->debuginfo_file);
- goto reset_bfd;
- } else
- error(INFO, "%s:\n CRC value does not match\n\n",
- pc->debuginfo_file);
- namelist_debug = pc->namelist_debug;
- pc->namelist_debug = NULL;
- }
- }
-
- found = 0;
- sprintf(pc->debuginfo_file, "%s/%s", dirname, contents);
- if (separate_debug_file_exists(pc->debuginfo_file, crc32, &exists)) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: CRC matches\n", pc->debuginfo_file);
- st->flags |= CRC_MATCHES;
- goto reset_bfd;
- } else {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: %s\n", pc->debuginfo_file, exists ?
- "CRC does not match" : "not readable/found");
- if (exists) {
- error(INFO, "%s: CRC does not match\n\n",
- pc->debuginfo_file);
- found++;
- }
- }
- sprintf(pc->debuginfo_file, "%s/.debug/%s", dirname, contents);
- if (separate_debug_file_exists(pc->debuginfo_file, crc32, &exists)) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: CRC matches\n", pc->debuginfo_file);
- st->flags |= CRC_MATCHES;
- goto reset_bfd;
- } else {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: %s\n", pc->debuginfo_file, exists ?
- "CRC does not match" : "not readable/found");
- if (exists) {
- error(INFO, "%s: CRC does not match\n\n",
- pc->debuginfo_file);
- found++;
- }
- }
- sprintf(pc->debuginfo_file, "/usr/lib/debug/boot/%s", contents);
- if (separate_debug_file_exists(pc->debuginfo_file, crc32, &exists)) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: CRC matches\n", pc->debuginfo_file);
- st->flags |= CRC_MATCHES;
- goto reset_bfd;
- } else {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: %s\n", pc->debuginfo_file, exists ?
- "CRC does not match" : "not readable/found");
- if (exists) {
- error(INFO, "%s: CRC does not match\n\n",
- pc->debuginfo_file);
- found++;
- }
- }
- if (!found && namelist_debug) {
- error(INFO,
- "%s:\n use of -f option may suffice, or may fail miserably\n",
- namelist_debug);
- }
- if (!found && !namelist_debug) {
- no_debugging_data(INFO);
- error(INFO, "%s: debuginfo file not found\n", contents);
- error(FATAL,
- "either install the appropriate kernel debuginfo package, or\n copy %s to this machine", contents);
- }
- return FALSE;
- reset_bfd:
- if ((st->bfd = bfd_openr(pc->debuginfo_file, NULL)) == NULL)
- error(FATAL, "cannot open object file: %s\n",
- pc->debuginfo_file);
- if (!bfd_check_format_matches(st->bfd, bfd_object, &matching))
- error(FATAL, "cannot determine object file format: %s\n",
- pc->debuginfo_file);
- FREEBUF(contents);
- FREEBUF(dirname);
- return TRUE;
- }
- /*
- * Based upon gdb's separate_debug_file_exists().
- */
- static int
- separate_debug_file_exists(const char *name, unsigned long crc, int *exists)
- {
- unsigned long file_crc = 0;
- int fd;
- char buffer[8*1024];
- size_t count;
- fd = open(name, O_RDONLY);
- if (fd < 0) {
- *exists = FALSE;
- return 0;
- }
- *exists = TRUE;
- while ((count = read(fd, buffer, sizeof(buffer))) > 0)
- #ifdef GDB_5_3
- file_crc = calc_crc32(file_crc, buffer, count);
- #else
- #ifdef GDB_7_6
- file_crc = bfd_calc_gnu_debuglink_crc32(file_crc,
- (unsigned char *)buffer, count);
- #else
- file_crc = gnu_debuglink_crc32(file_crc,
- (unsigned char *)buffer, count);
- #endif
- #endif
- close (fd);
- return crc == file_crc;
- }
- /*
- * Callback for gdb to use a specified vmlinux.debug file.
- */
- char *
- check_specified_kernel_debug_file()
- {
- if (pc->flags & GDB_INIT)
- return NULL;
- return (pc->namelist_debug ? pc->namelist_debug : NULL);
- }
- /*
- * Common bailout/warning routine when running against non-debug kernels.
- *
- * INFO: used when this routine should return.
- * FATAL: kills function if runtime, or kills program if during init.
- * WARNING: called by gdb_session_init() only, in an attempt to at least
- * get by with built-in debug data; if not possible the program
- * is killed.
- */
- void
- no_debugging_data(int error_type)
- {
- switch (error_type)
- {
- case INFO:
- error(INFO, "%s: no debugging data available\n", pc->namelist);
- break;
- case FATAL:
- error(FATAL, "%s%s: no debugging data available\n",
- pc->flags & RUNTIME ? "" : "\n", pc->namelist);
- clean_exit(1);
- case WARNING:
- error(FATAL, "\n%s: no debugging data available\n",
- pc->namelist);
- clean_exit(1);
- }
- }
- /*
- * Get the address space formerly used as init-time text. While there
- * get the boundaries of the kernel .rodata section so that it won't
- * be confused with text.
- *
- * This is done indirectly by the call-back to section_header_info().
- */
- void
- get_text_init_space(void)
- {
- asection *section = NULL;
- if (pc->flags & SYSMAP)
- return;
- if (machine_type("ARM"))
- section = get_kernel_section(".init");
- if (!section && !(section = get_kernel_section(".text.init")))
- section = get_kernel_section(".init.text");
- if (!section) {
- error(WARNING, "cannot determine text init space\n");
- return;
- }
- kt->stext_init = (ulong)bfd_get_section_vma(st->bfd, section);
- kt->etext_init = kt->stext_init +
- (ulong)bfd_section_size(st->bfd, section);
- if (kt->relocate) {
- kt->stext_init -= kt->relocate;
- kt->etext_init -= kt->relocate;
- }
- }
- /*
- * Strip gcc-generated cloned text symbol name endings.
- */
- static char *
- strip_symbol_end(const char *name, char *buf)
- {
- char *p;
- if (st->flags & NO_STRIP)
- return (char *)name;
- if ((p = strstr(name, ".isra."))) {
- if (buf) {
- strcpy(buf, name);
- buf[p-name] = NULLCHAR;
- return buf;
- } else {
- *p = NULLCHAR;
- return (char *)name;
- }
- }
- if ((p = strstr(name, ".part."))) {
- if (buf) {
- strcpy(buf, name);
- buf[p-name] = NULLCHAR;
- return buf;
- } else {
- *p = NULLCHAR;
- return (char *)name;
- }
- }
- return (char *)name;
- }
- /*
- * Gather the relevant information from the dumpfile or live system
- * and determine whether to derive the KASLR offset.
- *
- * Setting st->_stext_vmlinux to UNINITIALIZED will trigger the
- * search for "_stext" from the vmlinux file during the initial
- * symbol sort operation.
- *
- * Setting RELOC_AUTO will ensure that derive_kaslr_offset() is
- * called after the sorting operation has captured the vmlinux
- * file's "_stext" symbol value -- which it will compare to the
- * relocated "_stext" value found in either a dumpfile's vmcoreinfo
- * or in /proc/kallsyms on a live system.
- *
- * Setting KASLR_CHECK will trigger a search for "randomize_modules"
- * during the initial symbol sort operation, and if found, will
- * set (RELOC_AUTO|KASLR). On live systems, the search is done
- * here by checking /proc/kallsyms.
- */
- static void
- kaslr_init(void)
- {
- char *string;
- if (!machine_type("X86_64") || (kt->flags & RELOC_SET))
- return;
- /*
- * --kaslr=auto
- */
- if ((kt->flags2 & (RELOC_AUTO|KASLR)) == (RELOC_AUTO|KASLR))
- st->_stext_vmlinux = UNINITIALIZED;
- if (ACTIVE() && /* Linux 3.15 */
- (symbol_value_from_proc_kallsyms("randomize_modules") != BADVAL)) {
- kt->flags2 |= (RELOC_AUTO|KASLR);
- st->_stext_vmlinux = UNINITIALIZED;
- }
- if (KDUMP_DUMPFILE() || DISKDUMP_DUMPFILE()) {
- if ((string = pc->read_vmcoreinfo("SYMBOL(_stext)"))) {
- kt->vmcoreinfo._stext_SYMBOL =
- htol(string, RETURN_ON_ERROR, NULL);
- free(string);
- }
- /* Linux 3.14 */
- if ((string = pc->read_vmcoreinfo("KERNELOFFSET"))) {
- free(string);
- kt->flags2 |= KASLR_CHECK;
- st->_stext_vmlinux = UNINITIALIZED;
- }
- }
- }
- /*
- * Derives the kernel aslr offset by comparing the _stext symbol from the
- * the vmcoreinfo in the dump file to the _stext symbol in the vmlinux file.
- */
- static void
- derive_kaslr_offset(bfd *abfd, int dynamic, bfd_byte *start, bfd_byte *end,
- unsigned int size, asymbol *store)
- {
- unsigned long relocate;
- ulong _stext_relocated;
- if (ACTIVE()) {
- _stext_relocated = symbol_value_from_proc_kallsyms("_stext");
- if (_stext_relocated == BADVAL)
- return;
- } else {
- _stext_relocated = kt->vmcoreinfo._stext_SYMBOL;
- if (_stext_relocated == 0)
- return;
- }
- /*
- * To avoid mistaking an mismatched kernel version with
- * a kaslr offset, we make sure that the offset is
- * aligned by 0x1000, as it always will be for kaslr.
- */
- if (st->_stext_vmlinux && (st->_stext_vmlinux != UNINITIALIZED)) {
- relocate = st->_stext_vmlinux - _stext_relocated;
- if (relocate && !(relocate & 0xfff)) {
- kt->relocate = relocate;
- kt->flags |= RELOC_SET;
- }
- }
- if (CRASHDEBUG(1) && (kt->flags & RELOC_SET)) {
- fprintf(fp, "KASLR:\n");
- fprintf(fp, " _stext from %s: %lx\n",
- basename(pc->namelist), st->_stext_vmlinux);
- fprintf(fp, " _stext from %s: %lx\n",
- ACTIVE() ? "/proc/kallsyms" : "vmcoreinfo",
- _stext_relocated);
- fprintf(fp, " relocate: %lx (%ldMB)\n",
- kt->relocate * -1, (kt->relocate * -1) >> 20);
- }
- }
- /*
- * Store the symbols gathered by symtab_init(). The symbols are stored
- * in increasing numerical order.
- */
- static void
- store_symbols(bfd *abfd, int dynamic, void *minisyms, long symcount,
- unsigned int size)
- {
- asymbol *store;
- asymbol *sym;
- bfd_byte *from, *fromend;
- symbol_info syminfo;
- struct syment *sp;
- char buf[BUFSIZE];
- char *name;
- int first;
- if ((store = bfd_make_empty_symbol(abfd)) == NULL)
- error(FATAL, "bfd_make_empty_symbol() failed\n");
- if ((st->symtable = (struct syment *)
- calloc(symcount, sizeof(struct syment))) == NULL)
- error(FATAL, "symbol table syment space malloc: %s\n",
- strerror(errno));
- if (!namespace_ctl(NAMESPACE_INIT, &st->kernel_namespace,
- (void *)symcount, NULL))
- error(FATAL, "symbol table namespace malloc: %s\n",
- strerror(errno));
- st->syment_size = symcount * sizeof(struct syment);
- st->symcnt = 0;
- sp = st->symtable;
- first = 0;
- from = (bfd_byte *) minisyms;
- fromend = from + symcount * size;
- if (machine_type("X86")) {
- if (!(kt->flags & RELOC_SET))
- kt->flags |= RELOC_FORCE;
- } else if (machine_type("X86_64")) {
- if ((kt->flags2 & RELOC_AUTO) && !(kt->flags & RELOC_SET))
- derive_kaslr_offset(abfd, dynamic, from,
- fromend, size, store);
- } else
- kt->flags &= ~RELOC_SET;
- for (; from < fromend; from += size)
- {
- if ((sym = bfd_minisymbol_to_symbol(abfd, dynamic, from, store))
- == NULL)
- error(FATAL, "bfd_minisymbol_to_symbol() failed\n");
- bfd_get_symbol_info(abfd, sym, &syminfo);
- name = strip_symbol_end(syminfo.name, buf);
- if (machdep->verify_symbol(name, syminfo.value,
- syminfo.type)) {
- if (kt->flags & (RELOC_SET|RELOC_FORCE))
- sp->value = relocate(syminfo.value,
- (char *)syminfo.name, !(first++));
- else
- sp->value = syminfo.value;
- sp->type = syminfo.type;
- namespace_ctl(NAMESPACE_INSTALL, &st->kernel_namespace,
- sp, name);
- sp++;
- st->symcnt++;
- }
- }
- st->symend = &st->symtable[st->symcnt];
- st->flags |= KERNEL_SYMS;
- namespace_ctl(NAMESPACE_COMPLETE, &st->kernel_namespace,
- st->symtable, st->symend);
- }
- /*
- * Store the symbols from the designated System.map. The symbols are stored
- * in increasing numerical order.
- */
- static void
- store_sysmap_symbols(void)
- {
- int c, first;
- long symcount;
- char buf[BUFSIZE];
- char name[BUFSIZE];
- FILE *map;
- char *mapitems[MAXARGS];
- struct syment *sp, syment;
- if ((map = fopen(pc->system_map, "r")) == NULL)
- error(FATAL, "cannot open %s\n", pc->system_map);
- symcount = 0;
- while (fgets(buf, BUFSIZE, map))
- symcount++;
- if ((st->symtable = (struct syment *)
- calloc(symcount, sizeof(struct syment))) == NULL)
- error(FATAL, "symbol table syment space malloc: %s\n",
- strerror(errno));
- if (!namespace_ctl(NAMESPACE_INIT, &st->kernel_namespace,
- (void *)symcount, NULL))
- error(FATAL, "symbol table namespace malloc: %s\n",
- strerror(errno));
- if (!machine_type("X86") && !machine_type("X86_64"))
- kt->flags &= ~RELOC_SET;
- first = 0;
- st->syment_size = symcount * sizeof(struct syment);
- st->symcnt = 0;
- sp = st->symtable;
- rewind(map);
- while (fgets(buf, BUFSIZE, map)) {
- if ((c = parse_line(buf, mapitems)) != 3)
- continue;
- syment.value = htol(mapitems[0], FAULT_ON_ERROR, NULL);
- syment.type = mapitems[1][0];
- syment.name = mapitems[2];
- strcpy(name, syment.name);
- strip_symbol_end(name, NULL);
- if (machdep->verify_symbol(name, syment.value,
- syment.type)) {
- if (kt->flags & RELOC_SET)
- sp->value = relocate(syment.value,
- syment.name, !(first++));
- else
- sp->value = syment.value;
- sp->type = syment.type;
- namespace_ctl(NAMESPACE_INSTALL, &st->kernel_namespace,
- sp, name);
- sp++;
- st->symcnt++;
- }
- }
- fclose(map);
- st->symend = &st->symtable[st->symcnt];
- st->flags |= KERNEL_SYMS;
- namespace_ctl(NAMESPACE_COMPLETE, &st->kernel_namespace,
- st->symtable, st->symend);
- symname_hash_init();
- symval_hash_init();
- }
- /*
- * Handle x86 kernels configured such that the vmlinux symbols
- * are not as loaded into the kernel (not unity-mapped).
- */
- static ulong
- relocate(ulong symval, char *symname, int first_symbol)
- {
- if (XEN_HYPER_MODE()) {
- kt->flags &= ~(RELOC_SET|RELOC_FORCE);
- return symval;
- }
- switch (kt->flags & (RELOC_SET|RELOC_FORCE))
- {
- case RELOC_SET:
- break;
- case RELOC_FORCE:
- if (first_symbol && !relocate_force(symval, symname))
- kt->flags &= ~RELOC_FORCE;
- break;
- }
- if (machine_type("X86_64")) {
- /*
- * There are some symbols which are outside of any section
- * either because they are offsets or because they are absolute
- * addresses. These should not be relocated.
- */
- if (symval >= st->first_section_start &&
- symval <= st->last_section_end) {
- return symval - kt->relocate;
- } else {
- return symval;
- }
- } else
- return symval - kt->relocate;
- }
- /*
- * If no --reloc argument was passed, try to figure it out
- * by comparing the first vmlinux kernel symbol with the
- * first /proc/kallsyms symbol. (should be "_text")
- *
- * Live system only (at least for now).
- */
- static int
- relocate_force(ulong symval, char *symname)
- {
- int count, found;
- FILE *kp;
- char buf[BUFSIZE];
- char *kallsyms[MAXARGS];
- ulong kallsym;
- if (!ACTIVE() || !file_exists("/proc/kallsyms", NULL)) {
- if (CRASHDEBUG(1))
- fprintf(fp,
- "cannot determine relocation value: %s\n",
- !ACTIVE() ? "not a live system" :
- "/proc/kallsyms does not exist");
- return FALSE;
- }
- if ((kp = fopen("/proc/kallsyms", "r")) == NULL) {
- if (CRASHDEBUG(1))
- fprintf(fp,
- "cannot open /proc/kallsyms to determine relocation\n");
- return FALSE;
- }
- if (CRASHDEBUG(1))
- fprintf(fp,
- "relocate from: %s\n"
- " %s @ %lx\n"
- "relocate to: /proc/kallsyms\n",
- pc->namelist, symname, symval);
- found = FALSE;
- count = kallsym = 0;
- while (!found && fgets(buf, BUFSIZE, kp) &&
- (parse_line(buf, kallsyms) == 3) &&
- hexadecimal(kallsyms[0], 0)) {
- if (STREQ(kallsyms[2], symname)) {
- kallsym = htol(kallsyms[0], RETURN_ON_ERROR, NULL);
- found = TRUE;
- }
- count++;
- if (CRASHDEBUG(1))
- fprintf(fp,
- " %s @ %s %s\n",
- kallsyms[2], kallsyms[0],
- STREQ(kallsyms[2], symname) ?
- "(match!)" : "");
- }
- fclose(kp);
- /*
- * If the symbols match and have different values,
- * force the relocation.
- */
- if (found) {
- if (symval != kallsym) {
- kt->relocate = symval - kallsym;
- return TRUE;
- }
- }
- if (CRASHDEBUG(1))
- fprintf(fp,
- "cannot determine relocation value from"
- " %d symbols in /proc/kallsyms\n", count);
- return FALSE;
- }
- /*
- * Get a symbol value from /proc/kallsyms.
- */
- static ulong
- symbol_value_from_proc_kallsyms(char *symname)
- {
- FILE *kp;
- char buf[BUFSIZE];
- char *kallsyms[MAXARGS];
- ulong kallsym;
- int found;
- if (!file_exists("/proc/kallsyms", NULL)) {
- if (CRASHDEBUG(1))
- error(INFO, "cannot determine value of %s: "
- "/proc/kallsyms does not exist\n\n", symname);
- return BADVAL;
- }
- if ((kp = fopen("/proc/kallsyms", "r")) == NULL) {
- if (CRASHDEBUG(1))
- error(INFO, "cannot determine value of %s: "
- "cannot open /proc/kallsyms\n\n", symname);
- return BADVAL;
- }
- found = FALSE;
- while (!found && fgets(buf, BUFSIZE, kp) &&
- (parse_line(buf, kallsyms) == 3) &&
- hexadecimal(kallsyms[0], 0)) {
- if (STREQ(kallsyms[2], symname)) {
- kallsym = htol(kallsyms[0], RETURN_ON_ERROR, NULL);
- found = TRUE;
- break;
- }
- }
- fclose(kp);
- return(found ? kallsym : BADVAL);
- }
- /*
- * Install all static kernel symbol values into the symval_hash.
- */
- static void
- symval_hash_init(void)
- {
- int index;
- struct syment *sp, *sph;
- for (sp = st->symtable; sp < st->symend; sp++) {
- index = SYMVAL_HASH_INDEX(sp->value);
- if (st->symval_hash[index].val_hash_head == NULL) {
- st->symval_hash[index].val_hash_head = sp;
- st->symval_hash[index].val_hash_last = sp;
- continue;
- }
- sph = st->symval_hash[index].val_hash_head;
- while (sph->val_hash_next)
- sph = sph->val_hash_next;
-
- sph->val_hash_next = sp;
- }
- }
- /*
- * Static kernel symbol value search
- */
- static struct syment *
- symval_hash_search(ulong value)
- {
- int index;
- struct syment *sp, *splo;
- index = SYMVAL_HASH_INDEX(value);
- if (!st->symval_hash[index].val_hash_head)
- return NULL;
- st->val_hash_searches += 1;
- st->val_hash_iterations += 1;
- if (st->symval_hash[index].val_hash_last->value <= value)
- sp = st->symval_hash[index].val_hash_last;
- else
- sp = st->symval_hash[index].val_hash_head;
- for (splo = NULL; sp; sp = sp->val_hash_next) {
- if (sp->value == value) {
- st->symval_hash[index].val_hash_last = sp;
- return sp;
- }
- if (sp->value > value)
- break;
- st->val_hash_iterations += 1;
- splo = sp;
- }
- if (splo)
- st->symval_hash[index].val_hash_last = splo;
- return splo;
- }
- /*
- * Store all kernel static symbols into the symname_hash.
- */
- static void
- symname_hash_init(void)
- {
- struct syment *sp;
- for (sp = st->symtable; sp < st->symend; sp++)
- symname_hash_install(sp);
- if ((sp = symbol_search("__per_cpu_start")))
- st->__per_cpu_start = sp->value;
- if ((sp = symbol_search("__per_cpu_end")))
- st->__per_cpu_end = sp->value;
- }
- /*
- * Install a single static kernel symbol into the symname_hash.
- */
- static void
- symname_hash_install(struct syment *spn)
- {
- struct syment *sp;
- int index;
- index = SYMNAME_HASH_INDEX(spn->name);
- spn->cnt = 1;
- if ((sp = st->symname_hash[index]) == NULL)
- st->symname_hash[index] = spn;
- else {
- while (sp) {
- if (STREQ(sp->name, spn->name)) {
- sp->cnt++;
- spn->cnt++;
- }
- if (sp->name_hash_next)
- sp = sp->name_hash_next;
- else {
- sp->name_hash_next = spn;
- break;
- }
- }
- }
- }
- /*
- * Static kernel symbol value search
- */
- static struct syment *
- symname_hash_search(char *name)
- {
- struct syment *sp;
- sp = st->symname_hash[SYMNAME_HASH_INDEX(name)];
- while (sp) {
- if (STREQ(sp->name, name))
- return sp;
- sp = sp->name_hash_next;
- }
- return NULL;
- }
- /*
- * Output for sym -[lL] command.
- */
- #define MODULE_PSEUDO_SYMBOL(sp) \
- ((STRNEQ((sp)->name, "_MODULE_START_") || STRNEQ((sp)->name, "_MODULE_END_")) || \
- (STRNEQ((sp)->name, "_MODULE_INIT_START_") || STRNEQ((sp)->name, "_MODULE_INIT_END_")) || \
- (STRNEQ((sp)->name, "_MODULE_SECTION_")))
- #define MODULE_START(sp) (STRNEQ((sp)->name, "_MODULE_START_"))
- #define MODULE_END(sp) (STRNEQ((sp)->name, "_MODULE_END_"))
- #define MODULE_INIT_START(sp) (STRNEQ((sp)->name, "_MODULE_INIT_START_"))
- #define MODULE_INIT_END(sp) (STRNEQ((sp)->name, "_MODULE_INIT_END_"))
- #define MODULE_SECTION_START(sp) (STRNEQ((sp)->name, "_MODULE_SECTION_START"))
- #define MODULE_SECTION_END(sp) (STRNEQ((sp)->name, "_MODULE_SECTION_END"))
- static void
- symbol_dump(ulong flags, char *module)
- {
- int i, start, percpu_syms;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- char *p1, *p2;;
- #define TBD 1
- #define DISPLAYED 2
- if (flags & KERNEL_SYMS) {
- for (sp = st->symtable; sp < st->symend; sp++) {
- show_symbol(sp, 0, SHOW_RADIX());
- if (received_SIGINT() || output_closed())
- return;
- }
- }
- if (!(flags & MODULE_SYMS))
- return;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (module && !STREQ(module, lm->mod_name))
- continue;
- if (received_SIGINT() || output_closed())
- return;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- percpu_syms = 0;
- for (start = FALSE; sp <= sp_end; sp++) {
- if (IN_MODULE_PERCPU(sp->value, lm)) {
- if (percpu_syms == DISPLAYED)
- continue;
- if (!start) {
- percpu_syms = TBD;
- continue;
- }
- dump_percpu_symbols(lm);
- percpu_syms = DISPLAYED;
- }
- if (MODULE_PSEUDO_SYMBOL(sp)) {
- if (MODULE_SECTION_START(sp)) {
- p1 = sp->name +
- strlen("_MODULE_SECTION_START ");
- p2 = "section start";
- } else if (MODULE_SECTION_END(sp)) {
- p1 = sp->name +
- strlen("_MODULE_SECTION_END ");
- p2 = "section end";
- } else if (MODULE_START(sp)) {
- p1 = "MODULE START";
- p2 = sp->name+strlen("_MODULE_START_");
- start = TRUE;
- } else {
- p1 = "MODULE END";
- p2 = sp->name+strlen("_MODULE_END_");
- if (MODULE_PERCPU_SYMS_LOADED(lm) &&
- !percpu_syms) {
- dump_percpu_symbols(lm);
- percpu_syms = DISPLAYED;
- }
- }
- fprintf(fp, "%lx %s: %s\n", sp->value, p1, p2);
- if (percpu_syms == TBD) {
- dump_percpu_symbols(lm);
- percpu_syms = DISPLAYED;
- }
- } else
- show_symbol(sp, 0, SHOW_RADIX());
- }
- if (lm->mod_init_symtable) {
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp <= sp_end; sp++) {
- if (MODULE_PSEUDO_SYMBOL(sp)) {
- if (MODULE_INIT_START(sp)) {
- p1 = "MODULE INIT START";
- p2 = sp->name+strlen("_MODULE_INIT_START_");
- } else {
- p1 = "MODULE INIT END";
- p2 = sp->name+strlen("_MODULE_INIT_END_");
- }
- fprintf(fp, "%lx %s: %s\n", sp->value, p1, p2);
- } else
- show_symbol(sp, 0, SHOW_RADIX());
- }
- }
- }
- #undef TBD
- #undef DISPLAYED
- }
- static void
- dump_percpu_symbols(struct load_module *lm)
- {
- struct syment *sp, *sp_end;
- if (MODULE_PERCPU_SYMS_LOADED(lm)) {
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp <= sp_end; sp++) {
- if (IN_MODULE_PERCPU(sp->value, lm))
- show_symbol(sp, 0, SHOW_RADIX());
- }
- }
- }
- /*
- * Get a pointer to the desired asection.
- */
- static asection *
- get_kernel_section(char *name)
- {
- int i;
- asection **sec;
-
- sec = (asection **)st->sections;
- for (i = 0; i < st->bfd->section_count; i++, sec++) {
- if (STREQ(name, (*sec)->name))
- return(*sec);
- }
- return NULL;
- }
- /*
- * Walk through the current set of symbols and check for duplicates.
- */
- static void
- check_for_dups(struct load_module *lm)
- {
- struct syment *sp, *sp_end;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp <= sp_end; sp++) {
- if (symbol_name_count(sp->name) > 1)
- error(NOTE, "%s: duplicate symbol name: %s\n",
- lm->mod_name, sp->name);
- }
- }
- /*
- * Store the externally declared symbols for all modules in the system.
- * allowing for dynamic loading of symbols from individual mod object files
- * during runtime.
- */
- struct module_symbol {
- unsigned long value;
- const char *name;
- };
- void
- store_module_symbols_v1(ulong total, int mods_installed)
- {
- int i, m;
- ulong mod, mod_next, mod_name;
- uint nsyms;
- ulong syms, size_of_struct;
- long strbuflen, size;
- int mcnt, lm_mcnt;
- struct module_symbol *modsym;
- struct load_module *lm;
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char name[BUFSIZE];
- char rodata[BUFSIZE];
- char *strbuf, *modbuf, *modsymbuf;
- struct syment *sp;
- ulong first, last;
- st->mods_installed = mods_installed;
- if (!st->mods_installed) {
- st->flags &= ~MODULE_SYMS;
- return;
- }
- /*
- * If we've been here before, free up everything and start over.
- */
- if (st->flags & MODULE_SYMS) {
- error(FATAL,
- "re-initialization of module symbols not implemented yet!\n");
- }
- if ((st->ext_module_symtable = (struct syment *)
- calloc(total, sizeof(struct syment))) == NULL)
- error(FATAL, "module syment space malloc: %s\n",
- strerror(errno));
- if (!namespace_ctl(NAMESPACE_INIT, &st->ext_module_namespace,
- (void *)total, NULL))
- error(FATAL, "module namespace malloc: %s\n",
- strerror(errno));
- if ((st->load_modules = (struct load_module *)calloc
- (st->mods_installed, sizeof(struct load_module))) == NULL)
- error(FATAL, "load_module array malloc: %s\n", strerror(errno));
- modbuf = GETBUF(SIZE(module));
- modsymbuf = NULL;
- m = mcnt = mod_next = 0;
- for (mod = kt->module_list; mod != kt->kernel_module; mod = mod_next) {
- readmem(mod, KVADDR, modbuf, SIZE(module),
- "module buffer", FAULT_ON_ERROR);
- nsyms = UINT(modbuf + OFFSET(module_nsyms));
- syms = ULONG(modbuf + OFFSET(module_syms));
- size = LONG(modbuf + OFFSET(module_size));
- mod_name = ULONG(modbuf + OFFSET(module_name));
- size_of_struct = ULONG(modbuf +
- OFFSET(module_size_of_struct));
- if (!read_string(mod_name, name, BUFSIZE-1))
- sprintf(name, "(unknown module)");
-
- sprintf(rodata, "__insmod_%s_S.rodata", name);
- lm = &st->load_modules[m++];
- BZERO(lm, sizeof(struct load_module));
- lm->mod_base = lm->module_struct = mod;
- lm->mod_size = size;
- lm->mod_size_of_struct = size_of_struct;
- if (strlen(name) < MAX_MOD_NAME)
- strcpy(lm->mod_name, name);
- else {
- error(INFO,
- "module name greater than MAX_MOD_NAME: %s\n",
- name);
- strncpy(lm->mod_name, name, MAX_MOD_NAME-1);
- }
- lm->mod_flags = MOD_EXT_SYMS;
- lm->mod_ext_symcnt = mcnt;
- lm->mod_etext_guess = 0;
- st->ext_module_symtable[mcnt].value = mod;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_START_", name);
- namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf2);
- lm_mcnt = mcnt;
- mcnt++;
- if (nsyms) {
- modsymbuf = GETBUF(sizeof(struct module_symbol)*nsyms);
- readmem((ulong)syms, KVADDR, modsymbuf,
- nsyms * sizeof(struct module_symbol),
- "module symbols", FAULT_ON_ERROR);
- }
- for (i = first = last = 0; i < nsyms; i++) {
- modsym = (struct module_symbol *)
- (modsymbuf + (i * sizeof(struct module_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- }
- if (last > first) {
- strbuflen = (last-first) + BUFSIZE;
- if ((first + strbuflen) >=
- (lm->mod_base + lm->mod_size)) {
- strbuflen = (lm->mod_base + lm->mod_size) -
- first;
- }
- strbuf = GETBUF(strbuflen);
- if (!readmem(first, KVADDR, strbuf, strbuflen,
- "module symbol strings", RETURN_ON_ERROR)) {
- FREEBUF(strbuf);
- strbuf = NULL;
- }
- } else
- strbuf = NULL;
- for (i = first = last = 0; i < nsyms; i++) {
- modsym = (struct module_symbol *)
- (modsymbuf + (i * sizeof(struct module_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- BZERO(buf1, BUFSIZE);
- if (strbuf)
- strcpy(buf1,
- &strbuf[(ulong)modsym->name - first]);
- else
- read_string((ulong)modsym->name, buf1,
- BUFSIZE-1);
- if (strlen(buf1)) {
- st->ext_module_symtable[mcnt].value =
- modsym->value;
- st->ext_module_symtable[mcnt].type = '?';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- strip_module_symbol_end(buf1);
- strip_symbol_end(buf1, NULL);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf1);
- if (strstr(buf1, rodata))
- lm->mod_etext_guess = modsym->value;
- sprintf(buf2, "__insmod_%s_O/", lm->mod_name);
- if (strstr(buf1, buf2) &&
- !strstr(buf1, "modules"))
- lm->mod_flags |= MOD_INITRD;
- mcnt++;
- }
- }
-
- if (modsymbuf) {
- FREEBUF(modsymbuf);
- modsymbuf = NULL;
- }
- if (strbuf)
- FREEBUF(strbuf);
- /*
- * If the module was compiled with kallsyms, add them in.
- */
- switch (kt->flags & (KALLSYMS_V1|KALLSYMS_V2))
- {
- case KALLSYMS_V1:
- mcnt += store_module_kallsyms_v1(lm, lm_mcnt,
- mcnt, modbuf);
- break;
- case KALLSYMS_V2: /* impossible, I hope... */
- mcnt += store_module_kallsyms_v2(lm, lm_mcnt,
- mcnt, modbuf);
- break;
- }
- st->ext_module_symtable[mcnt].value = mod + size;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_END_", name);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf2);
- mcnt++;
- lm->mod_ext_symcnt = mcnt - lm->mod_ext_symcnt;
- if (!lm->mod_etext_guess)
- find_mod_etext(lm);
- NEXT_MODULE(mod_next, modbuf);
- }
- FREEBUF(modbuf);
- st->ext_module_symcnt = mcnt;
- st->ext_module_symend = &st->ext_module_symtable[mcnt];
- namespace_ctl(NAMESPACE_COMPLETE, &st->ext_module_namespace,
- st->ext_module_symtable, st->ext_module_symend);
- qsort(st->ext_module_symtable, mcnt, sizeof(struct syment),
- compare_syms);
- qsort(st->load_modules, m, sizeof(struct load_module), compare_mods);
- for (m = 0; m < st->mods_installed; m++) {
- lm = &st->load_modules[m];
- sprintf(buf1, "_MODULE_START_%s", lm->mod_name);
- sprintf(buf2, "_MODULE_END_%s", lm->mod_name);
- for (sp = st->ext_module_symtable;
- sp < st->ext_module_symend; sp++) {
- if (STREQ(sp->name, buf1)) {
- lm->mod_ext_symtable = sp;
- lm->mod_symtable = sp;
- }
- if (STREQ(sp->name, buf2)) {
- lm->mod_ext_symend = sp;
- lm->mod_symend = sp;
- }
- }
- }
- st->flags |= MODULE_SYMS;
- if (symbol_query("__insmod_", NULL, NULL))
- st->flags |= INSMOD_BUILTIN;
- }
- struct kernel_symbol
- {
- unsigned long value;
- const char *name;
- };
- void
- store_module_symbols_v2(ulong total, int mods_installed)
- {
- int i, m;
- ulong mod, mod_next;
- char *mod_name;
- uint nsyms, ngplsyms;
- ulong syms, gpl_syms;
- ulong nksyms;
- long strbuflen;
- ulong size;
- int mcnt, lm_mcnt;
- struct kernel_symbol *modsym;
- struct load_module *lm;
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- char buf4[BUFSIZE];
- char *strbuf, *modbuf, *modsymbuf;
- struct syment *sp;
- ulong first, last;
- st->mods_installed = mods_installed;
- if (!st->mods_installed) {
- st->flags &= ~MODULE_SYMS;
- return;
- }
- /*
- * If we've been here before, free up everything and start over.
- */
- if (st->flags & MODULE_SYMS) {
- error(FATAL,
- "re-initialization of module symbols not implemented yet!\n");
- }
- if ((st->ext_module_symtable = (struct syment *)
- calloc(total, sizeof(struct syment))) == NULL)
- error(FATAL, "v2 module syment space malloc (%ld symbols): %s\n",
- total, strerror(errno));
- if (!namespace_ctl(NAMESPACE_INIT, &st->ext_module_namespace,
- (void *)total, NULL))
- error(FATAL, "module namespace malloc: %s\n",
- strerror(errno));
- if ((st->load_modules = (struct load_module *)calloc
- (st->mods_installed, sizeof(struct load_module))) == NULL)
- error(FATAL, "load_module array malloc: %s\n", strerror(errno));
- modbuf = GETBUF(SIZE(module));
- modsymbuf = NULL;
- m = mcnt = mod_next = 0;
- for (mod = kt->module_list; mod != kt->kernel_module; mod = mod_next) {
- readmem(mod, KVADDR, modbuf, SIZE(module),
- "module buffer", FAULT_ON_ERROR);
- syms = ULONG(modbuf + OFFSET(module_syms));
- gpl_syms = ULONG(modbuf + OFFSET(module_gpl_syms));
- nsyms = UINT(modbuf + OFFSET(module_num_syms));
- ngplsyms = UINT(modbuf + OFFSET(module_num_gpl_syms));
- if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {
- nksyms = UINT(modbuf + OFFSET(module_num_symtab));
- size = UINT(modbuf + OFFSET(module_core_size));
- } else {
- nksyms = ULONG(modbuf + OFFSET(module_num_symtab));
- size = ULONG(modbuf + OFFSET(module_core_size));
- }
- mod_name = modbuf + OFFSET(module_name);
- lm = &st->load_modules[m++];
- BZERO(lm, sizeof(struct load_module));
- lm->mod_base = ULONG(modbuf + OFFSET(module_module_core));
- lm->module_struct = mod;
- lm->mod_size = size;
- if (strlen(mod_name) < MAX_MOD_NAME)
- strcpy(lm->mod_name, mod_name);
- else {
- error(INFO,
- "module name greater than MAX_MOD_NAME: %s\n",
- mod_name);
- strncpy(lm->mod_name, mod_name, MAX_MOD_NAME-1);
- }
- if (CRASHDEBUG(3))
- fprintf(fp,
- "%lx (%lx): %s syms: %d gplsyms: %d ksyms: %ld\n",
- mod, lm->mod_base, lm->mod_name, nsyms,
- ngplsyms, nksyms);
- lm->mod_flags = MOD_EXT_SYMS;
- lm->mod_ext_symcnt = mcnt;
- lm->mod_init_module_ptr = ULONG(modbuf +
- OFFSET(module_module_init));
- if (VALID_MEMBER(module_percpu))
- lm->mod_percpu = ULONG(modbuf + OFFSET(module_percpu));
- if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) {
- lm->mod_etext_guess = lm->mod_base +
- UINT(modbuf + OFFSET(module_core_text_size));
- lm->mod_init_size =
- UINT(modbuf + OFFSET(module_init_size));
- lm->mod_init_text_size =
- UINT(modbuf + OFFSET(module_init_text_size));
- } else {
- lm->mod_etext_guess = lm->mod_base +
- ULONG(modbuf + OFFSET(module_core_text_size));
- lm->mod_init_size =
- ULONG(modbuf + OFFSET(module_init_size));
- lm->mod_init_text_size =
- ULONG(modbuf + OFFSET(module_init_text_size));
- }
- lm->mod_text_start = lm->mod_base;
- st->ext_module_symtable[mcnt].value = lm->mod_base;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_START_", mod_name);
- namespace_ctl(NAMESPACE_INSTALL, &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf2);
- lm_mcnt = mcnt;
- mcnt++;
- if (lm->mod_init_size > 0) {
- st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf3, "%s%s", "_MODULE_INIT_START_", mod_name);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf3);
- lm_mcnt = mcnt;
- mcnt++;
- lm->mod_flags |= MOD_INIT;
- }
- if (nsyms && !IN_MODULE(syms, lm)) {
- error(WARNING,
- "[%s] module.syms outside of module "
- "address space (%lx)\n\n",
- lm->mod_name, syms);
- nsyms = 0;
- }
- if (nsyms) {
- modsymbuf = GETBUF(sizeof(struct kernel_symbol)*nsyms);
- readmem((ulong)syms, KVADDR, modsymbuf,
- nsyms * sizeof(struct kernel_symbol),
- "module symbols", FAULT_ON_ERROR);
- }
- for (i = first = last = 0; i < nsyms; i++) {
- modsym = (struct kernel_symbol *)
- (modsymbuf + (i * sizeof(struct kernel_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- }
- if (last > first) {
- strbuflen = (last-first) + BUFSIZE;
- if ((first + strbuflen) >=
- (lm->mod_base + lm->mod_size)) {
- strbuflen = (lm->mod_base + lm->mod_size) -
- first;
- }
- strbuf = GETBUF(strbuflen);
- if (!readmem(first, KVADDR, strbuf, strbuflen,
- "module symbol strings", RETURN_ON_ERROR)) {
- FREEBUF(strbuf);
- strbuf = NULL;
- }
- } else
- strbuf = NULL;
- for (i = first = last = 0; i < nsyms; i++) {
- modsym = (struct kernel_symbol *)
- (modsymbuf + (i * sizeof(struct kernel_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- BZERO(buf1, BUFSIZE);
- if (strbuf)
- strcpy(buf1,
- &strbuf[(ulong)modsym->name - first]);
- else
- read_string((ulong)modsym->name, buf1,
- BUFSIZE-1);
- if (strlen(buf1)) {
- st->ext_module_symtable[mcnt].value =
- modsym->value;
- st->ext_module_symtable[mcnt].type = '?';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- strip_module_symbol_end(buf1);
- strip_symbol_end(buf1, NULL);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf1);
- mcnt++;
- }
- }
-
- if (modsymbuf) {
- FREEBUF(modsymbuf);
- modsymbuf = NULL;
- }
- if (strbuf)
- FREEBUF(strbuf);
- if (ngplsyms) {
- modsymbuf = GETBUF(sizeof(struct kernel_symbol) *
- ngplsyms);
- readmem((ulong)gpl_syms, KVADDR, modsymbuf,
- ngplsyms * sizeof(struct kernel_symbol),
- "module gpl symbols", FAULT_ON_ERROR);
- }
- for (i = first = last = 0; i < ngplsyms; i++) {
- modsym = (struct kernel_symbol *)
- (modsymbuf + (i * sizeof(struct kernel_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- }
- if (last > first) {
- strbuflen = (last-first) + BUFSIZE;
- if ((first + strbuflen) >=
- (lm->mod_base + lm->mod_size)) {
- strbuflen = (lm->mod_base + lm->mod_size) -
- first;
- }
- strbuf = GETBUF(strbuflen);
- if (!readmem(first, KVADDR, strbuf, strbuflen,
- "module gpl symbol strings", RETURN_ON_ERROR)) {
- FREEBUF(strbuf);
- strbuf = NULL;
- }
- } else
- strbuf = NULL;
- for (i = first = last = 0; i < ngplsyms; i++) {
- modsym = (struct kernel_symbol *)
- (modsymbuf + (i * sizeof(struct kernel_symbol)));
- if (!first)
- first = (ulong)modsym->name;
- last = (ulong)modsym->name;
- BZERO(buf1, BUFSIZE);
- if (strbuf)
- strcpy(buf1,
- &strbuf[(ulong)modsym->name - first]);
- else
- read_string((ulong)modsym->name, buf1,
- BUFSIZE-1);
- if (strlen(buf1)) {
- st->ext_module_symtable[mcnt].value =
- modsym->value;
- st->ext_module_symtable[mcnt].type = '?';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- strip_module_symbol_end(buf1);
- strip_symbol_end(buf1, NULL);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf1);
- mcnt++;
- }
- }
-
- if (modsymbuf) {
- FREEBUF(modsymbuf);
- modsymbuf = NULL;
- }
- if (strbuf)
- FREEBUF(strbuf);
- /*
- * If the module was compiled with kallsyms, add them in.
- */
- switch (kt->flags & (KALLSYMS_V1|KALLSYMS_V2))
- {
- case KALLSYMS_V1: /* impossible, I hope... */
- mcnt += store_module_kallsyms_v1(lm, lm_mcnt,
- mcnt, modbuf);
- break;
- case KALLSYMS_V2:
- mcnt += store_module_kallsyms_v2(lm, lm_mcnt,
- mcnt, modbuf);
- break;
- }
- st->ext_module_symtable[mcnt].value = lm->mod_base + size;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf2, "%s%s", "_MODULE_END_", mod_name);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf2);
- mcnt++;
- if (lm->mod_init_size > 0) {
- st->ext_module_symtable[mcnt].value = lm->mod_init_module_ptr + lm->mod_init_size;
- st->ext_module_symtable[mcnt].type = 'm';
- st->ext_module_symtable[mcnt].flags |= MODULE_SYMBOL;
- sprintf(buf4, "%s%s", "_MODULE_INIT_END_", mod_name);
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt], buf4);
- mcnt++;
- }
- lm->mod_ext_symcnt = mcnt - lm->mod_ext_symcnt;
- if (!lm->mod_etext_guess)
- find_mod_etext(lm);
- NEXT_MODULE(mod_next, modbuf);
- }
- FREEBUF(modbuf);
- st->ext_module_symcnt = mcnt;
- st->ext_module_symend = &st->ext_module_symtable[mcnt];
- namespace_ctl(NAMESPACE_COMPLETE, &st->ext_module_namespace,
- st->ext_module_symtable, st->ext_module_symend);
- qsort(st->ext_module_symtable, mcnt, sizeof(struct syment),
- compare_syms);
- qsort(st->load_modules, m, sizeof(struct load_module), compare_mods);
- for (m = 0; m < st->mods_installed; m++) {
- lm = &st->load_modules[m];
- sprintf(buf1, "_MODULE_START_%s", lm->mod_name);
- sprintf(buf2, "_MODULE_END_%s", lm->mod_name);
- sprintf(buf3, "_MODULE_INIT_START_%s", lm->mod_name);
- sprintf(buf4, "_MODULE_INIT_END_%s", lm->mod_name);
- for (sp = st->ext_module_symtable;
- sp < st->ext_module_symend; sp++) {
- if (STREQ(sp->name, buf1)) {
- lm->mod_ext_symtable = sp;
- lm->mod_symtable = sp;
- }
- if (STREQ(sp->name, buf2)) {
- lm->mod_ext_symend = sp;
- lm->mod_symend = sp;
- }
- if (STREQ(sp->name, buf3)) {
- lm->mod_init_symtable = sp;
- }
- if (STREQ(sp->name, buf4)) {
- lm->mod_init_symend = sp;
- }
- }
- }
- st->flags |= MODULE_SYMS;
- if (symbol_query("__insmod_", NULL, NULL))
- st->flags |= INSMOD_BUILTIN;
- if (mcnt > total)
- error(FATAL, "store_module_symbols_v2: total: %ld mcnt: %d\n",
- total, mcnt);
- }
- /*
- * Get the module's kallsyms list if it was compiled in.
- */
- static int
- store_module_kallsyms_v1(struct load_module *lm, int start, int curr,
- char *modbuf)
- {
- int i, j;
- struct syment *sp;
- ulong kallsyms_header;
- char *module_buf;
- char *header_buf;
- uint symbols;
- ulong name_off;
- ulong sec_name_off;
- ulong section_off;
- ulong symptr;
- ulong symbol_addr;
- ulong stringptr;
- ulong sectionptr;
- char *nameptr;
- char *secnameptr;
- ulong secptr;
- char type;
- int mcnt;
- int mcnt_idx;
- int found;
- struct symbol_namespace *ns;
- if (!(kt->flags & KALLSYMS_V1))
- return 0;
- kallsyms_header = ULONG(modbuf + OFFSET(module_kallsyms_start));
- if (!kallsyms_header)
- return 0;
- mcnt = 0;
- mcnt_idx = curr;
- module_buf = GETBUF(ULONG(modbuf + OFFSET(module_size)));
- ns = &st->ext_module_namespace;
- if (!readmem(lm->mod_base, KVADDR, module_buf, lm->mod_size,
- "module (kallsyms)", RETURN_ON_ERROR|QUIET)) {
- error(WARNING,"cannot access module kallsyms\n");
- FREEBUF(module_buf);
- return 0;
- }
- #define IN_MODULE_BUF_V1(x) \
- (((x) >= module_buf) && ((x) < (module_buf + lm->mod_size)))
- header_buf = module_buf + (kallsyms_header - lm->mod_base);
- symbols = UINT(header_buf + OFFSET(kallsyms_header_symbols));
- // sections = UINT(header_buf + OFFSET(kallsyms_header_sections));
- if (CRASHDEBUG(7))
- fprintf(fp, "kallsyms: module: %s\n", lm->mod_name);
- symptr = (ulong)(header_buf +
- ULONG(header_buf + OFFSET(kallsyms_header_symbol_off)));
- stringptr = (ulong)(header_buf +
- ULONG(header_buf + OFFSET(kallsyms_header_string_off)));
- sectionptr = (ulong)(header_buf +
- ULONG(header_buf + OFFSET(kallsyms_header_section_off)));
- for (i = 0; i < symbols; i++, symptr += SIZE(kallsyms_symbol)) {
- symbol_addr = ULONG(symptr+OFFSET(kallsyms_symbol_symbol_addr));
- name_off = ULONG(symptr+OFFSET(kallsyms_symbol_name_off));
- section_off = ULONG(symptr+OFFSET(kallsyms_symbol_section_off));
- nameptr = (char *)(stringptr + name_off);
- secptr = (ulong)(sectionptr + section_off);
- sec_name_off = ULONG(secptr+OFFSET(kallsyms_section_name_off));
- secnameptr = (char *)(stringptr + sec_name_off);
- if (!IN_MODULE_BUF_V1(nameptr)) {
- if (CRASHDEBUG(7))
- error(INFO,
- "%s: invalid nameptr: %lx (stringptr: %lx + name_off: %lx)\n",
- lm->mod_name, nameptr,
- stringptr, name_off);
- continue;
- }
- if (!IN_MODULE_BUF_V1(secnameptr)) {
- if (CRASHDEBUG(7))
- error(INFO,
- "%s: invalid secnameptr: %lx (stringptr: %lx + sec_name_off: %lx)\n",
- lm->mod_name, secnameptr,
- stringptr, sec_name_off);
- continue;
- }
- if (!STREQ(nameptr, secnameptr)) {
- if (STREQ(secnameptr, ".text"))
- type = 't';
- else if (STREQ(secnameptr, ".data"))
- type = 'd';
- else if (STREQ(secnameptr, ".bss"))
- type = 'b';
- else if (STREQ(secnameptr, ".rodata"))
- type = 'd';
- else
- continue;
- strip_module_symbol_end(nameptr);
- strip_symbol_end(nameptr, NULL);
- if (CRASHDEBUG(7))
- fprintf(fp," symbol: %lx \"%s\" section: %s\n",
- symbol_addr, nameptr, secnameptr);
- for (found = 0, j = start; j < curr; j++) {
- sp = &st->ext_module_symtable[j];
- if ((sp->value == symbol_addr) &&
- STREQ(nameptr,
- &ns->address[(ulong)sp->name])) {
- if (CRASHDEBUG(7))
- fprintf(fp,
- "current symbol \"%s\" at %lx of type (%c)\n",
- &ns->address[(ulong)sp->name],
- sp->value, sp->type);
- if (sp->type == '?')
- sp->type = type;
- found++;
- break;
- }
- }
- if (found)
- continue;
- st->ext_module_symtable[mcnt_idx].value = symbol_addr;
- st->ext_module_symtable[mcnt_idx].type = type;
- st->ext_module_symtable[mcnt_idx].flags |= MODULE_SYMBOL;
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt_idx++], nameptr);
- mcnt++;
- }
- }
- lm->mod_flags |= MOD_KALLSYMS;
- FREEBUF(module_buf);
- return mcnt;
- }
- /*
- * Translate either an Elf32_Sym or Elf64_Sym to an elf_common structure
- * for more convenient use by store_module_kallsyms_v2().
- */
- struct elf_common {
- ulong st_name;
- ulong st_value;
- ulong st_shndx;
- unsigned char st_info;
- };
- static void Elf32_Sym_to_common(Elf32_Sym *e32, struct elf_common *ec)
- {
- ec->st_name = (ulong)e32->st_name;
- ec->st_value = (ulong)e32->st_value;
- ec->st_shndx = (ulong)e32->st_shndx;
- ec->st_info = e32->st_info;
- }
- static void Elf64_Sym_to_common(Elf64_Sym *e64, struct elf_common *ec)
- {
- ec->st_name = (ulong)e64->st_name;
- ec->st_value = (ulong)e64->st_value;
- ec->st_shndx = (ulong)e64->st_shndx;
- ec->st_info = e64->st_info;
- }
- static int
- store_module_kallsyms_v2(struct load_module *lm, int start, int curr,
- char *modbuf)
- {
- int i, j, found;
- struct elf_common elf_common, *ec;
- ulong nksyms, ksymtab, kstrtab;
- char *module_buf, *ptr, *locsymtab, *locstrtab, *nameptr;
- struct syment *sp;
- struct symbol_namespace *ns;
- int mcnt;
- int mcnt_idx;
- char *module_buf_init = NULL;
- if (!(kt->flags & KALLSYMS_V2))
- return 0;
- mcnt = 0;
- BZERO(&elf_common, sizeof(struct elf_common));
- mcnt_idx = curr;
- ns = &st->ext_module_namespace;
- ec = &elf_common;
- module_buf = GETBUF(lm->mod_size);
- if (!readmem(lm->mod_base, KVADDR, module_buf, lm->mod_size,
- "module (kallsyms)", RETURN_ON_ERROR|QUIET)) {
- error(WARNING,"cannot access module kallsyms\n");
- FREEBUF(module_buf);
- return 0;
- }
- if (lm->mod_init_size > 0) {
- module_buf_init = GETBUF(lm->mod_init_size);
- if (!readmem(lm->mod_init_module_ptr, KVADDR, module_buf_init, lm->mod_init_size,
- "module init (kallsyms)", RETURN_ON_ERROR|QUIET)) {
- error(WARNING,"cannot access module init kallsyms\n");
- FREEBUF(module_buf_init);
- }
- }
- if (THIS_KERNEL_VERSION >= LINUX(2,6,27))
- nksyms = UINT(modbuf + OFFSET(module_num_symtab));
- else
- nksyms = ULONG(modbuf + OFFSET(module_num_symtab));
- ksymtab = ULONG(modbuf + OFFSET(module_symtab));
- if (!IN_MODULE(ksymtab, lm) && !IN_MODULE_INIT(ksymtab, lm)) {
- error(WARNING,
- "%s: module.symtab outside of module address space\n",
- lm->mod_name);
- FREEBUF(module_buf);
- if (module_buf_init)
- FREEBUF(module_buf_init);
- return 0;
- }
- if (IN_MODULE(ksymtab, lm))
- locsymtab = module_buf + (ksymtab - lm->mod_base);
- else
- locsymtab = module_buf_init + (ksymtab - lm->mod_init_module_ptr);
- kstrtab = ULONG(modbuf + OFFSET(module_strtab));
- if (!IN_MODULE(kstrtab, lm) && !IN_MODULE_INIT(kstrtab, lm)) {
- error(WARNING,
- "%s: module.strtab outside of module address space\n",
- lm->mod_name);
- FREEBUF(module_buf);
- if (module_buf_init)
- FREEBUF(module_buf_init);
- return 0;
- }
- if (IN_MODULE(kstrtab, lm))
- locstrtab = module_buf + (kstrtab - lm->mod_base);
- else
- locstrtab = module_buf_init + (kstrtab - lm->mod_init_module_ptr);
- for (i = 1; i < nksyms; i++) { /* ELF starts real symbols at 1 */
- switch (BITS())
- {
- case 32:
- ptr = locsymtab + (i * sizeof(Elf32_Sym));
- Elf32_Sym_to_common((Elf32_Sym *)ptr, ec);
- break;
- case 64:
- ptr = locsymtab + (i * sizeof(Elf64_Sym));
- Elf64_Sym_to_common((Elf64_Sym *)ptr, ec);
- break;
- }
- if (((ec->st_value < lm->mod_base) ||
- (ec->st_value > (lm->mod_base + lm->mod_size))) &&
- ((ec->st_value < lm->mod_init_module_ptr) ||
- (ec->st_value > (lm->mod_init_module_ptr + lm->mod_init_size))))
- continue;
- if (ec->st_shndx == SHN_UNDEF)
- continue;
- if (!IN_MODULE(kstrtab + ec->st_name, lm) && !IN_MODULE_INIT(kstrtab + ec->st_name, lm)) {
- if (CRASHDEBUG(3)) {
- error(WARNING,
- "%s: bad st_name index: %lx -> %lx\n "
- " st_value: %lx st_shndx: %ld st_info: %c\n",
- lm->mod_name,
- ec->st_name, (kstrtab + ec->st_name),
- ec->st_value, ec->st_shndx,
- ec->st_info);
- }
- continue;
- }
- nameptr = locstrtab + ec->st_name;
- if (*nameptr == '\0')
- continue;
- /*
- * On ARM we have linker mapping symbols like '$a' and '$d'.
- * Make sure that these don't end up into our symbol list.
- */
- if (machine_type("ARM") &&
- !machdep->verify_symbol(nameptr, ec->st_value, ec->st_info))
- continue;
- if (CRASHDEBUG(7))
- fprintf(fp,
- "%s: st_name: %ld st_value: %lx st_shndx: %ld st_info: %c\n",
- nameptr, ec->st_name, ec->st_value,
- ec->st_shndx, ec->st_info);
- strip_symbol_end(nameptr, NULL);
- for (found = 0, j = start; j < curr; j++) {
- sp = &st->ext_module_symtable[j];
- if ((sp->value == ec->st_value) &&
- STREQ(nameptr, &ns->address[(ulong)sp->name])) {
- if (CRASHDEBUG(7))
- fprintf(fp,
- "current symbol \"%s\" at %lx of type (%c)\n",
- &ns->address[(ulong)sp->name],
- sp->value, sp->type);
- if (sp->type == '?')
- sp->type = ec->st_info;
- found++;
- break;
- }
- }
- if (found)
- continue;
- st->ext_module_symtable[mcnt_idx].value = ec->st_value;
- st->ext_module_symtable[mcnt_idx].type = ec->st_info;
- st->ext_module_symtable[mcnt_idx].flags |= MODULE_SYMBOL;
- namespace_ctl(NAMESPACE_INSTALL,
- &st->ext_module_namespace,
- &st->ext_module_symtable[mcnt_idx++], nameptr);
- mcnt++;
- }
- lm->mod_flags |= MOD_KALLSYMS;
- FREEBUF(module_buf);
- if (module_buf_init)
- FREEBUF(module_buf_init);
- return mcnt;
- }
- /*
- * Strip the kernel clutter tagged on the end of an exported module symbol.
- */
- static void
- strip_module_symbol_end(char *buf)
- {
- char *p1, *lastR;
- if (!(lastR = strrchr(buf, 'R')))
- return;
- if (((p1 = lastR-1) < buf) || (*p1 != '_'))
- return;
- if ((kt->flags & SMP) && STRNEQ(p1, "_Rsmp_")) {
- *p1 = NULLCHAR;
- return;
- }
- if (!hexadecimal(lastR+1, 0))
- return;
- *p1 = NULLCHAR;
- }
- /*
- * Return the lowest or highest module virtual address.
- */
- ulong
- lowest_module_address(void)
- {
- int i;
- struct load_module *lm;
- ulong low, lowest;
- if (!st->mods_installed)
- return 0;
- lowest = (ulong)(-1);
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- low = lm->mod_base;
- if (low < lowest)
- lowest = low;
- }
- return lowest;
- }
- ulong
- highest_module_address(void)
- {
- int i;
- struct load_module *lm;
- ulong high, highest;
- highest = 0;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- high = lm->mod_base + lm->mod_size;
- if (high > highest)
- highest = high;
- }
- return highest;
- }
- /*
- * Look through a string for bogus kernel clutter of an exported
- * module symbol. In the case of LM_P_FILTER, shift the string left
- * as appropriate to get rid of the extra stuff. In the case of
- * LM_DIS_FILTER, translation of the previous address is done first,
- * and its results are stuffed into the string. In both cases,
- * this routine is recursive to catch multiple instances.
- */
- #define SMP_CLUTTER (strlen("_Rsmp_"))
- #define UP_CLUTTER (strlen("_R"))
- #define CLUTTER_IDLEN (8)
- char *
- load_module_filter(char *s, int type)
- {
- char *arglist[MAXARGS];
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- int clen, last;
- int prev;
- char *pstart, *p1, *p2, *smp, *pend, *colon;
- ulong vaddr;
- ulong offset;
- struct syment *sp;
- int argc;
- switch (type)
- {
- case LM_P_FILTER:
- if (!(pstart = strstr(s, "_R")))
- return s;
- smp = strstr(s, "_Rsmp_");
- pend = &s[strlen(s)];
- p2 = pstart + (smp ? SMP_CLUTTER : UP_CLUTTER);
- if ((p2 >= pend) || !hexadecimal(p2, CLUTTER_IDLEN))
- return s;
- clen = smp ?
- SMP_CLUTTER+CLUTTER_IDLEN : UP_CLUTTER+CLUTTER_IDLEN;
- if (bracketed(s, pstart, clen)) { /* hack it out for now */
- pstart--;
- shift_string_left(pstart, clen+2);
- if (*pstart == ',')
- shift_string_left(pstart-1, 1);
- } else
- shift_string_left(pstart, clen);
- return (load_module_filter(s, type)); /* catch multiples */
- case LM_DIS_FILTER:
- strip_beginning_whitespace(s);
- strcpy(buf1, s);
- argc = parse_line(buf1, arglist);
- if (argc < 2)
- return s;
- /*
- * Fix up the first half of the disassembly expression,
- * that is, the address and symbol to the left of the
- * colon.
- */
- colon = NULL;
- if (hexadecimal(arglist[0], VADDR_PRLEN+2) &&
- bracketed(arglist[1], &arglist[1][1], 0) &&
- (colon = strstr(s, ":"))) {
- strcpy(buf2, colon+2);
- vaddr = htol(arglist[0], FAULT_ON_ERROR, NULL);
- if ((sp = value_search(vaddr, &offset))) {
- if (offset)
- sprintf(s, "%s <%s+%ld>:\t%s",
- arglist[0], sp->name, offset, buf2);
- else
- sprintf(s, "%s <%s>:\t%s",
- arglist[0], sp->name, buf2);
- }
- }
- /*
- * Now work on the second part -- if it exists.
- * Find a virtual address followed by a bracked symbol
- * at the end of the line.
- */
- if (colon) {
- strcpy(buf1, s);
- argc = parse_line(buf1, arglist);
- colon = strstr(s, ":");
- }
- last = argc-1;
- prev = argc-2;
- if (bracketed(arglist[last], &arglist[last][1], 0) &&
- hexadecimal(arglist[prev], VADDR_PRLEN+2)) {
- vaddr = htol(arglist[prev], FAULT_ON_ERROR, NULL);
- p1 = strstr(s, arglist[last]);
- if ((sp = value_search(vaddr, &offset)) &&
- !(colon && (p1 < colon))) {
- if (offset)
- sprintf(p1, "<%s+%ld>\n",
- sp->name, offset);
- else
- sprintf(p1, "<%s>\n", sp->name);
- }
- }
- pend = &s[strlen(s)-3];
- if (STREQ(pend, ":\t\n"))
- LASTCHAR(s) = NULLCHAR;
- return s;
- default:
- return NULL; /* can't get here */
- }
- }
- /*
- * Handle the various commands for controlling symbol string space:
- *
- * NAMESPACE_INIT: Allocates an estimated size for the string space.
- * NAMESPACE_REUSE: Resets appropriate fields to allow a previously
- * allocated module string buffer to be reused.
- * NAMESPACE_FREE: Frees (module) string space.
- * NAMESPACE_INSTALL: Copies a symbol name string into the next available
- * buffer space. If the string cannot be squeezed in,
- * the whole string space is reallocated, which may
- * change its starting address. For that reason, the
- * buffer index is temporarily stored in the sp->name
- * field, which NAMESPACE_COMPLETE later transforms into
- * the proper address when the buffer is set.
- * NAMESPACE_COMPLETE: Reallocs a completed string buffer to the exact
- * size that is required, and then calculates and stores
- * the proper addresses into the name fields of the
- * passed-in syment array.
- */
- #define AVERAGE_SYMBOL_SIZE (16)
- static int
- namespace_ctl(int cmd, struct symbol_namespace *ns, void *nsarg1, void *nsarg2)
- {
- char *addr;
- struct syment *sp, *sp_end;
- char *name;
- long cnt;
- int len;
- switch (cmd)
- {
- case NAMESPACE_INIT:
- cnt = (long)nsarg1;
- if ((addr = calloc(cnt, AVERAGE_SYMBOL_SIZE)) == NULL)
- return FALSE;
- ns->address = addr;
- ns->index = 0;
- ns->cnt = 0;
- ns->size = cnt * AVERAGE_SYMBOL_SIZE;
- return TRUE;
- case NAMESPACE_REUSE:
- ns->index = 0;
- ns->cnt = 0;
- return TRUE;
- case NAMESPACE_FREE:
- if (!ns->address)
- error(FATAL,
- "attempt to free unallocated module namespace\n");
- free(ns->address);
- ns->address = 0;
- ns->index = 0;
- ns->size = 0;
- ns->cnt = 0;
- return TRUE;
- case NAMESPACE_INSTALL:
- sp = (struct syment *)nsarg1;
- name = (char *)nsarg2;
- len = strlen(name)+1;
- if ((ns->index + len) >= ns->size) {
- if (!(addr = realloc(ns->address, ns->size*2)))
- error(FATAL, "symbol name space malloc: %s\n",
- strerror(errno));
- ns->address = addr;
- ns->size *= 2;
- }
- sp->name = (char *)ns->index;
- BCOPY(name, &ns->address[ns->index], len);
- ns->index += len;
- ns->cnt++;
- return TRUE;
- case NAMESPACE_COMPLETE:
- sp = (struct syment *)nsarg1;
- sp_end = (struct syment *)nsarg2;
- if (ns->index < (ns->size-1)) {
- if ((addr = realloc(ns->address, ns->index+1))) {
- ns->address = addr;
- ns->size = ns->index+1;
- }
- }
- for ( ; sp < sp_end; sp++)
- sp->name = ns->address + (long)sp->name;
- return TRUE;
- default:
- return FALSE; /* can't get here */
- }
- }
- /*
- * These comparison functions must return an integer less than,
- * equal to, or greater than zero if the first argument is
- * considered to be respectively less than, equal to, or
- * greater than the second. If two members compare as equal,
- * their order in the sorted array is undefined.
- */
- static int
- compare_syms(const void *v1, const void *v2)
- {
- struct syment *s1, *s2;
- char sn1[BUFSIZE], sn2[BUFSIZE];
- s1 = (struct syment *)v1;
- s2 = (struct syment *)v2;
- if (s1->value == s2->value) {
- if (STRNEQ(s1->name, "__insmod"))
- return -1;
- if (STRNEQ(s2->name, "__insmod"))
- return 1;
- if (STRNEQ(s2->name, "_MODULE_START_"))
- return 1;
- /* Get pseudo section name. */
- if (MODULE_SECTION_START(s1))
- sscanf(s1->name, "_MODULE_SECTION_START [%s]", sn1);
- else if (MODULE_SECTION_END(s1))
- sscanf(s1->name, "_MODULE_SECTION_END [%s]", sn1);
- if (MODULE_SECTION_START(s2))
- sscanf(s2->name, "_MODULE_SECTION_START [%s]", sn2);
- else if (MODULE_SECTION_END(s2))
- sscanf(s2->name, "_MODULE_SECTION_END [%s]", sn2);
- /*
- * Sort pseudo symbols in mind section.
- * The same values must be sorted like examples.
- * - exp1
- * c9046000 MODULE START: sctp
- * c9046000 [.data]: section start
- * c9046000 (D) sctp_timer_events
- *
- * - exp2
- * c9046c68 [.bss]: section end
- * c9046c68 MODULE END: sctp
- *
- * - exp3
- * c90e9b44 [.text]: section end
- * c90e9b44 [.exit.text]: section start
- * c90e9b44 (T) cleanup_module
- * c90e9b44 (t) sctp_exit
- * c90e9c81 [.exit.text]: section end
- */
- if (MODULE_SECTION_END(s1)) {
- if (!MODULE_PSEUDO_SYMBOL(s2) || MODULE_END(s2))
- return -1;
- else if (MODULE_SECTION_START(s2) && !STREQ(sn1, sn2))
- return -1;
- return 1;
- }
- if (MODULE_SECTION_END(s2)) {
- if (MODULE_END(s1) || !MODULE_PSEUDO_SYMBOL(s1))
- return 1;
- else if (MODULE_SECTION_START(s1) && STREQ(sn1, sn2))
- return 1;
- return -1;
- }
- if (MODULE_SECTION_START(s2)) {
- if (MODULE_START(s1))
- return -1;
- return 1;
- }
- }
- return (s1->value < s2->value ? -1 :
- s1->value == s2->value ? 0 : 1);
- }
- static int
- compare_mods(const void *v1, const void *v2)
- {
- struct load_module *lm1, *lm2;
- lm1 = (struct load_module *)v1;
- lm2 = (struct load_module *)v2;
- return (lm1->mod_base < lm2->mod_base ? -1 :
- lm1->mod_base == lm2->mod_base ? 0 : 1);
- }
- /*
- * Check whether a value falls into a text-type (SEC_CODE) section.
- * If it's a module address, and symbols are not loaded, we're forced
- * to use our "mod_etext_guess" value.
- */
- int
- is_kernel_text(ulong value)
- {
- int i, s;
- asection **sec, *section;
- struct load_module *lm;
- ulong start, end;
- struct syment *sp;
- start = 0;
- if (pc->flags & SYSMAP) {
- if ((sp = value_search(value, NULL)) &&
- ((sp->type == 'T') || (sp->type == 't')))
- return TRUE;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (!((sp->type == 'T') || (sp->type == 't')))
- continue;
- if ((value >= sp->value) && (value < kt->etext))
- return TRUE;
- break;
- }
- } else {
- sec = (asection **)st->sections;
- for (i = 0; i < st->bfd->section_count; i++, sec++) {
- section = *sec;
- if (section->flags & SEC_CODE) {
- start = (ulong)bfd_get_section_vma(st->bfd,
- section);
- end = start + (ulong)bfd_section_size(st->bfd,
- section);
-
- if ((value >= start) && (value < end))
- return TRUE;
- }
- }
- }
- if ((sp = value_search(value, NULL)) &&
- ((sp->type == 'T') || (sp->type == 't')))
- return TRUE;
- if (NO_MODULES())
- return FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!IN_MODULE(value, lm) && !IN_MODULE_INIT(value, lm))
- continue;
- if (lm->mod_flags & MOD_LOAD_SYMS) {
- for (s = (lm->mod_sections-1); s >= 0; s--) {
- if (!(lm->mod_section_data[s].flags & SEC_CODE))
- continue;
-
- start = lm->mod_base +
- lm->mod_section_data[s].offset;
- end = start + lm->mod_section_data[s].size;
-
- if ((value >= start) && (value < end))
- return TRUE;
- }
- } else {
- switch (kt->flags & (KMOD_V1|KMOD_V2))
- {
- case KMOD_V1:
- start = lm->mod_base + lm->mod_size_of_struct;
- break;
- case KMOD_V2:
- if (IN_MODULE(value, lm))
- start = lm->mod_base;
- else
- start = lm->mod_init_module_ptr;
- break;
- }
- end = lm->mod_etext_guess;
- if (IN_MODULE_INIT(value, lm) && end < lm->mod_init_module_ptr + lm->mod_init_size)
- end = lm->mod_init_module_ptr + lm->mod_init_size;
- if ((value >= start) && (value < end))
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * Detemine whether an address is offset into a text function, i.e., not
- * the starting address of the function.
- */
- int
- is_kernel_text_offset(ulong value)
- {
- struct syment *sp;
- ulong offset;
- if (!is_kernel_text(value))
- return FALSE;
- if (!(sp = value_search(value, &offset)))
- return FALSE;
- return(offset ? TRUE : FALSE);
- }
- /*
- * Check whether an address is most likely kernel data.
- *
- * TBD: This should be refined to recognize module text/data.
- */
- int
- is_kernel_data(ulong value)
- {
- return(IS_KVADDR(value) &&
- !is_kernel_text(value) && !IS_MODULE_VADDR(value));
- }
- /*
- * Check whether the closest symbol to a value is rodata.
- */
- int
- is_rodata(ulong value, struct syment **spp)
- {
- struct syment *sp;
- if (!(sp = value_search(value, NULL)))
- return FALSE;
- if ((sp->type == 'r') || (sp->type == 'R')) {
- if (spp)
- *spp = sp;
- return TRUE;
- }
- return FALSE;
- }
- /*
- * "help -s" output
- */
- void
- dump_symbol_table(void)
- {
- int i, s, cnt, tot;
- struct load_module *lm;
- struct syment *sp;
- int others;
- asection **sec;
- fprintf(fp, " flags: %lx%s(", st->flags,
- count_bits_long(st->flags) > 3 ? "\n " : " ");
- others = 0;
- if (st->flags & KERNEL_SYMS)
- fprintf(fp, "%sKERNEL_SYMS", others++ ? "|" : "");
- if (st->flags & MODULE_SYMS)
- fprintf(fp, "%sMODULE_SYMS", others++ ? "|" : "");
- if (st->flags & LOAD_MODULE_SYMS)
- fprintf(fp, "%sLOAD_MODULE_SYMS",
- others++ ? "|" : "");
- if (st->flags & INSMOD_BUILTIN)
- fprintf(fp, "%sINSMOD_BUILTIN", others++ ? "|" : "");
- if (st->flags & GDB_SYMS_PATCHED)
- fprintf(fp, "%sGDB_SYMS_PATCHED", others++ ? "|" : "");
- if (st->flags & NO_SEC_LOAD)
- fprintf(fp, "%sNO_SEC_LOAD", others++ ? "|" : "");
- if (st->flags & NO_SEC_CONTENTS)
- fprintf(fp, "%sNO_SEC_CONTENTS", others++ ? "|" : "");
- if (st->flags & FORCE_DEBUGINFO)
- fprintf(fp, "%sFORCE_DEBUGINFO", others++ ? "|" : "");
- if (st->flags & CRC_MATCHES)
- fprintf(fp, "%sCRC_MATCHES", others++ ? "|" : "");
- if (st->flags & ADD_SYMBOL_FILE)
- fprintf(fp, "%sADD_SYMBOL_FILE", others++ ? "|" : "");
- if (st->flags & USE_OLD_ADD_SYM)
- fprintf(fp, "%sUSE_OLD_ADD_SYM", others++ ? "|" : "");
- if (st->flags & PERCPU_SYMS)
- fprintf(fp, "%sPERCPU_SYMS", others++ ? "|" : "");
- if (st->flags & MODSECT_V1)
- fprintf(fp, "%sMODSECT_V1", others++ ? "|" : "");
- if (st->flags & MODSECT_V2)
- fprintf(fp, "%sMODSECT_V2", others++ ? "|" : "");
- if (st->flags & MODSECT_V3)
- fprintf(fp, "%sMODSECT_V3", others++ ? "|" : "");
- if (st->flags & MODSECT_UNKNOWN)
- fprintf(fp, "%sMODSECT_UNKNOWN", others++ ? "|" : "");
- if (st->flags & NO_STRIP)
- fprintf(fp, "%sNO_STRIP", others++ ? "|" : "");
- fprintf(fp, ")\n");
- fprintf(fp, " bfd: %lx\n", (ulong)st->bfd);
- fprintf(fp, " symtable: %lx\n", (ulong)st->symtable);
- fprintf(fp, " symend: %lx\n", (ulong)st->symend);
- fprintf(fp, " symcnt: %ld\n", st->symcnt);
- fprintf(fp, " syment_size: %ld\n", st->syment_size);
- fprintf(fp, " first_ksymbol: ");
- if (st->first_ksymbol) {
- fprintf(fp, "%lx (%s)\n",
- st->first_ksymbol,
- st->flags & KERNEL_SYMS ?
- value_symbol(st->first_ksymbol) : "");
- } else
- fprintf(fp, "(unused)\n");
- if (st->__per_cpu_start || st->__per_cpu_end) {
- fprintf(fp, " __per_cpu_start: %lx\n", st->__per_cpu_start);
- fprintf(fp, " __per_cpu_end: %lx\n", st->__per_cpu_end);
- } else {
- fprintf(fp, " __per_cpu_start: (unused)\n");
- fprintf(fp, " __per_cpu_end: (unused)\n");
- }
- fprintf(fp, " first_section_start: %lx\n", st->first_section_start);
- fprintf(fp, " last_section_end: %lx\n", st->last_section_end);
- fprintf(fp, " _stext_vmlinux: %lx ", st->_stext_vmlinux);
- if (st->_stext_vmlinux == UNINITIALIZED)
- fprintf(fp, "(UNINITIALIZED)\n");
- else if (st->_stext_vmlinux == 0)
- fprintf(fp, "(unused)\n");
- else
- fprintf(fp, "\n");
- fprintf(fp, " symval_hash[%d]: %lx\n", SYMVAL_HASH,
- (ulong)&st->symval_hash[0]);
- if (CRASHDEBUG(1)) {
- fprintf(fp, " ");
- for (i = 0; i < SYMVAL_HASH; i++) {
- fprintf(fp, " [%3d]: ", i);
-
- sp = st->symval_hash[i].val_hash_head;
- if (!sp) {
- fprintf(fp, " 0 ");
- } else {
- cnt = 1;
- while ((sp = sp->val_hash_next))
- cnt++;
-
- fprintf(fp, "%3d ", cnt);
- }
- if (i && (((i+1)%6)== 0))
- fprintf(fp, "\n ");
- }
- }
- fprintf(fp, "%s val_hash_searches: %.0f\n",
- CRASHDEBUG(1) ? "\n" : "", st->val_hash_searches);
- fprintf(fp, " val_hash_iterations: %.0f (avg: %.1f)\n",
- st->val_hash_iterations,
- st->val_hash_iterations/st->val_hash_searches);
- fprintf(fp, " symname_hash[%d]: %lx\n", SYMNAME_HASH,
- (ulong)&st->symname_hash[0]);
- if (CRASHDEBUG(1)) {
- fprintf(fp, " ");
- for (i = tot = 0; i < SYMNAME_HASH; i++) {
- fprintf(fp, "[%3d]: ", i);
- if ((sp = st->symname_hash[i]) == NULL)
- fprintf(fp, "%3d ", 0);
- else {
- cnt = 1;
- while (sp->name_hash_next) {
- cnt++;
- sp = sp->name_hash_next;
- }
- fprintf(fp, "%3d ", cnt);
- tot += cnt;
- }
- if (i && (((i+1) % 6) == 0))
- fprintf(fp, "\n ");
- }
- if (SYMNAME_HASH % 6)
- fprintf(fp, "\n");
- }
- fprintf(fp, " symbol_namespace: ");
- fprintf(fp, "address: %lx ", (ulong)st->kernel_namespace.address);
- fprintf(fp, "index: %ld ", st->kernel_namespace.index);
- fprintf(fp, "size: %ld ", (ulong)st->kernel_namespace.size);
- fprintf(fp, "cnt: %ld\n", st->kernel_namespace.cnt);
- fprintf(fp, " ext_module_symtable: %lx\n",
- (ulong)st->ext_module_symtable);
- fprintf(fp, " ext_module_symend: %lx\n",
- (ulong)st->ext_module_symend);
- fprintf(fp, " ext_module_symcnt: %ld\n",
- (ulong)st->ext_module_symcnt);
- fprintf(fp, "ext_module_namespace: ");
- fprintf(fp, "address: %lx ",
- (ulong)st->ext_module_namespace.address);
- fprintf(fp, "index: %ld ",
- st->ext_module_namespace.index);
- fprintf(fp, "size: %ld ",
- (ulong)st->ext_module_namespace.size);
- fprintf(fp, "cnt: %ld\n",
- st->ext_module_namespace.cnt);
- fprintf(fp, " mods_installed: %d\n", st->mods_installed);
- fprintf(fp, " current: %lx\n", (ulong)st->current);
- fprintf(fp, " load_modules: %lx\n", (ulong)st->load_modules);
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- others = 0;
- fprintf(fp, "\n mod_base: %lx\n", lm->mod_base);
- fprintf(fp, " module_struct: %lx\n", lm->module_struct);
- fprintf(fp, " mod_name: %s\n", lm->mod_name);
- fprintf(fp, " mod_size: %ld\n", lm->mod_size);
- fprintf(fp, " mod_namelist: %s\n", lm->mod_namelist);
- fprintf(fp, " mod_flags: %lx (", lm->mod_flags);
- if (lm->mod_flags & MOD_EXT_SYMS)
- fprintf(fp, "%sMOD_EXT_SYMS", others++ ? "|" : "");
- if (lm->mod_flags & MOD_LOAD_SYMS)
- fprintf(fp, "%sMOD_LOAD_SYMS", others++ ? "|" : "");
- if (lm->mod_flags & MOD_REMOTE)
- fprintf(fp, "%sMOD_REMOTE", others++ ? "|" : "");
- if (lm->mod_flags & MOD_KALLSYMS)
- fprintf(fp, "%sMOD_KALLSYMS", others++ ? "|" : "");
- if (lm->mod_flags & MOD_INITRD)
- fprintf(fp, "%sMOD_INITRD", others++ ? "|" : "");
- if (lm->mod_flags & MOD_NOPATCH)
- fprintf(fp, "%sMOD_NOPATCH", others++ ? "|" : "");
- if (lm->mod_flags & MOD_INIT)
- fprintf(fp, "%sMOD_INIT", others++ ? "|" : "");
- if (lm->mod_flags & MOD_DO_READNOW)
- fprintf(fp, "%sMOD_DO_READNOW", others++ ? "|" : "");
- fprintf(fp, ")\n");
- fprintf(fp, " mod_symtable: %lx\n",
- (ulong)lm->mod_symtable);
- fprintf(fp, " mod_symend: %lx\n",
- (ulong)lm->mod_symend);
- fprintf(fp, " mod_init_symtable: %lx\n",
- (ulong)lm->mod_init_symtable);
- fprintf(fp, " mod_init_symend: %lx\n",
- (ulong)lm->mod_init_symend);
- fprintf(fp, " mod_ext_symcnt: %ld\n",
- lm->mod_ext_symcnt);
- fprintf(fp, " mod_ext_symtable: %lx\n",
- (ulong)lm->mod_ext_symtable);
- fprintf(fp, " mod_ext_symend: %lx\n",
- (ulong)lm->mod_ext_symend);
- fprintf(fp, " mod_load_symcnt: %ld\n",
- lm->mod_load_symcnt);
- fprintf(fp, " mod_load_symtable: %lx\n",
- (ulong)lm->mod_load_symtable);
- fprintf(fp, " mod_load_symend: %lx\n",
- (ulong)lm->mod_load_symend);
- fprintf(fp, " mod_load_namespace: ");
- fprintf(fp, "address: %lx ",
- (ulong)lm->mod_load_namespace.address);
- fprintf(fp, "index: %ld ",
- lm->mod_load_namespace.index);
- fprintf(fp, "size: %ld ",
- (ulong)lm->mod_load_namespace.size);
- fprintf(fp, "cnt: %ld\n",
- lm->mod_load_namespace.cnt);
- fprintf(fp, " mod_symalloc: %ld\n", lm->mod_symalloc);
- fprintf(fp, " mod_size_of_struct: %ld (%lx)\n",
- lm->mod_size_of_struct, lm->mod_size_of_struct);
- fprintf(fp, " mod_text_start: %lx (%lx)\n",
- lm->mod_text_start,
- lm->mod_text_start ?
- lm->mod_text_start - lm->mod_base : 0);
- fprintf(fp, " mod_etext_guess: %lx (%lx)\n",
- lm->mod_etext_guess,
- lm->mod_etext_guess ?
- lm->mod_etext_guess - lm->mod_base : 0);
- fprintf(fp, " mod_rodata_start: %lx (%lx)\n",
- lm->mod_rodata_start,
- lm->mod_rodata_start ?
- lm->mod_rodata_start - lm->mod_base : 0);
- fprintf(fp, " mod_data_start: %lx (%lx)\n",
- lm->mod_data_start,
- lm->mod_data_start ?
- lm->mod_data_start - lm->mod_base : 0);
- fprintf(fp, " mod_bss_start: %lx (%lx)\n",
- lm->mod_bss_start,
- lm->mod_bss_start ?
- lm->mod_bss_start - lm->mod_base : 0);
- fprintf(fp, " mod_init_size: %ld\n",
- lm->mod_init_size);
- fprintf(fp, " mod_init_text_size: %ld\n",
- lm->mod_init_text_size);
- fprintf(fp, " mod_init_module_ptr: %lx\n",
- lm->mod_init_module_ptr);
- if (lm->mod_percpu_size) {
- fprintf(fp, " mod_percpu_size: %lx\n",
- lm->mod_percpu_size);
- fprintf(fp, " mod_percpu: %lx - %lx\n",
- lm->mod_percpu,
- lm->mod_percpu + lm->mod_percpu_size);
- } else {
- if (lm->mod_percpu) {
- fprintf(fp,
- " mod_percpu_size: (not loaded)\n");
- fprintf(fp,
- " mod_percpu: %lx - (unknown)\n",
- lm->mod_percpu);
- } else {
- fprintf(fp,
- " mod_percpu_size: (not used)\n");
- fprintf(fp,
- " mod_percpu: (not used)\n");
- }
- }
- fprintf(fp, " mod_sections: %d\n", lm->mod_sections);
- fprintf(fp, " mod_section_data: %lx %s\n",
- (ulong)lm->mod_section_data,
- lm->mod_section_data ? "" : "(not allocated)");
- for (s = 0; s < lm->mod_sections; s++) {
- fprintf(fp,
- " %12s prio: %x flags: %05x offset: %-8lx size: %lx\n",
- lm->mod_section_data[s].name,
- lm->mod_section_data[s].priority,
- lm->mod_section_data[s].flags,
- lm->mod_section_data[s].offset,
- lm->mod_section_data[s].size);
- }
- if (CRASHDEBUG(1)) {
- for (sp = lm->mod_load_symtable;
- sp < lm->mod_load_symend; sp++) {
- fprintf(fp, " %lx %s\n",
- sp->value, sp->name);
- }
- }
- }
- fprintf(fp, "\n");
- fprintf(fp, " dwarf_eh_frame_file_offset: %llx\n",
- (unsigned long long)st->dwarf_eh_frame_file_offset);
- fprintf(fp, " dwarf_eh_frame_size: %ld\n", st->dwarf_eh_frame_size);
- fprintf(fp, "dwarf_debug_frame_file_offset: %llx\n",
- (unsigned long long)st->dwarf_debug_frame_file_offset);
- fprintf(fp, " dwarf_debug_frame_size: %ld\n", st->dwarf_debug_frame_size);
- fprintf(fp, "\n");
- sec = (asection **)st->sections;
- fprintf(fp, " sections: %s\n", sec ? "" : "(not in use)");
- for (i = 0; sec && (i < st->bfd->section_count); i++, sec++) {
- asection *section;
- section = *sec;
- fprintf(fp, "%25s vma: %.*lx size: %ld\n",
- section->name, VADDR_PRLEN,
- (ulong)bfd_get_section_vma(st->bfd, section),
- (ulong)bfd_section_size(st->bfd, section));
- }
- }
- /*
- * Determine whether a file is in ELF format by checking the magic number
- * in the first EI_NIDENT characters of the file; if those match, check
- * whether the file is a known BFD format.
- */
- int
- is_elf_file(char *s)
- {
- int fd;
- char magic[EI_NIDENT];
- if ((fd = open(s, O_RDONLY)) < 0) {
- error(INFO, "%s: %s\n", s, strerror(errno));
- return FALSE;
- }
- if (read(fd, magic, EI_NIDENT) != EI_NIDENT) {
- /* error(INFO, "%s: %s\n", s, strerror(errno)); */
- close(fd);
- return FALSE;
- }
- close(fd);
- magic[EI_CLASS] = NULLCHAR;
- if (!STREQ(magic, ELFMAG))
- return FALSE;
- return(is_bfd_format(s));
- }
- /*
- * Verify a vmlinux file, issuing a warning for processor and endianness
- * mismatches.
- */
- int
- is_kernel(char *file)
- {
- int fd, swap;
- char eheader[BUFSIZE];
- Elf32_Ehdr *elf32;
- Elf64_Ehdr *elf64;
- if ((fd = open(file, O_RDONLY)) < 0) {
- error(INFO, "%s: %s\n", file, strerror(errno));
- return FALSE;
- }
- if (read(fd, eheader, BUFSIZE) != BUFSIZE) {
- /* error(INFO, "%s: %s\n", file, strerror(errno)); */
- close(fd);
- return FALSE;
- }
- close(fd);
- if (!STRNEQ(eheader, ELFMAG) || eheader[EI_VERSION] != EV_CURRENT)
- return FALSE;
- elf32 = (Elf32_Ehdr *)&eheader[0];
- elf64 = (Elf64_Ehdr *)&eheader[0];
- swap = (((eheader[EI_DATA] == ELFDATA2LSB) &&
- (__BYTE_ORDER == __BIG_ENDIAN)) ||
- ((eheader[EI_DATA] == ELFDATA2MSB) &&
- (__BYTE_ORDER == __LITTLE_ENDIAN)));
- if ((elf32->e_ident[EI_CLASS] == ELFCLASS32) &&
- (swap16(elf32->e_type, swap) == ET_EXEC) &&
- (swap32(elf32->e_version, swap) == EV_CURRENT)) {
- switch (swap16(elf32->e_machine, swap))
- {
- case EM_386:
- if (machine_type_mismatch(file, "X86", NULL, 0)) {
- if (machine_type("X86_64")) {
- /*
- * Since is_bfd_format() returns TRUE
- * in this case, just bail out here.
- */
- return FALSE;
- }
- goto bailout;
- }
- break;
- case EM_S390:
- if (machine_type_mismatch(file, "S390", NULL, 0))
- goto bailout;
- break;
- case EM_ARM:
- if (machine_type_mismatch(file, "ARM", NULL, 0))
- goto bailout;
- break;
- case EM_PPC:
- if (machine_type_mismatch(file, "PPC", NULL, 0))
- goto bailout;
- break;
- default:
- if (machine_type_mismatch(file, "(unknown)", NULL, 0))
- goto bailout;
- }
- if (endian_mismatch(file, elf32->e_ident[EI_DATA], 0))
- goto bailout;
- } else if ((elf64->e_ident[EI_CLASS] == ELFCLASS64) &&
- ((swap16(elf64->e_type, swap) == ET_EXEC) ||
- (swap16(elf64->e_type, swap) == ET_DYN)) &&
- (swap32(elf64->e_version, swap) == EV_CURRENT)) {
- switch (swap16(elf64->e_machine, swap))
- {
- case EM_IA_64:
- if (machine_type_mismatch(file, "IA64", NULL, 0))
- goto bailout;
- break;
- case EM_PPC64:
- if (machine_type_mismatch(file, "PPC64", NULL, 0))
- goto bailout;
- break;
- case EM_X86_64:
- if (machine_type_mismatch(file, "X86_64", NULL, 0))
- goto bailout;
- break;
- case EM_386:
- if (machine_type_mismatch(file, "X86", NULL, 0))
- goto bailout;
- break;
- case EM_S390:
- if (machine_type_mismatch(file, "S390X", NULL, 0))
- goto bailout;
- break;
- case EM_AARCH64:
- if (machine_type_mismatch(file, "ARM64", NULL, 0))
- goto bailout;
- break;
- default:
- if (machine_type_mismatch(file, "(unknown)", NULL, 0))
- goto bailout;
- }
- if (endian_mismatch(file, elf64->e_ident[EI_DATA], 0))
- goto bailout;
- }
- bailout:
- return(is_bfd_format(file));
- }
- int
- is_compressed_kernel(char *file, char **tmp)
- {
- int len, type, fd;
- char *tmpdir, *tempname;
- unsigned char header[BUFSIZE];
- char command[BUFSIZE];
- char message[BUFSIZE];
- #define GZIP (1)
- #define BZIP2 (2)
- #define FNAME (1 << 3)
- if ((fd = open(file, O_RDONLY)) < 0)
- return FALSE;
- if (read(fd, header, BUFSIZE) != BUFSIZE) {
- close(fd);
- return FALSE;
- }
- close(fd);
- type = 0;
- if ((header[0] == 0x1f) && (header[1] == 0x8b) && (header[2] == 8)) {
- if (!(header[3] & FNAME)) {
- if (!(st->flags & FORCE_DEBUGINFO)) {
- error(INFO, "%s: "
- "original filename unknown\n",
- file);
- error(CONT,
- "Use \"-f %s\" on command line to prevent this message.\n\n",
- file);
- }
- } else if (!STRNEQ((char *)&header[10], "vmlinux") &&
- !(st->flags & FORCE_DEBUGINFO)) {
- error(INFO, "%s: compressed file name does not "
- "start with \"vmlinux\"\n", &header[10]);
- error(CONT,
- "Use \"-f %s\" on command line to override.\n\n",
- file);
- return FALSE;
- }
- type = GZIP;
- }
- if ((header[0] == 'B') && (header[1] == 'Z') && (header[2] == 'h')) {
- if (!STRNEQ(basename(file), "vmlinux") &&
- !(st->flags & FORCE_DEBUGINFO)) {
- error(INFO, "%s: compressed file name does not start "
- "with \"vmlinux\"\n", file);
- error(CONT,
- "Use \"-f %s\" on command line to override.\n\n",
- file);
- return FALSE;
- }
- type = BZIP2;
- }
- if (!type)
- return FALSE;
- if (!(tmpdir = getenv("TMPDIR")))
- tmpdir = "/var/tmp";
- len = strlen(tmpdir) + strlen(basename(file)) +
- strlen("_XXXXXX") + 2;
- if (!(tempname = (char *)malloc(len)))
- return FALSE;
- sprintf(tempname, "%s/%s_XXXXXX", tmpdir, basename(file));
- fd = mkstemp(tempname);
- if (fd < 0) {
- perror("mkstemp");
- free(tempname);
- return FALSE;
- }
- pc->cleanup = tempname;
- sprintf(message, "uncompressing %s", file);
- please_wait(message);
- switch (type)
- {
- case GZIP:
- sprintf(command, "%s -c %s > %s",
- file_exists("/bin/gunzip", NULL) ?
- "/bin/gunzip" : "/usr/bin/gunzip",
- file, tempname);
- break;
- case BZIP2:
- sprintf(command, "%s -c %s > %s",
- file_exists("/bin/bunzip2", NULL) ?
- "/bin/bunzip2" : "/usr/bin/bunzip2",
- file, tempname);
- break;
- }
- if (system(command) < 0) {
- please_wait_done();
- error(INFO, "%s of %s failed\n",
- type == GZIP ? "gunzip" : "bunzip2", file);
- free(tempname);
- return FALSE;
- }
- please_wait_done();
- if (is_bfd_format(tempname) && is_kernel(tempname)) {
- *tmp = tempname;
- return TRUE;
- }
- unlink(tempname);
- close(fd);
- free(tempname);
- pc->cleanup = NULL;
- return FALSE;
- }
- int
- is_shared_object(char *file)
- {
- int fd, swap;
- char eheader[BUFSIZE];
- Elf32_Ehdr *elf32;
- Elf64_Ehdr *elf64;
- if (is_directory(file))
- return FALSE;
- if ((fd = open(file, O_RDONLY)) < 0)
- return FALSE;
- if (read(fd, eheader, BUFSIZE) != BUFSIZE) {
- close(fd);
- return FALSE;
- }
- close(fd);
- if (!STRNEQ(eheader, ELFMAG) || eheader[EI_VERSION] != EV_CURRENT)
- return FALSE;
- elf32 = (Elf32_Ehdr *)&eheader[0];
- elf64 = (Elf64_Ehdr *)&eheader[0];
- swap = (((eheader[EI_DATA] == ELFDATA2LSB) &&
- (__BYTE_ORDER == __BIG_ENDIAN)) ||
- ((eheader[EI_DATA] == ELFDATA2MSB) &&
- (__BYTE_ORDER == __LITTLE_ENDIAN)));
- if ((elf32->e_ident[EI_CLASS] == ELFCLASS32) &&
- (swap16(elf32->e_type, swap) == ET_DYN)) {
- switch (swap16(elf32->e_machine, swap))
- {
- case EM_386:
- if (machine_type("X86") || machine_type("ARM"))
- return TRUE;
- break;
- case EM_S390:
- if (machine_type("S390"))
- return TRUE;
- break;
- case EM_ARM:
- if (machine_type("ARM"))
- return TRUE;
- break;
- case EM_PPC:
- if (machine_type("PPC"))
- return TRUE;
- break;
- }
- if (CRASHDEBUG(1))
- error(INFO, "%s: machine type mismatch: %d\n",
- file, swap16(elf32->e_machine, swap));
- return FALSE;
- } else if ((elf64->e_ident[EI_CLASS] == ELFCLASS64) &&
- (swap16(elf64->e_type, swap) == ET_DYN)) {
- switch (swap16(elf64->e_machine, swap))
- {
- case EM_IA_64:
- if (machine_type("IA64"))
- return TRUE;
- break;
- case EM_PPC64:
- if (machine_type("PPC64"))
- return TRUE;
- break;
- case EM_X86_64:
- if (machine_type("X86_64") || machine_type("ARM64"))
- return TRUE;
- break;
- case EM_S390:
- if (machine_type("S390X"))
- return TRUE;
- break;
- case EM_AARCH64:
- if (machine_type("ARM64"))
- return TRUE;
- break;
- }
- if (CRASHDEBUG(1))
- error(INFO, "%s: machine type mismatch: %d\n",
- file, swap16(elf32->e_machine, swap));
- }
- return FALSE;
- }
- /*
- * Given a choice between two namelists, pick the one for gdb to use.
- * For now, just check get their stats and check their sizes; the larger
- * one presumably has debug data.
- */
- int
- select_namelist(char *new)
- {
- struct stat stat1, stat2;
- char *namep;
- if (pc->server_namelist) {
- pc->namelist_debug = new;
- return TRUE;
- }
- if (!file_exists(pc->namelist, &stat1) ||
- !file_exists(new, &stat2)) {
- return FALSE;
- }
- if (stat1.st_size > stat2.st_size) {
- pc->namelist_debug = pc->namelist;
- if (pc->namelist_orig) {
- namep = pc->namelist_debug_orig;
- pc->namelist_debug_orig = pc->namelist_orig;
- pc->namelist_orig = namep;
- }
- pc->namelist = new;
- } else if (stat2.st_size > stat1.st_size)
- pc->namelist_debug = new;
- else {
- error(INFO, "cannot distinguish %s and %s\n",
- pc->namelist, new);
- return FALSE;
- }
- return TRUE;
- }
- /*
- * Make a sweep of a non-dump, non-ELF file to guess whether it's a
- * legitimate System.map file.
- */
- int
- is_system_map(char *s)
- {
- int i, lines, retval;
- char *mapitems[MAXARGS];
- char buf[16384];
- FILE *map;
- /*
- * First simulate what "file" does by verifying that the first 16K
- * bytes are ascii data.
- */
- if ((map = fopen(s, "r")) == NULL) {
- error(INFO, "cannot open %s\n", s);
- return FALSE;
- }
- retval = FALSE;
- if (fread(buf, sizeof(char), 16384, map) != (16384*sizeof(char))) {
- if (CRASHDEBUG(1))
- error(INFO, "%s: cannot read 16K\n", s);
- goto not_system_map;
- }
- for (i = 0; i < 16384; i++) {
- if (!ascii(buf[i]))
- goto not_system_map;
- }
- rewind(map);
- for (lines = 0; lines < 100; lines++) {
- if (!fgets(buf, BUFSIZE, map))
- goto not_system_map;
- if (parse_line(buf, mapitems) != 3)
- goto not_system_map;
- if ((strlen(mapitems[0]) > MAX_HEXADDR_STRLEN) ||
- !hexadecimal(mapitems[0], 0) || (strlen(mapitems[1]) > 1))
- goto not_system_map;
- }
- if ((pc->flags & SYSMAP) && !same_file("/boot/System.map", s))
- error(INFO, "overriding /boot/System.map with %s\n", s);
- retval = TRUE;
- not_system_map:
- fclose(map);
- return retval;
- }
- /*
- * Check whether a file is a known BFD format.
- */
- static int
- is_bfd_format(char *filename)
- {
- #ifdef GDB_5_3
- struct _bfd *bfd;
- #else
- struct bfd *bfd;
- #endif
- char **matching;
- if ((bfd = bfd_openr(filename, NULL)) == NULL)
- return FALSE;
-
- if (!bfd_check_format_matches(bfd, bfd_object, &matching)) {
- bfd_close(bfd);
- return FALSE;
- }
-
- bfd_close(bfd);
- return TRUE;
- }
- static int
- is_binary_stripped(char *filename)
- {
- #ifdef GDB_5_3
- struct _bfd *bfd;
- #else
- struct bfd *bfd;
- #endif
- int number_of_symbols;
- if ((bfd = bfd_openr(filename, NULL)) == NULL) {
- error(INFO, "cannot open ELF file: %s\n", filename);
- return FALSE;
- }
- if (!bfd_check_format(bfd, bfd_object)) {
- error(INFO, "invalid ELF file: %s\n", filename);
- bfd_close(bfd);
- return FALSE;
- }
- number_of_symbols = bfd_canonicalize_symtab(bfd, NULL);
- bfd_close(bfd);
-
- return (number_of_symbols == 0);
- }
- /*
- * This command may be used to:
- *
- * 1. Translate a symbol to its value.
- * 2. Translate a value to it symbol.
- * 3. List all stored symbols.
- * 4. Query for symbols containing a string.
- * 5. Show the next and previous symbols.
- */
- void
- cmd_sym(void)
- {
- int c;
- struct syment *sp, *spp, *spn;
- ulong value, show_flags;
- ulong offset;
- int next, prev, multiples, others;
- char *name;
- int errflag;
- char buf[BUFSIZE];
- next = prev = others = 0;
- show_flags = SHOW_LINENUM | SHOW_RADIX();
- while ((c = getopt(argcnt, args, "lLQ:q:npsMm:")) != EOF) {
- switch(c)
- {
- case 'n':
- next++;
- break;
- case 'p':
- prev++;
- break;
- case 'Q':
- fprintf(fp, "%d found ",
- symbol_query(optarg, NULL, &sp));
- if (sp)
- fprintf(fp, "(%s)", sp->name);
- fprintf(fp, "\n");
- others++;
- break;
-
- case 'q':
- if (!symbol_query(optarg, "", NULL))
- fprintf(fp, "(none found)\n");
- others++;
- break;
- case 'm':
- symbol_dump(MODULE_SYMS, optarg);
- others++;
- break;
- case 'M':
- symbol_dump(MODULE_SYMS, NULL);
- others++;
- break;
- case 'L': /* obsolete */
- case 'l':
- symbol_dump(KERNEL_SYMS|MODULE_SYMS, NULL);
- others++;
- break;
- case 's':
- show_flags &= ~SHOW_LINENUM;
- show_flags |= SHOW_SECTION;
- break;
- default:
- argerrs++;
- break;
- }
- }
- if (argerrs)
- cmd_usage(pc->curcmd, SYNOPSIS);
- if (args[optind]) {
- do {
- name = NULL;
- multiples = 0;
- sp = NULL;
- show_flags &= ~SHOW_MODULE;
- if (clean_arg() && hexadecimal(args[optind], 0)) {
- errflag = 0;
- value = htol(args[optind], RETURN_ON_ERROR,
- &errflag);
- if (errflag || !in_ksymbol_range(value)) {
- error(INFO, "invalid address: %s\n",
- args[optind]);
- } else if ((sp = value_search(value, &offset))){
- name = sp->name;
- if (module_symbol(sp->value, NULL, NULL,
- NULL, 0))
- show_flags |= SHOW_MODULE;
- if (prev &&
- (spp = prev_symbol(NULL, sp)))
- show_symbol(spp, 0, show_flags);
- show_symbol(sp, offset, show_flags);
- }
- else if (module_symbol(value, &sp,
- NULL, buf, *gdb_output_radix)) {
- name = buf;
- if (prev && sp &&
- (spp = prev_symbol(NULL, sp)))
- show_symbol(spp, 0, show_flags);
-
- fprintf(fp, "%lx (?) %s\n",
- value, buf);
- } else
- fprintf(fp, "symbol not found: %s\n",
- args[optind]);
- } else {
- if ((sp = symbol_search(args[optind]))) {
- multiples = symbol_name_count(sp->name);
- do_multiples:
- if (module_symbol(sp->value, NULL, NULL,
- NULL, 0))
- show_flags |= SHOW_MODULE;
- name = sp->name;
- if (prev &&
- (spp = prev_symbol(NULL, sp)))
- show_symbol(spp, 0, show_flags);
-
- show_symbol(sp, 0, show_flags);
- }
- else {
- fprintf(fp, "symbol not found: %s\n",
- args[optind]);
- fprintf(fp, "possible alternatives:\n");
- if (!symbol_query(args[optind], " ",
- NULL))
- fprintf(fp, " (none found)\n");
- }
- }
- if (name && next && (spn = next_symbol(NULL, sp)))
- show_symbol(spn, 0, show_flags);
- if (multiples > 1) {
- if ((sp = symbol_search_next(name, sp)))
- goto do_multiples;
- }
- optind++;
- } while(args[optind]);
- }
- else if (!others)
- cmd_usage(pc->curcmd, SYNOPSIS);
- }
- /*
- * Common symbol display for cmd_sym().
- */
- void
- show_symbol(struct syment *sp, ulong offset, ulong show_flags)
- {
- char buf[BUFSIZE];
- char *p1;
- ulong radix;
- struct load_module *lm;
- lm = NULL;
- if (CRASHDEBUG(1))
- show_flags |= SHOW_LINENUM;
- switch (show_flags & (SHOW_HEX_OFFS|SHOW_DEC_OFFS))
- {
- case SHOW_DEC_OFFS:
- radix = 10;
- break;
- default:
- case SHOW_HEX_OFFS:
- radix = 16;
- break;
- }
- if (MODULE_START(sp)) {
- p1 = sp->name + strlen("_MODULE_START_");
- fprintf(fp, "%lx (%c) (%s module)", sp->value, sp->type, p1);
- if (offset)
- fprintf(fp, (radix == 16) ? "+0x%lx" : "+%ld",
- offset);
- fprintf(fp, "\n");
- return;
- } else if (show_flags & SHOW_MODULE)
- module_symbol(sp->value, NULL, &lm, NULL, 0);
- if (offset)
- fprintf(fp, (radix == 16) ?
- "%lx (%c) %s+0x%lx" : "%lx (%c) %s+%ld",
- sp->value+offset, sp->type, sp->name, offset);
- else
- fprintf(fp, "%lx (%c) %s", sp->value, sp->type, sp->name);
- if (lm)
- fprintf(fp, " [%s]", lm->mod_name);
- if (is_kernel_text(sp->value+offset) &&
- (show_flags & SHOW_LINENUM))
- fprintf(fp, " %s",
- get_line_number(sp->value+offset, buf, TRUE));
- if (show_flags & SHOW_SECTION)
- fprintf(fp, " [%s]", get_section(sp->value+offset, buf));
-
- fprintf(fp, "\n");
- }
- /*
- * Use the gdb_interface to get a line number associated with a
- * text address -- but first check whether the address gets past
- * any machine-dependent line_number_hooks reference.
- */
- char *
- get_line_number(ulong addr, char *buf, int reserved)
- {
- char *p;
- struct gnu_request request, *req;
- struct line_number_hook *lnh;
- struct syment *sp;
- char bldbuf[BUFSIZE], *name;
- struct load_module *lm;
- buf[0] = NULLCHAR;
- if (NO_LINE_NUMBERS() || !is_kernel_text(addr))
- return(buf);
- if (module_symbol(addr, NULL, &lm, NULL, 0)) {
- if (!(lm->mod_flags & MOD_LOAD_SYMS))
- return(buf);
- } else if (kt->flags2 & KASLR)
- addr -= (kt->relocate * -1);
- if ((lnh = machdep->line_number_hooks)) {
- name = closest_symbol(addr);
- while (lnh->func) {
- if (STREQ(name, lnh->func)) {
- sprintf(buf, "%s/%s",
- get_build_directory(bldbuf) ?
- bldbuf : "..", *(lnh->file));
- break;
- }
- lnh++;
- }
- }
- if (!strlen(buf)) {
- req = &request;
- BZERO(req, sizeof(struct gnu_request));
- req->command = GNU_GET_LINE_NUMBER;
- req->addr = addr;
- req->buf = buf;
- if ((sp = value_search(addr, NULL)))
- req->name = sp->name;
- gdb_interface(req);
- }
- while ((p = strstr(buf, "//")))
- shift_string_left(p+1, 1);
- return(buf);
- }
- static char *
- get_section(ulong vaddr, char *buf)
- {
- int i;
- asection **sec;
- asection *section;
- ulong start, end;
- struct load_module *lm;
- buf[0] = NULLCHAR;
- if (module_symbol(vaddr, NULL, &lm, NULL, *gdb_output_radix)) {
- if (lm->mod_flags & MOD_LOAD_SYMS) {
- for (i = (lm->mod_sections-1); i >= 0; i--) {
- start = lm->mod_base +
- lm->mod_section_data[i].offset;
- end = start + lm->mod_section_data[i].size;
- if ((vaddr >= start) && (vaddr < end)) {
- strcpy(buf,
- lm->mod_section_data[i].name);
- break;
- }
- }
- } else
- sprintf(buf, "in %s module", lm->mod_name);
- } else {
- sec = (asection **)st->sections;
- for (i = 0; i < st->bfd->section_count; i++, sec++) {
- section = *sec;
- start = (ulong)bfd_get_section_vma(st->bfd, section);
- end = start + (ulong)bfd_section_size(st->bfd, section);
-
- if ((vaddr >= start) && (vaddr < end)) {
- strcpy(buf, bfd_get_section_name(st->bfd,
- section));
- break;
- }
- }
- }
- return buf;
- }
- /*
- * Get the kernel build directory.
- */
- char *
- get_build_directory(char *buf)
- {
- char *p;
- if (symbol_exists("schedule"))
- get_line_number(symbol_value("schedule"), buf, FALSE);
- else if (symbol_exists("do_schedule"))
- get_line_number(symbol_value("do_schedule"), buf, FALSE);
- else
- return NULL;
- if ((p = strstr(buf, "/kernel/")))
- *p = NULLCHAR;
- else
- return(NULL);
- return buf;
- }
- /*
- * Search for all symbols containing a string.
- */
- int
- symbol_query(char *s, char *print_pad, struct syment **spp)
- {
- int i;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- int cnt, search_init;
- cnt = 0;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (strstr(sp->name, s)) {
- if (print_pad) {
- if (strlen(print_pad))
- fprintf(fp, "%s", print_pad);
- show_symbol(sp, 0, SHOW_RADIX());
- }
- if (spp)
- *spp = sp;
- cnt++;
- }
- }
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (MODULE_START(sp))
- continue;
- if (strstr(sp->name, s)) {
- if (print_pad) {
- if (strlen(print_pad))
- fprintf(fp, "%s", print_pad);
- show_symbol(sp, 0,
- SHOW_RADIX()|SHOW_MODULE);
- }
- if (spp)
- *spp = sp;
- cnt++;
- }
- }
- }
- if (!search_init)
- return(cnt);
-
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (MODULE_START(sp))
- continue;
- if (strstr(sp->name, s)) {
- if (print_pad) {
- if (strlen(print_pad))
- fprintf(fp, "%s", print_pad);
- show_symbol(sp, 0,
- SHOW_RADIX()|SHOW_MODULE);
- }
- if (spp)
- *spp = sp;
- cnt++;
- }
- }
- }
- return(cnt);
- }
- /*
- * Return the syment of a symbol.
- */
- struct syment *
- symbol_search(char *s)
- {
- int i;
- struct syment *sp_hashed, *sp, *sp_end;
- struct load_module *lm;
- int pseudos, search_init;
- sp_hashed = symname_hash_search(s);
- for (sp = sp_hashed ? sp_hashed : st->symtable; sp < st->symend; sp++) {
- if (STREQ(s, sp->name))
- return(sp);
- }
- pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_"));
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp <= sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (STREQ(s, sp->name))
- return(sp);
- }
- }
- if (!search_init)
- return((struct syment *)NULL);
- pseudos = (strstr(s, "_MODULE_INIT_START_") || strstr(s, "_MODULE_INIT_END_"));
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (STREQ(s, sp->name))
- return(sp);
- }
- }
- return((struct syment *)NULL);
- }
- /*
- * Count the number of instances of a symbol name.
- */
- static int
- symbol_name_count(char *s)
- {
- int i;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- int count, pseudos, search_init;
- count = 0;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (STREQ(s, sp->name)) {
- count = sp->cnt;
- break;
- }
- }
- pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_"));
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
-
- for ( ; sp < sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
-
- if (STREQ(s, sp->name))
- count++;
- }
- }
- if (!search_init)
- return(count);
- pseudos = (strstr(s, "_MODULE_INIT_START_") || strstr(s, "_MODULE_INIT_END_"));
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (STREQ(s, sp->name))
- count++;
- }
- }
- return(count);
- }
- /*
- * Return the syment of the next symbol with the same name of the input symbol.
- */
- struct syment *
- symbol_search_next(char *s, struct syment *spstart)
- {
- int i;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- int found_start;
- int pseudos, search_init;
- found_start = FALSE;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (sp == spstart) {
- found_start = TRUE;
- continue;
- } else if (!found_start)
- continue;
- if (strcmp(s, sp->name) == 0) {
- return(sp);
- }
- }
- pseudos = (strstr(s, "_MODULE_START_") || strstr(s, "_MODULE_END_"));
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == spstart) {
- found_start = TRUE;
- continue;
- } else if (!found_start)
- continue;
- if (STREQ(s, sp->name))
- return(sp);
- }
- }
- if (!search_init)
- return((struct syment *)NULL);
- pseudos = (strstr(s, "_MODULE_INIT_START_") || strstr(s, "_MODULE_INIT_END_"));
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (!pseudos && MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == spstart) {
- found_start = TRUE;
- continue;
- } else if (!found_start)
- continue;
- if (STREQ(s, sp->name))
- return(sp);
- }
- }
- return((struct syment *)NULL);
- }
- /*
- * Determine whether an address falls within the kernel's, or any module's,
- * address space.
- */
- int
- in_ksymbol_range(ulong value)
- {
- if ((value >= st->symtable[0].value) &&
- (value <= st->symtable[st->symcnt-1].value)) {
- if ((st->flags & PERCPU_SYMS) && (value < st->first_ksymbol))
- return FALSE;
- else
- return TRUE;
- }
- if (module_symbol(value, NULL, NULL, NULL, *gdb_output_radix))
- return TRUE;
- if (machdep->value_to_symbol(value, NULL))
- return TRUE;
- return FALSE;
- }
- /*
- * Determine whether an address falls within any module's address space.
- * If syment or load_module pointers are passed, send them back.
- * If a pointer to a name buffer is passed, stuff it with the particulars.
- */
- int
- module_symbol(ulong value,
- struct syment **spp,
- struct load_module **lmp,
- char *name,
- ulong radix)
- {
- int i;
- struct load_module *lm;
- struct syment *sp;
- char buf[BUFSIZE];
- ulong offs, offset;
- ulong base, end;
- if (NO_MODULES())
- return FALSE;
- if (!radix)
- radix = *gdb_output_radix;
- if ((radix != 10) && (radix != 16))
- radix = 16;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (IN_MODULE(value, lm)) {
- base = lm->mod_base;
- end = lm->mod_base + lm->mod_size;
- } else if (IN_MODULE_INIT(value, lm)) {
- base = lm->mod_init_module_ptr;
- end = lm->mod_init_module_ptr + lm->mod_init_size;
- } else if (IN_MODULE_PERCPU(value, lm)) {
- base = lm->mod_percpu;
- end = lm->mod_percpu + lm->mod_percpu_size;
- } else
- continue;
- if ((value >= base) && (value < end)) {
- if (lmp)
- *lmp = lm;
- if (name) {
- offs = value - base;
- if ((sp = value_search(value, &offset))) {
- if (offset)
- sprintf(buf, radix == 16 ?
- "%s+0x%lx" : "%s+%ld",
- sp->name, offset);
- else
- sprintf(buf, "%s", sp->name);
- strcpy(name, buf);
- if (spp)
- *spp = sp;
- return TRUE;
- }
- sprintf(name, "(%s module)", lm->mod_name);
- if (offs) {
- sprintf(buf, radix == 16 ?
- "+0x%lx" : "+%ld", offs);
- strcat(name, buf);
- }
- }
- return TRUE;
- }
- }
- return FALSE;
- }
- struct syment *
- value_search_module(ulong value, ulong *offset)
- {
- int i;
- struct syment *sp, *sp_end, *spnext, *splast;
- struct load_module *lm;
- int search_init_sections, search_init;
- search_init = FALSE;
- search_init_sections = 0;
- for (i = 0; i < st->mods_installed; i++) {
- if (st->load_modules[i].mod_flags & MOD_INIT)
- search_init_sections++;
- }
- retry:
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (search_init) {
- if (lm->mod_init_symtable) {
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- } else
- continue;
- } else {
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- }
- if (sp->value > value) /* invalid -- between modules */
- break;
- /*
- * splast will contain the last module symbol encountered.
- * Note: "__insmod_"-type symbols will be set in splast only
- * when they have unique values.
- */
- splast = NULL;
- for ( ; sp <= sp_end; sp++) {
- if (value == sp->value) {
- if (MODULE_END(sp) || MODULE_INIT_END(sp))
- break;
- if (MODULE_PSEUDO_SYMBOL(sp)) {
- spnext = sp + 1;
- if (MODULE_PSEUDO_SYMBOL(spnext))
- continue;
- if (spnext->value == value)
- sp = spnext;
- }
- if (is_insmod_builtin(lm, sp)) {
- spnext = sp+1;
- if ((spnext < sp_end) &&
- (value == spnext->value))
- sp = spnext;
- }
- if (sp->name[0] == '.') {
- spnext = sp+1;
- if (spnext->value == value)
- sp = spnext;
- }
- if (offset)
- *offset = 0;
- return((struct syment *)sp);
- }
- if (sp->value > value) {
- sp = splast ? splast : sp - 1;
- if (offset)
- *offset = value - sp->value;
- return(sp);
- }
- if (!MODULE_PSEUDO_SYMBOL(sp)) {
- if (is_insmod_builtin(lm, sp)) {
- if (!splast ||
- (sp->value > splast->value))
- splast = sp;
-
- } else
- splast = sp;
- }
- }
- }
- if (search_init_sections) {
- if (!search_init) {
- search_init = TRUE;
- goto retry;
- }
- }
- return((struct syment *)NULL);
- }
- /*
- * Return the syment of the symbol closest to the value, along with
- * the offset from the symbol value if requested.
- */
- struct syment *
- value_search(ulong value, ulong *offset)
- {
- struct syment *sp, *spnext;
- if (!in_ksymbol_range(value))
- return((struct syment *)NULL);
- if ((sp = machdep->value_to_symbol(value, offset)))
- return sp;
- if (IS_VMALLOC_ADDR(value))
- goto check_modules;
- if ((sp = symval_hash_search(value)) == NULL)
- sp = st->symtable;
-
- for ( ; sp < st->symend; sp++) {
- if (value == sp->value) {
- #if !defined(GDB_5_3) && !defined(GDB_6_0) && !defined(GDB_6_1)
- if (STRNEQ(sp->name, ".text.")) {
- spnext = sp+1;
- if (spnext->value == value)
- sp = spnext;
- }
- #endif
- if (offset)
- *offset = 0;
- /*
- * Avoid "SyS" and "compat_SyS" kernel syscall
- * aliases by returning the real symbol name,
- * which is the next symbol in the list.
- */
- if ((STRNEQ(sp->name, "SyS_") ||
- STRNEQ(sp->name, "compat_SyS_")) &&
- ((spnext = sp+1) < st->symend) &&
- (spnext->value == value))
- sp = spnext;
- return((struct syment *)sp);
- }
- if (sp->value > value) {
- if (offset)
- *offset = value - ((sp-1)->value);
- return((struct syment *)(sp-1));
- }
- }
- check_modules:
- sp = value_search_module(value, offset);
- return sp;
- }
- ulong
- highest_bss_symbol(void)
- {
- struct syment *sp;
- ulong highest = 0;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if ((sp->type == 'b') || (sp->type == 'B')) {
- if (sp->value > highest)
- highest = sp->value;
- }
- }
- return highest;
- }
- /*
- * Search for a value only within the base kernel's symbols,
- * also avoiding the machdep->value_to_symbol() call, which will
- * most likely be the prime consumer of this call.
- */
- struct syment *
- value_search_base_kernel(ulong value, ulong *offset)
- {
- struct syment *sp;
- if (value < st->symtable[0].value)
- return((struct syment *)NULL);
- if ((sp = symval_hash_search(value)) == NULL)
- sp = st->symtable;
-
- for ( ; sp < st->symend; sp++) {
- if (value == sp->value) {
- if (offset)
- *offset = 0;
- return((struct syment *)sp);
- }
- if (sp->value > value) {
- if (offset)
- *offset = value - ((sp-1)->value);
- return((struct syment *)(sp-1));
- }
- }
- /*
- * If we go off the end, just use the last symbol plus offset.
- */
- sp = st->symend;
- if (offset)
- *offset = value - ((sp-1)->value);
- return((struct syment *)(sp-1));
- }
- /*
- * Allow platforms to assign symbols to their own special values.
- */
- struct syment *
- generic_machdep_value_to_symbol(ulong value, ulong *offset)
- {
- return NULL;
- }
- /*
- * For a given value, format a string containing the nearest symbol name
- * plus the offset if appropriate. Display the offset in the specified
- * radix (10 or 16) -- if it's 0, set it to the current pc->output_radix.
- */
- char *
- value_to_symstr(ulong value, char *buf, ulong radix)
- {
- struct syment *sp;
- ulong offset;
- char *p1, locbuf[BUFSIZE];
- struct load_module *lm;
- sp = NULL;
- offset = 0;
- buf[0] = NULLCHAR;
- if (!radix)
- radix = *gdb_output_radix;
- if ((radix != 10) && (radix != 16))
- radix = 16;
- if ((sp = value_search(value, &offset))) {
- if (offset)
- sprintf(buf, radix == 16 ? "%s+0x%lx" : "%s+%ld",
- sp->name, offset);
- else
- sprintf(buf, "%s", sp->name);
- }
- if (module_symbol(value, NULL, NULL, locbuf, *gdb_output_radix)) {
- if (sp) {
- if (STRNEQ(locbuf, "_MODULE_START_"))
- shift_string_left(locbuf,
- strlen("_MODULE_START_"));
- if ((p1 = strstr(locbuf, "+")))
- *p1 = NULLCHAR;
- if (offset) {
- if (is_module_name(locbuf, NULL, &lm) &&
- (value < lm->mod_text_start))
- sprintf(buf, radix == 16 ?
- "(%s module)+0x%lx" :
- "(%s module)+%ld",
- locbuf, offset);
- else
- sprintf(buf, radix == 16 ?
- "%s+0x%lx" : "%s+%ld",
- locbuf, offset);
- } else {
- if (is_module_name(locbuf, NULL, &lm) &&
- (value < lm->mod_text_start))
- sprintf(buf, "(%s)", locbuf);
- else
- sprintf(buf, "%s", locbuf);
- }
- } else
- sprintf(buf, "%s", locbuf);
- }
- return(buf);
- }
- /*
- * For a given value, return the closest (lower-in-value) symbol name.
- */
- char *
- closest_symbol(ulong value)
- {
- struct syment *sp;
- if ((sp = value_search(value, NULL)))
- return(sp->name);
- else
- return(NULL);
- }
- /*
- * Same as above, but return the closest (lower-in-value) symbol value.
- */
- ulong
- closest_symbol_value(ulong value)
- {
- struct syment *sp;
- if ((sp = value_search(value, NULL)))
- return(sp->value);
- else
- return(0);
- }
- /*
- * For a given symbol, return a pointer to the next (higher) symbol's syment.
- * Either a symbol name or syment pointer may be passed as an argument.
- */
- struct syment *
- next_symbol(char *symbol, struct syment *sp_in)
- {
- int i;
- int found, search_init;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- char buf[BUFSIZE], *p1;
- if (!symbol && !sp_in)
- error(FATAL, "next_symbol: two NULL args!\n");
- if (sp_in) {
- found = FALSE;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (sp == sp_in)
- found = TRUE;
- else if (found) {
- if (sp->value > sp_in->value)
- return sp;
- }
- }
-
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
-
- for ( ; sp < sp_end; sp++) {
- if (MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == sp_in)
- found = TRUE;
- else if (found) {
- if ((sp->value == sp_in->value) &&
- is_insmod_builtin(lm, sp))
- continue;
- return sp;
- }
- }
- }
- for (i = 0; search_init && (i < st->mods_installed); i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
-
- for ( ; sp < sp_end; sp++) {
- if (MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == sp_in)
- found = TRUE;
- else if (found)
- return sp;
- }
- }
- return NULL;
- }
- /*
- * Deal with a few special cases...
- */
- if (strstr(symbol, " module)")) {
- sprintf(buf, "_MODULE_START_");
- strcat(buf, &symbol[1]);
- p1 = strstr(buf, " module)");
- *p1 = NULLCHAR;
- symbol = buf;
- }
- if (STREQ(symbol, "_end")) {
- if (!st->mods_installed)
- return NULL;
- lm = &st->load_modules[0];
- return lm->mod_symtable;
- }
- if ((sp = symbol_search(symbol))) {
- sp++;
- if (MODULE_END(sp)) {
- sp--;
- i = load_module_index(sp);
- if ((i+1) == st->mods_installed)
- return NULL;
- lm = &st->load_modules[i+1];
- sp = lm->mod_symtable;
- }
- return sp;
- }
- return NULL;
- }
- /*
- * For a given symbol, return a pointer to the previous (lower) symbol's syment.
- * Either a symbol name or syment pointer may be passed as an argument.
- */
- struct syment *
- prev_symbol(char *symbol, struct syment *sp_in)
- {
- int i, search_init;
- struct syment *sp, *sp_end, *sp_prev;
- char buf[BUFSIZE], *p1;
- struct load_module *lm;
- if (!symbol && !sp_in)
- error(FATAL, "prev_symbol: two NULL args!\n");
- if (sp_in) {
- sp_prev = NULL;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if (sp == sp_in)
- return sp_prev;
- sp_prev = sp;
- }
- search_init = FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_INIT)
- search_init = TRUE;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == sp_in)
- return sp_prev;
- if (is_insmod_builtin(lm, sp)) {
- if (sp->value > sp_prev->value)
- sp_prev = sp;
- } else
- sp_prev = sp;
- }
- }
- for (i = 0; search_init && (i < st->mods_installed); i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_symtable)
- continue;
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (MODULE_PSEUDO_SYMBOL(sp))
- continue;
- if (sp == sp_in)
- return sp_prev;
- sp_prev = sp;
- }
- }
- return NULL;
- }
- if (strstr(symbol, " module)")) {
- sprintf(buf, "_MODULE_START_");
- strcat(buf, &symbol[1]);
- p1 = strstr(buf, " module)");
- *p1 = NULLCHAR;
- symbol = buf;
- }
- if ((sp = symbol_search(symbol))) {
- if (sp == st->symtable)
- return((struct syment *)NULL);
- if (module_symbol(sp->value, NULL, NULL, NULL, 0)) {
- if (MODULE_START(sp)) {
- i = load_module_index(sp);
- if (i == 0)
- sp = symbol_search("_end");
- else {
- lm = &st->load_modules[i-1];
- sp = lm->mod_symend;
- sp--;
- }
- } else
- sp--;
- } else
- sp--;
- return sp;
- }
- return NULL;
- }
- /*
- * Read the specified amount of data from the given symbol's value.
- */
- void
- get_symbol_data(char *symbol, long size, void *local)
- {
- struct syment *sp;
- if ((sp = symbol_search(symbol)))
- readmem(sp->value, KVADDR, local,
- size, symbol, FAULT_ON_ERROR);
- else
- error(FATAL, "cannot resolve: \"%s\"\n", symbol);
- }
- /*
- * Same as above, but allow for failure.
- */
- int
- try_get_symbol_data(char *symbol, long size, void *local)
- {
- struct syment *sp;
- if ((sp = symbol_search(symbol)) &&
- readmem(sp->value, KVADDR, local,
- size, symbol, RETURN_ON_ERROR|QUIET))
- return TRUE;
- return FALSE;
- }
- /*
- * Return the value of a given symbol.
- */
- ulong
- symbol_value(char *symbol)
- {
- struct syment *sp;
- if (!(sp = symbol_search(symbol)))
- error(FATAL, "cannot resolve \"%s\"\n", symbol);
- return(sp->value);
- }
- /*
- * Return the value of a symbol from a specific module.
- */
- ulong
- symbol_value_module(char *symbol, char *module)
- {
- int i;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!STREQ(module, lm->mod_name))
- continue;
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name))
- return(sp->value);
- }
- if (lm->mod_init_symtable) {
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
-
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name))
- return(sp->value);
- }
- }
- }
- return 0;
- }
- /*
- * Return the symbol name of a given value, with no allowance for offsets.
- * Returns NULL on failure to allow for testing of a value.
- */
- char *
- value_symbol(ulong value)
- {
- struct syment *sp;
- ulong offset;
- if ((sp = value_search(value, &offset))) {
- if (offset)
- return NULL;
- else
- return sp->name;
- }
- return NULL;
- }
- /*
- * Determine whether a symbol exists.
- */
- int
- symbol_exists(char *symbol)
- {
- int i;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- if ((sp = symname_hash_search(symbol)))
- return TRUE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name))
- return(TRUE);
- }
- if (lm->mod_init_symtable) {
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
-
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name))
- return(TRUE);
- }
- }
- }
- return(FALSE);
- }
- /*
- * Determine whether a per-cpu symbol exists.
- * The old-style per-cpu symbol names were pre-pended with
- * "per_cpu__", whereas the new-style ones (as of 2.6.34)
- * are not. This function allows the symbol argument to
- * use either the old- or new-sytle format, and find either
- * type.
- */
- struct syment *
- per_cpu_symbol_search(char *symbol)
- {
- struct syment *sp;
- char old[BUFSIZE];
- char *new;
- if (STRNEQ(symbol, "per_cpu__")) {
- if ((sp = symbol_search(symbol)))
- return sp;
- new = symbol + strlen("per_cpu__");
- if ((sp = symbol_search(new))) {
- if ((sp->type == 'V') || (is_percpu_symbol(sp)))
- return sp;
- if ((sp->type == 'd') &&
- (st->__per_cpu_start == st->__per_cpu_end))
- return sp;
- }
- } else {
- if ((sp = symbol_search(symbol))) {
- if ((sp->type == 'V') || (is_percpu_symbol(sp)))
- return sp;
- }
- sprintf(old, "per_cpu__%s", symbol);
- if ((sp = symbol_search(old)))
- return sp;
- }
- if (CRASHDEBUG(1))
- error(INFO, "per_cpu_symbol_search(%s): NULL\n", symbol);
- return NULL;
- }
- /*
- * Determine whether a static kernel symbol exists.
- */
- int
- kernel_symbol_exists(char *symbol)
- {
- struct syment *sp;
- if ((sp = symname_hash_search(symbol)))
- return TRUE;
- else
- return FALSE;
- }
- /*
- * Similar to above, but return the syment of the kernel symbol.
- */
- struct syment *
- kernel_symbol_search(char *symbol)
- {
- return symname_hash_search(symbol);
- }
- /*
- * Return the number of instances of a symbol name along with pointers to
- * their syment structures.
- */
- int
- get_syment_array(char *symbol, struct syment **sp_array, int max)
- {
- int i, cnt;
- struct syment *sp, *sp_end;
- struct load_module *lm;
- cnt = 0;
- for (sp = st->symtable; sp < st->symend; sp++) {
- if ((*symbol == *(sp->name)) && STREQ(symbol, sp->name)) {
- if (!sp_array)
- return sp->cnt;
- if (max) {
- if (cnt == max) {
- error(INFO,
- "symbol count overflow (%s)\n",
- symbol);
- return cnt;
- } else
- sp_array[cnt] = sp;
- }
- if (sp->cnt == 1)
- return 1;
- cnt++;
- }
- }
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- sp = lm->mod_symtable;
- sp_end = lm->mod_symend;
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name)) {
- if (max && (cnt < max))
- sp_array[cnt] = sp;
- cnt++;
- }
- }
- if (lm->mod_init_symtable) {
- sp = lm->mod_init_symtable;
- sp_end = lm->mod_init_symend;
- for ( ; sp < sp_end; sp++) {
- if (STREQ(symbol, sp->name)) {
- if (max && (cnt < max))
- sp_array[cnt] = sp;
- cnt++;
- }
- }
- }
- }
- return cnt;
- }
- /*
- * Perform any datatype-related initializations here.
- */
- void
- datatype_init(void)
- {
- BNEG(&offset_table, sizeof(offset_table));
- BNEG(&size_table, sizeof(size_table));
- BZERO(&array_table, sizeof(array_table));
- }
- /*
- * This function is called through the following macros:
- *
- * #define STRUCT_SIZE(X) datatype_info((X), NULL, NULL)
- * #define UNION_SIZE(X) datatype_info((X), NULL, NULL)
- * #define DATATYPE_SIZE(X) datatype_info((X)->name, NULL, (X))
- * #define MEMBER_OFFSET(X,Y) datatype_info((X), (Y), NULL)
- * #define STRUCT_EXISTS(X) (datatype_info((X), NULL, NULL) >= 0)
- * #define MEMBER_EXISTS(X,Y) (datatype_info((X), (Y), NULL) >= 0)
- * #define MEMBER_SIZE(X,Y) datatype_info((X), (Y), MEMBER_SIZE_REQUEST)
- * #define MEMBER_TYPE(X,Y) datatype_info((X), (Y), MEMBER_TYPE_REQUEST)
- * #define ANON_MEMBER_OFFSET(X,Y) datatype_info((X), (Y), ANON_MEMBER_OFFSET_REQUEST)
- *
- * to determine structure or union sizes, or member offsets.
- */
- long
- datatype_info(char *name, char *member, struct datatype_member *dm)
- {
- struct gnu_request *req;
- long offset, size, member_size;
- int member_typecode;
- ulong type_found;
- char buf[BUFSIZE];
- if (dm == ANON_MEMBER_OFFSET_REQUEST)
- return anon_member_offset(name, member);
- strcpy(buf, name);
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- req->command = GNU_GET_DATATYPE;
- req->flags |= GNU_RETURN_ON_ERROR;
- req->name = buf;
- req->member = member;
- req->fp = pc->nullfp;
- gdb_interface(req);
- if (req->flags & GNU_COMMAND_FAILED) {
- FREEBUF(req);
- return -1;
- }
- if (!req->typecode) {
- sprintf(buf, "struct %s", name);
- gdb_interface(req);
- }
- if (!req->typecode) {
- sprintf(buf, "union %s", name);
- gdb_interface(req);
- }
- member_typecode = TYPE_CODE_UNDEF;
- member_size = 0;
- type_found = 0;
- if (CRASHDEBUG(2)) {
- if (req->typecode) {
- console("name: %s ", req->name);
- if (member)
- console("member: %s ", req->member);
- console("typecode: %d%s ", req->typecode,
- req->is_typedef ? " (TYPEDEF)" : "");
- console("length: %ld ", req->length);
- console("member_offset: %ld\n", req->member_offset);
- }
- else
- console("%s: unknown\n", name);
- }
- switch (req->typecode)
- {
- case TYPE_CODE_STRUCT:
- type_found = STRUCT_REQUEST;
- size = req->length;
- if (req->member_offset >= 0) {
- offset = req->member_offset/BITS_PER_BYTE;
- member_size = req->member_length;
- member_typecode = req->member_typecode;
- } else {
- offset = -1;
- member_size = 0;
- member_typecode = TYPE_CODE_UNDEF;
- }
- break;
- case TYPE_CODE_UNION:
- type_found = UNION_REQUEST;
- size = req->length;
- if (req->member_offset >= 0) {
- offset = req->member_offset/BITS_PER_BYTE;
- member_size = req->member_length;
- member_typecode = req->member_typecode;
- } else {
- offset = -1;
- member_size = 0;
- member_typecode = TYPE_CODE_UNDEF;
- }
- break;
- case TYPE_CODE_RANGE:
- case TYPE_CODE_INT:
- size = req->length;
- offset = 0;
- switch (size)
- {
- case SIZEOF_64BIT:
- type_found = INT64;
- break;
- case SIZEOF_32BIT:
- type_found = INT32;
- break;
- case SIZEOF_16BIT:
- type_found = INT16;
- break;
- case SIZEOF_8BIT:
- type_found = INT8;
- break;
- }
- break;
- case TYPE_CODE_PTR:
- size = req->length;
- offset = 0;
- type_found = POINTER;
- break;
- case TYPE_CODE_FUNC:
- size = req->length;
- offset = 0;
- type_found = FUNCTION;
- break;
- case TYPE_CODE_ARRAY:
- size = req->length;
- offset = 0;
- type_found = ARRAY;
- break;
- case TYPE_CODE_ENUM:
- size = req->length;
- offset = 0;
- type_found = ENUM;
- break;
- default:
- type_found = 0;
- size = -1;
- offset = -1;
- break;
- }
- FREEBUF(req);
- if (dm && (dm != MEMBER_SIZE_REQUEST) && (dm != MEMBER_TYPE_REQUEST) &&
- (dm != STRUCT_SIZE_REQUEST)) {
- dm->type = type_found;
- dm->size = size;
- dm->member_size = member_size;
- dm->member_typecode = member_typecode;
- dm->member_offset = offset;
- if (req->is_typedef) {
- dm->flags |= TYPEDEF;
- }
- if (req->tagname) {
- dm->tagname = req->tagname;
- dm->value = req->value;
- }
- }
- if (!type_found)
- return -1;
- if (dm == MEMBER_SIZE_REQUEST)
- return member_size;
- else if (dm == MEMBER_TYPE_REQUEST)
- return member_typecode;
- else if (dm == STRUCT_SIZE_REQUEST) {
- if ((req->typecode == TYPE_CODE_STRUCT) ||
- (req->typecode == TYPE_CODE_UNION) ||
- req->is_typedef)
- return size;
- else
- return -1;
- } else if (member) {
- if ((req->typecode == TYPE_CODE_STRUCT) ||
- (req->typecode == TYPE_CODE_UNION))
- return offset;
- else
- return -1;
- } else
- return size;
- }
- /*
- * Determine the offset of a member in an anonymous union
- * in a structure or union.
- */
- static long
- anon_member_offset(char *name, char *member)
- {
- char buf[BUFSIZE];
- ulong value;
- int type;
- value = -1;
- type = STRUCT_REQUEST;
- sprintf(buf, "printf \"%%p\", &((struct %s *)0x0)->%s", name, member);
- open_tmpfile2();
- retry:
- if (gdb_pass_through(buf, pc->tmpfile2, GNU_RETURN_ON_ERROR)) {
- rewind(pc->tmpfile2);
- if (fgets(buf, BUFSIZE, pc->tmpfile2)) {
- if (hexadecimal(buf, 0))
- value = htol(buf, RETURN_ON_ERROR|QUIET, NULL);
- else if (STRNEQ(buf, "(nil)"))
- value = 0;
- }
- }
- if ((value == -1) && (type == STRUCT_REQUEST)) {
- type = UNION_REQUEST;
- sprintf(buf, "printf \"%%p\", &((union %s *)0x0)->%s", name, member);
- rewind(pc->tmpfile2);
- goto retry;
- }
- close_tmpfile2();
- return value;
- }
- /*
- * Get the basic type info for a symbol. Let the caller pass in the
- * gnu_request structure to have access to the full response; in either
- * case, return the type code. The member field can be used for structures
- * with no type names, and if there, the member data will be filled in
- * as well.
- */
- int
- get_symbol_type(char *name, char *member, struct gnu_request *caller_req)
- {
- struct gnu_request *req;
- int typecode;
- if (!caller_req)
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- else {
- req = caller_req;
- BZERO(req, sizeof(struct gnu_request));
- }
- req->command = GNU_GET_SYMBOL_TYPE;
- req->name = name;
- req->member = member;
- req->flags = GNU_RETURN_ON_ERROR;
- req->fp = pc->nullfp;
- gdb_interface(req);
- if (req->flags & GNU_COMMAND_FAILED)
- typecode = TYPE_CODE_UNDEF;
- else if (member) {
- if (req->member_offset >= 0)
- typecode = req->member_typecode;
- else
- typecode = TYPE_CODE_UNDEF;
- } else
- typecode = req->typecode;
- if (!caller_req)
- FREEBUF(req);
- return(typecode);
- }
- int
- get_symbol_length(char *symbol)
- {
- struct gnu_request *req;
- int len;
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- if (get_symbol_type(symbol, NULL, req) == TYPE_CODE_UNDEF)
- error(FATAL, "cannot determine length of symbol: %s\n",
- symbol);
- len = (int)req->length;
- FREEBUF(req);
- return len;
- }
- /*
- * Initialize the caller's restore_radix, and if valid,
- * temporarily override the current output radix.
- */
- void
- set_temporary_radix(unsigned int radix, unsigned int *restore_radix)
- {
- *restore_radix = *gdb_output_radix;
- if ((radix == 10) || (radix == 16)) {
- *gdb_output_radix = radix; \
- *gdb_output_format = (*gdb_output_radix == 10) ? 0 : 'x';
- }
- }
- /*
- * Restore the output radix to the current/default value saved
- * by the caller.
- */
- void
- restore_current_radix(unsigned int restore_radix)
- {
- if ((restore_radix == 10) || (restore_radix == 16)) {
- *gdb_output_radix = restore_radix;
- *gdb_output_format = (*gdb_output_radix == 10) ? 0 : 'x';
- }
- }
- /*
- * Externally available routine to dump a structure at an address.
- */
- void
- dump_struct(char *s, ulong addr, unsigned radix)
- {
- unsigned restore_radix;
- long len;
- restore_radix = 0;
- if ((len = STRUCT_SIZE(s)) < 0)
- error(FATAL, "invalid structure name: %s\n", s);
- set_temporary_radix(radix, &restore_radix);
- print_struct(s, addr);
- restore_current_radix(restore_radix);
- }
- /*
- * Externally available routine to dump a structure member, given the
- * base structure address. The input string must be in struct.member format.
- */
- void
- dump_struct_member(char *s, ulong addr, unsigned radix)
- {
- struct datatype_member datatype_member, *dm;
- unsigned restore_radix;
- char *buf, *p1;
- restore_radix = 0;
- buf = GETBUF(strlen(s)+1);
- strcpy(buf, s);
- p1 = strstr(buf, ".");
- *p1 = NULLCHAR;
- p1++;
- dm = &datatype_member;
- dm->name = buf;
- dm->member = p1;
-
- if (!STRUCT_EXISTS(dm->name)) {
- FREEBUF(buf);
- error(FATAL, "invalid structure name: %s\n", dm->name);
- }
- if (!MEMBER_EXISTS(dm->name, dm->member)) {
- FREEBUF(buf);
- error(FATAL, "invalid structure member name: %s\n",
- dm->member);
- }
-
- set_temporary_radix(radix, &restore_radix);
-
- open_tmpfile();
- print_struct(dm->name, addr);
- parse_for_member(dm, PARSE_FOR_DATA);
- close_tmpfile();
-
- restore_current_radix(restore_radix);
- FREEBUF(buf);
- }
- /*
- * Externally available routine to dump a union at an address.
- */
- void
- dump_union(char *s, ulong addr, unsigned radix)
- {
- unsigned restore_radix;
- long len;
- restore_radix = 0;
- if ((len = UNION_SIZE(s)) < 0)
- error(FATAL, "invalid union name: %s\n", s);
- set_temporary_radix(radix, &restore_radix);
- print_union(s, addr);
- restore_current_radix(restore_radix);
- }
- /*
- * This command displays either a structure definition, or a formatted display
- * of the contents of a structure at a specified address. If no address is
- * specified, the structure size and the file in which the structure is defined
- * are also displayed. A structure member may be appended to the structure
- * name (in a "struct.member" format) in order to limit the scope of the data
- * displayed to that particular member. Structure data is shown in hexadecimal
- * format. The raw data in a structure may be dumped with the -r flag.
- */
- void
- cmd_struct(void)
- {
- cmd_datatype_common(STRUCT_REQUEST);
- }
- /*
- * This command displays either a union definition, or a formatted display
- * of the contents of a union at a specified address. If no address is
- * specified, the union size and the file in which the union is defined
- * are also displayed. A union member may be appended to the union
- * name (in a "union.member" format) in order to limit the scope of the data
- * displayed to that particular member. Structure data is shown in hexadecimal
- * format. The raw data in a union may be dumped with the -r flag.
- */
- void
- cmd_union(void)
- {
- cmd_datatype_common(UNION_REQUEST);
- }
- /*
- * After determining what type of data type follows the *, this routine
- * has the identical functionality as cmd_struct() or cmd_union().
- */
- void
- cmd_pointer(void)
- {
- cmd_datatype_common(0);
- }
- static void
- print_struct_with_dereference(ulong addr, struct datatype_member *dm, ulong flags)
- {
- int indent;
- char *p1;
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char buf3[BUFSIZE];
- struct datatype_member datatype_member, *dm1;
- dm1 = &datatype_member;
- open_tmpfile();
- if (flags & UNION_REQUEST)
- print_union(dm->name, addr);
- else if (flags & STRUCT_REQUEST)
- print_struct(dm->name, addr);
- rewind(pc->tmpfile);
- while (fgets(buf1, BUFSIZE, pc->tmpfile)) {
- indent = count_leading_spaces(buf1);
- if ((indent != 2) || strstr(buf1, "{") || strstr(buf1, "}")) {
- print_verbatim(pc->saved_fp, buf1);
- continue;
- }
- sprintf(buf2, "%s.", dm->name);
- strcpy(buf3, &buf1[2]);
- p1 = strstr(buf3, " =");
- *p1 = NULLCHAR;
- strcat(buf2, buf3);
- if ((arg_to_datatype(buf2, dm1, RETURN_ON_ERROR) == 2) &&
- dereference_pointer(addr, dm1, flags))
- continue;
- print_verbatim(pc->saved_fp, buf1);
- }
- close_tmpfile();
- }
- static int
- dereference_pointer(ulong addr, struct datatype_member *dm, ulong flags)
- {
- char buf1[BUFSIZE];
- char buf2[BUFSIZE];
- char *typeptr, *member, *charptr, *voidptr, *p1, *sym;
- int found, ptrptr, funcptr, typedef_is_ptr, use_symbol;
- ulong target, value;
- found = ptrptr = funcptr = typedef_is_ptr = use_symbol = FALSE;
- member = GETBUF(strlen(dm->member)+4);
- typeptr = charptr = voidptr = NULL;
- open_tmpfile2();
- whatis_datatype(dm->name, flags, pc->tmpfile2);
- rewind(pc->tmpfile2);
- while (fgets(buf1, BUFSIZE, pc->tmpfile2)) {
- sprintf(member, " *%s;", dm->member);
- if (strstr(buf1, member) && (buf1[4] != ' ')) {
- typeptr = &buf1[4];
- found++;
- break;
- }
- sprintf(member, "**%s;", dm->member);
- if (strstr(buf1, member) && (buf1[4] != ' ')) {
- typeptr = &buf1[4];
- found++;
- ptrptr = TRUE;
- break;
- }
- sprintf(member, "(*%s)(", dm->member);
- if (strstr(buf1, member) && (buf1[4] != ' ')) {
- typeptr = &buf1[4];
- funcptr = TRUE;
- found++;
- break;
- }
- sprintf(member, " %s;", dm->member);
- if (strstr(buf1, member) && (buf1[4] != ' ')) {
- typeptr = &buf1[4];
- typedef_is_ptr = TRUE;
- strcpy(buf2, typeptr);
- p1 = strstr(buf2, " ");
- *p1 = NULLCHAR;
- if (datatype_exists(buf2) == TYPE_CODE_PTR) {
- found++;
- break;
- }
- }
- }
- close_tmpfile2();
- FREEBUF(member);
- if (!found) {
- console("%s.%s: not found!\n", dm->name, dm->member);
- return FALSE;
- }
- if (funcptr) {
- p1 = strstr(buf1, ";");
- *p1 = NULLCHAR;
- } else if (ptrptr) {
- p1 = strstr(buf1, "**");
- *(p1+2) = NULLCHAR;
- charptr = voidptr = NULL;
- } else if (typedef_is_ptr) {
- p1 = strstr(typeptr, " ");
- *p1 = NULLCHAR;
- } else {
- p1 = strstr(buf1, "*");
- *(p1+1) = NULLCHAR;
- charptr = strstr(&buf1[4], "char *");
- voidptr = strstr(&buf1[4], "void *");
- }
- console("%s.%s typeptr: %s ",
- dm->name, dm->member,
- typeptr);
- if (charptr)
- console("[char *]");
- else if (voidptr)
- console("[void *]");
- else if (funcptr)
- console("[func *]");
- else if (typedef_is_ptr)
- console("[typedef is ptr]");
- console("\n");
- if (!readmem(addr + dm->member_offset, KVADDR,
- &target, sizeof(void *), "target address",
- RETURN_ON_ERROR|QUIET)) {
- error(INFO, "cannot access %s.%s %lx\n",
- dm->name, dm->member,
- addr + dm->member_offset);
- return FALSE;
- }
- if ((sym = value_symbol(target))) {
- switch (get_symbol_type(sym, NULL, NULL))
- {
- case TYPE_CODE_ARRAY:
- case TYPE_CODE_UNION:
- case TYPE_CODE_STRUCT:
- case TYPE_CODE_INT:
- case TYPE_CODE_PTR:
- use_symbol = TRUE;
- console("use_symbol: %s\n", sym);
- break;
- }
- }
- if (funcptr) {
- fprintf(pc->saved_fp, " %s = 0x%lx\n -> ",
- typeptr, target);
- if (sym)
- fprintf(pc->saved_fp, "<%s>\n", sym);
- else if (target)
- fprintf(pc->saved_fp, "(unknown)\n");
- else
- fprintf(pc->saved_fp, "NULL\n");
- return TRUE;
- }
- if (charptr) {
- fprintf(pc->saved_fp, " %s%s = 0x%lx\n -> ", typeptr, dm->member,
- target);
- if (sym)
- fprintf(pc->saved_fp, "<%s> ", sym);
- if (!target)
- fprintf(pc->saved_fp, "NULL\n");
- else if (!accessible(target) || !read_string(target, buf1, BUFSIZE-1))
- fprintf(pc->saved_fp, "(not accessible)\n");
- else
- fprintf(pc->saved_fp, "\"%s\"\n", buf1);
- return TRUE;
- }
- if (voidptr && !use_symbol) {
- fprintf(pc->saved_fp, " %s%s = 0x%lx\n -> ", typeptr, dm->member,
- target);
- if (sym)
- fprintf(pc->saved_fp, "<%s>\n", sym);
- else if (!target)
- fprintf(pc->saved_fp, "NULL\n");
- else if (voidptr)
- fprintf(pc->saved_fp, "(unknown target type)\n");
- return TRUE;
- }
- if (!target || !accessible(target)) {
- fprintf(pc->saved_fp, " %s%s%s = 0x%lx\n -> ", typeptr,
- typedef_is_ptr ? " " : "", dm->member, target);
- if (!target)
- fprintf(pc->saved_fp, "NULL\n");
- else
- fprintf(pc->saved_fp, "(not accessible)\n");
- return TRUE;
- }
- if (ptrptr) {
- fprintf(pc->saved_fp, " %s%s = 0x%lx\n -> ", typeptr, dm->member,
- target);
- if (sym)
- fprintf(pc->saved_fp, "<%s> ", sym);
- if (!target ||
- !readmem(target, KVADDR, &value, sizeof(void *),
- "target value", RETURN_ON_ERROR|QUIET))
- fprintf(pc->saved_fp, "\n");
- else
- fprintf(pc->saved_fp, "%lx\n", value);
- return TRUE;
- }
- if (use_symbol)
- sprintf(buf2, "p %s\n", sym);
- else
- sprintf(buf2, "p *((%s)(0x%lx))\n", typeptr, target);
- console("gdb command: %s", buf2);
- if (!typedef_is_ptr) {
- p1 = strstr(typeptr, "*");
- *(p1-1) = NULLCHAR;
- }
- if (!datatype_exists(typeptr)) {
- fprintf(pc->saved_fp,
- " %s %s%s = 0x%lx\n -> (%s: no debuginfo data)\n",
- typeptr, typedef_is_ptr ? "" : "*", dm->member, target,
- typeptr);
- return TRUE;
- }
- open_tmpfile2();
- if (!gdb_pass_through(buf2, pc->tmpfile2, GNU_RETURN_ON_ERROR)) {
- console("gdb request failed: %s\n", buf2);
- close_tmpfile2();
- return FALSE;
- }
- fprintf(pc->saved_fp, " %s %s%s = 0x%lx\n -> ", typeptr,
- typedef_is_ptr ? "" : "*", dm->member, target);
- rewind(pc->tmpfile2);
- while (fgets(buf1, BUFSIZE, pc->tmpfile2)) {
- if (buf1[0] == '$') {
- if (sym)
- fprintf(pc->saved_fp, "<%s> ", sym);
- if (typedef_is_ptr || use_symbol) {
- if (strstr(buf1, "(") && strstr(buf1, ")")) {
- fprintf(pc->saved_fp, "\n");
- break;
- }
- }
- p1 = strstr(buf1, "=");
- fprintf(pc->saved_fp, "%s", p1+2);
- } else
- fprintf(pc->saved_fp, " %s", buf1);
- }
-
- close_tmpfile2();
- return TRUE;
- }
- static void
- cmd_datatype_common(ulong flags)
- {
- int c;
- ulong addr, aflag;
- char *cpuspec;
- ulong *cpus;
- struct syment *sp;
- ulong list_head_offset;
- int count;
- int argc_members;
- int optind_save;
- unsigned int radix, restore_radix;
- struct datatype_member datatype_member, *dm;
- char *separator;
- char *structname, *members;
- char *memberlist[MAXARGS];
- dm = &datatype_member;
- count = 0xdeadbeef;
- aflag = addr = 0;
- list_head_offset = 0;
- argc_members = 0;
- radix = restore_radix = 0;
- separator = members = NULL;
- cpuspec = NULL;
- cpus = NULL;
- while ((c = getopt(argcnt, args, "pxdhfuc:rvol:")) != EOF) {
- switch (c)
- {
- case 'p':
- flags |= DEREF_POINTERS;
- break;
- case 'd':
- if (radix == 16)
- error(FATAL,
- "-d and -x are mutually exclusive\n");
- radix = 10;
- break;
- case 'h':
- case 'x':
- if (radix == 10)
- error(FATAL,
- "-d and -x are mutually exclusive\n");
- radix = 16;
- break;
- case 'c':
- count = atoi(optarg);
- break;
- case 'r':
- flags |= SHOW_RAW_DATA;
- break;
- case 'v':
- flags |= STRUCT_VERBOSE;
- break;
- case 'o':
- flags |= SHOW_OFFSET;
- break;
- case 'l':
- if (IS_A_NUMBER(optarg))
- list_head_offset = stol(optarg,
- FAULT_ON_ERROR, NULL);
- else if (arg_to_datatype(optarg,
- dm, RETURN_ON_ERROR) > 1)
- list_head_offset = dm->member_offset;
- else
- error(FATAL, "invalid -l option: %s\n",
- optarg);
- break;
- case 'f':
- if (!pc->dumpfile)
- error(FATAL,
- "-f option requires a dumpfile\n");
- pc->curcmd_flags |= MEMTYPE_FILEADDR;
- break;
- case 'u':
- pc->curcmd_flags |= MEMTYPE_UVADDR;
- break;
- default:
- argerrs++;
- break;
- }
- }
- if (argerrs || !args[optind])
- cmd_usage(pc->curcmd, SYNOPSIS);
- if ((count_chars(args[optind], ',')+1) > MAXARGS)
- error(FATAL, "too many members in comma-separated list!\n");
- if ((count_chars(args[optind], '.') > 1) ||
- (LASTCHAR(args[optind]) == ',') ||
- (LASTCHAR(args[optind]) == '.'))
- error(FATAL, "invalid format: %s\n", args[optind]);
- optind_save = optind;
- /*
- * Take care of address and count (array).
- */
- while (args[++optind]) {
- if (aflag && (count != 0xdeadbeef))
- error(FATAL, "too many arguments!\n");
- if (!aflag) {
- cpuspec = strchr(args[optind], ':');
- if (cpuspec)
- *cpuspec++ = NULLCHAR;
- }
- if (clean_arg() && IS_A_NUMBER(args[optind])) {
- if (aflag)
- count = stol(args[optind],
- FAULT_ON_ERROR, NULL);
- else if (cpuspec) {
- if (pc->curcmd_flags & MEMTYPE_FILEADDR)
- error(FATAL, "-f option cannot be used with percpu\n");
- addr = htol(args[optind], FAULT_ON_ERROR, NULL);
- aflag++;
- } else {
- if (pc->curcmd_flags & MEMTYPE_FILEADDR)
- pc->curcmd_private = stoll(args[optind],
- FAULT_ON_ERROR, NULL);
- else if (pc->curcmd_flags & MEMTYPE_UVADDR) {
- addr = htol(args[optind], FAULT_ON_ERROR,
- NULL);
- } else if (!IS_KVADDR(addr = htol(args[optind],
- FAULT_ON_ERROR, NULL)))
- error(FATAL,
- "invalid kernel virtual address: %s\n",
- args[optind]);
- aflag++;
- }
- } else if ((sp = symbol_search(args[optind]))) {
- if (cpuspec && !is_percpu_symbol(sp)) {
- error(WARNING,
- "%s is not percpu; cpuspec ignored.\n",
- sp->name);
- cpuspec = NULL;
- }
- addr = sp->value;
- aflag++;
- } else {
- fprintf(fp, "symbol not found: %s\n", args[optind]);
- fprintf(fp, "possible alternatives:\n");
- if (!symbol_query(args[optind], " ", NULL))
- fprintf(fp, " (none found)\n");
- goto freebuf;
- }
- }
- if (cpuspec) {
- cpus = get_cpumask_buf();
- if (STREQ(cpuspec, ""))
- SET_BIT(cpus, CURRENT_CONTEXT()->processor);
- else
- make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
- }
- optind = optind_save;
- if (count == 0xdeadbeef)
- count = 1;
- else if (!aflag)
- error(FATAL, "no kernel virtual address argument entered\n");
- if ((flags & DEREF_POINTERS) && !aflag)
- error(FATAL, "-p option requires address argument\n");
- if (list_head_offset)
- addr -= list_head_offset;
- /*
- * Handle struct.member[,member] argument format.
- */
- if (strstr(args[optind], ".")) {
- structname = GETBUF(strlen(args[optind])+1);
- strcpy(structname, args[optind]);
- separator = strstr(structname, ".");
- members = GETBUF(strlen(args[optind])+1);
- strcpy(members, separator+1);
- replace_string(members, ",", ' ');
- argc_members = parse_line(members, memberlist);
- } else
- structname = args[optind];
- if ((arg_to_datatype(structname, dm,
- DATATYPE_QUERY|ANON_MEMBER_QUERY|RETURN_ON_ERROR) < 1))
- error(FATAL, "invalid data structure reference: %s\n", structname);
- if (! (flags & (STRUCT_REQUEST|UNION_REQUEST)) ) {
- flags |= dm->type;
- if (!(flags & (UNION_REQUEST|STRUCT_REQUEST)))
- error(FATAL, "invalid argument");
- } else if ( (flags &(STRUCT_REQUEST|UNION_REQUEST)) != dm->type) {
- error(FATAL, "data type mismatch: %s is not a %s\n",
- dm->name, flags & UNION_REQUEST ? "union" : "struct");
- }
- if ((argc_members > 1) && !aflag) {
- error(INFO, flags & SHOW_OFFSET ?
- "-o option not valid with multiple member format\n" :
- "multiple member format not supported in this syntax\n");
- *separator = NULLCHAR;
- argc_members = 0;
- flags |= SHOW_OFFSET;
- }
- if ((argc_members > 1) && aflag && (flags & SHOW_OFFSET))
- error(FATAL,
- "-o option not valid with multiple member format\n");
- set_temporary_radix(radix, &restore_radix);
- /*
- * No address was passed -- dump the structure/member declaration.
- */
- if (!aflag) {
- if (argc_members &&
- !member_to_datatype(memberlist[0], dm,
- ANON_MEMBER_QUERY))
- error(FATAL, "invalid data structure reference: %s.%s\n",
- dm->name, memberlist[0]);
- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
- } else if (cpus) {
- for (c = 0; c < kt->cpus; c++) {
- ulong cpuaddr;
- if (!NUM_IN_BITMAP(cpus, c))
- continue;
- cpuaddr = addr + kt->__per_cpu_offset[c];
- fprintf(fp, "[%d]: %lx\n", c, cpuaddr);
- do_datatype_addr(dm, cpuaddr , count,
- flags, memberlist, argc_members);
- }
- } else
- do_datatype_addr(dm, addr, count, flags,
- memberlist, argc_members);
- restore_current_radix(restore_radix);
- freebuf:
- if (argc_members) {
- FREEBUF(structname);
- FREEBUF(members);
- }
- if (cpus)
- FREEBUF(cpus);
- }
- static void
- do_datatype_addr(struct datatype_member *dm, ulong addr, int count,
- ulong flags, char **memberlist, int argc_members)
- {
- int i, c;
- long len = dm->size;
- if (count < 0) {
- addr -= len * abs(count);
- addr += len;
- }
- if (pc->curcmd_flags & MEMTYPE_FILEADDR)
- addr = 0; /* unused, but parsed by gdb */
- for (c = 0; c < abs(count); c++, addr += len, pc->curcmd_private += len) {
- if (c)
- fprintf(fp,"\n");
- i = 0;
- do {
- if (argc_members) {
- if (!member_to_datatype(memberlist[i], dm,
- ANON_MEMBER_QUERY))
- error(FATAL, "invalid data structure reference: %s.%s\n",
- dm->name, memberlist[i]);
- if (flags & SHOW_RAW_DATA)
- error(FATAL,
- "member-specific output not allowed with -r\n");
- }
- /*
- * Display member addresses or data
- */
- if (flags & SHOW_OFFSET) {
- dm->vaddr = addr;
- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
- } else if (flags & SHOW_RAW_DATA)
- raw_data_dump(addr, len, flags & STRUCT_VERBOSE);
- else if ((flags & DEREF_POINTERS) && !dm->member) {
- print_struct_with_dereference(addr, dm, flags);
- } else {
- if (dm->member)
- open_tmpfile();
-
- if (flags & UNION_REQUEST)
- print_union(dm->name, addr);
- else if (flags & STRUCT_REQUEST)
- print_struct(dm->name, addr);
- if (dm->member) {
- if (!((flags & DEREF_POINTERS) &&
- dereference_pointer(addr, dm, flags)))
- parse_for_member(dm, PARSE_FOR_DATA);
- close_tmpfile();
- }
- }
- } while (++i < argc_members);
- }
- }
- /*
- * Generic function for dumping data structure declarations, with a small
- * fixup for typedefs, sizes and member offsets.
- */
- static void
- do_datatype_declaration(struct datatype_member *dm, ulong flags)
- {
- long len;
- char buf[BUFSIZE];
- char *p1, *p2, *multiline;
- FILE *sfp;
- if (CRASHDEBUG(1))
- dump_datatype_member(fp, dm);
- open_tmpfile();
- whatis_datatype(dm->name, flags, pc->tmpfile);
- rewind(pc->tmpfile);
- if (dm->member)
- flags |= SHOW_OFFSET;
- sfp = pc->saved_fp;
- len = dm->size;
- multiline = NULL;
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (STRNEQ(buf, "type = ")) {
- multiline = strstr(buf, "{");
- if (flags & TYPEDEF)
- fprintf(sfp, "typedef ");
- p1 = buf + strlen("type = ");
- if ((p2 = strstr(buf, "(*)()"))) {
- *p2 = NULLCHAR;
- fprintf(sfp, "%s(*%s)();\n",
- p1, dm->name);
- } else if ((p2 = strstr(buf, "()"))) {
- *p2 = NULLCHAR;
- fprintf(sfp, "%s(%s)();\n", p1, dm->name);
- } else if (multiline)
- fprintf(sfp, "%s", p1);
- else
- fprintf(sfp, "%s %s;\n",
- strip_linefeeds(p1), dm->name);
- } else {
- if (multiline && STRNEQ(buf, "}") && (flags & TYPEDEF)){
- if (strstr(buf, "} **()"))
- fprintf(sfp, "} **(%s)();\n", dm->name);
- else
- fprintf(sfp, "%s %s;\n",
- strip_linefeeds(buf), dm->name);
- } else {
- if ((flags & SHOW_OFFSET) && whitespace(buf[0]))
- show_member_offset(sfp, dm, buf);
- else
- fprintf(sfp, "%s", buf);
- }
- }
- }
- if (!dm->member) {
- switch (*gdb_output_radix)
- {
- default:
- case 10:
- fprintf(sfp, "SIZE: %ld\n", len);
- break;
- case 16:
- fprintf(sfp, "SIZE: 0x%lx\n", len);
- break;
- }
- }
- close_tmpfile();
- }
- /*
- * Take a argument string, which may be in "struct.member" or "union.member"
- * format, figure out whether it's a structure or a union reference, and
- * fill in the appropriate fields of the dataytype_member structure.
- * Return 1 if it's a straight struct or union reference, 2 if it has
- * a legitimate .member attached to it, or 0 if it's bogus.
- */
- int
- arg_to_datatype(char *s, struct datatype_member *dm, ulong flags)
- {
- char *p1;
- int both;
-
- BZERO(dm, sizeof(struct datatype_member));
- both = FALSE;
- dm->name = s;
- if (!(p1 = strstr(s, ".")))
- both = FALSE;
- else if (flags & DATATYPE_QUERY) {
- *p1 = NULLCHAR;
- both = FALSE;
- } else {
- if ((p1 == s) || !strlen(p1+1))
- goto datatype_member_fatal;
- *p1 = NULLCHAR;
- if (strstr(p1+1, "."))
- goto datatype_member_fatal;
- both = TRUE;
- }
- if ((dm->size = DATATYPE_SIZE(dm)) < 0) {
- if (flags & RETURN_ON_ERROR)
- goto datatype_member_fatal;
- error(FATAL,
- "cannot handle \"%s\": try \"gdb whatis\" or \"gdb ptype\"\n", s);
- }
- if (!both)
- return 1;
- if (member_to_datatype(p1 + 1, dm, flags))
- return 2;
- datatype_member_fatal:
- if (flags & RETURN_ON_ERROR) {
- if (both)
- *p1 = '.';
- return 0;
- }
- if (both) {
- *p1 = '.';
- if (strstr(p1+1, "."))
- error(FATAL, "only one %s member allowed: %s\n",
- (dm->type == STRUCT_REQUEST) ? "struct" :
- ((dm->type == UNION_REQUEST) ?
- "union" : "struct/union"), s);
- }
- return (error(FATAL, "invalid argument: %s\n", s));
- }
- static int
- member_to_datatype(char *s, struct datatype_member *dm, ulong flags)
- {
- dm->member = s;
- if ((dm->member_offset = MEMBER_OFFSET(dm->name, s)) >= 0)
- return TRUE;
- if ((flags & ANON_MEMBER_QUERY) &&
- ((dm->member_offset = ANON_MEMBER_OFFSET(dm->name, s)) >= 0))
- return TRUE;
- return FALSE;
- }
- /*
- * debug routine -- not called on purpose by anybody.
- */
- static void
- dump_datatype_member(FILE *ofp, struct datatype_member *dm)
- {
- int others;
- others = 0;
- fprintf(ofp, " name: %s\n", dm->name);
- fprintf(ofp, " member: %s\n", dm->member);
- fprintf(ofp, " type: %lx (", dm->type);
- if (dm->type & STRUCT_REQUEST)
- fprintf(ofp, "%sSTRUCT_REQUEST", others++ ? "|" : "");
- if (dm->type & UNION_REQUEST)
- fprintf(fp, "%sUNION_REQUEST", others++ ? "|" : "");
- if (dm->type & INT64)
- fprintf(ofp, "%sINT64", others++ ? "|" : "");
- if (dm->type & INT32)
- fprintf(ofp, "%sINT32", others++ ? "|" : "");
- if (dm->type & INT16)
- fprintf(ofp, "%sINT16", others++ ? "|" : "");
- if (dm->type & INT8)
- fprintf(ofp, "%sINT8", others++ ? "|" : "");
- if (dm->type & POINTER)
- fprintf(ofp, "%sPOINTER", others++ ? "|" : "");
- if (dm->type & FUNCTION)
- fprintf(ofp, "%sFUNCTION", others++ ? "|" : "");
- if (dm->type & ARRAY)
- fprintf(ofp, "%sARRAY", others++ ? "|" : "");
- if (dm->type & ENUM)
- fprintf(ofp, "%sENUM", others++ ? "|" : "");
- if (dm->type & IN_UNION)
- fprintf(ofp, "%sIN_UNION", others++ ? "|" : "");
- if (dm->type & IN_STRUCT)
- fprintf(ofp, "%sIN_STRUCT", others++ ? "|" : "");
- fprintf(ofp, ")\n");
- fprintf(ofp, " size: %ld\n", dm->size);
- fprintf(ofp, " member_offset: %ld\n", dm->member_offset);
- fprintf(ofp, " member_size: %ld\n", dm->member_size);
- fprintf(ofp, "member_typecode: %d\n", dm->member_typecode);
- fprintf(ofp, " flags: %lx ", dm->flags);
- dump_datatype_flags(dm->flags, ofp);
- fprintf(ofp, " tagname: %s\n", dm->tagname);
- fprintf(ofp, " value: %ld\n", dm->value);
- fprintf(ofp, " vaddr: %lx\n", dm->vaddr);
- fprintf(ofp, "\n");
- }
- /*
- * This command displays the definition of structures, unions, typedefs or
- * text/data symbols:
- *
- * 1. For a structure name, the output is the same as if the "struct"
- * command was used.
- * 2. For a union name, the output is the same as if the "union" command
- * was used.
- * 3. For a typedef name that translates to a structure or union, the output
- * is the same as if the "struct" or "union" command was used.
- * 4. For a typedef name that translates to a primitive datatype, the one-line
- * declaration is displayed.
- * 5. For a kernel symbol name, the output is the same as if the "sym" command
- * was used.
- */
- void
- cmd_whatis(void)
- {
- struct datatype_member datatype_member, *dm;
- struct syment *sp;
- char buf[BUFSIZE];
- long len;
- int c;
- ulong flags;
- dm = &datatype_member;
- flags = 0;
- while ((c = getopt(argcnt, args, "o")) != EOF) {
- switch(c)
- {
- case 'o':
- flags |= SHOW_OFFSET;
- break;
- default:
- argerrs++;
- break;
- }
- }
- if (argerrs || !args[optind])
- cmd_usage(pc->curcmd, SYNOPSIS);
- if (STREQ(args[optind], "struct") ||
- STREQ(args[optind], "union") ||
- STREQ(args[optind], "enum"))
- optind++;
- else if ((sp = symbol_search(args[optind]))) {
- whatis_variable(sp);
- return;
- }
- if (!args[optind])
- cmd_usage(pc->curcmd, SYNOPSIS);
- if (arg_to_datatype(args[optind], dm, RETURN_ON_ERROR)) {
- if ((len = dm->size) < 0)
- goto whatis_failure;
- flags |= dm->type;
- if (dm->type == ENUM) {
- if (dm->tagname)
- fprintf(fp, "%senum%s%s = %ld\n",
- dm->flags & TYPEDEF ? "typedef " : "",
- strlen(dm->tagname) ? " " : "",
- dm->tagname, dm->value);
- else
- dump_enumerator_list(args[optind]);
- return;
- }
- do_datatype_declaration(dm, flags | (dm->flags & TYPEDEF));
- } else {
- if (!gdb_whatis(concat_args(buf, 1, FALSE)))
- goto whatis_failure;
- }
- return;
- whatis_failure:
- error(INFO, "cannot resolve: %s\n", concat_args(buf, 1, FALSE));
- cmd_usage(pc->curcmd, SYNOPSIS);
- }
- /*
- * Try gdb's whatis on a command string.
- */
- static int
- gdb_whatis(char *s)
- {
- char buf[BUFSIZE], *p1;
- open_tmpfile();
- sprintf(buf, "whatis %s", s);
- if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- return FALSE;
- }
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- p1 = buf;
- if (STRNEQ(buf, "type = "))
- p1 += strlen("type = ");
- fprintf(pc->saved_fp, "%s", p1);
- }
- close_tmpfile();
- return TRUE;
- }
- /*
- * Given the name of an enum, have gdb dump its enumerator list.
- */
- int
- dump_enumerator_list(char *e)
- {
- struct gnu_request *req;
- struct datatype_member datatype_member, *dm;
- dm = &datatype_member;
- if (!arg_to_datatype(e, dm, RETURN_ON_ERROR) ||
- (dm->size < 0) || (dm->type != ENUM) || dm->tagname)
- return FALSE;
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- req->command = GNU_GET_DATATYPE;
- req->name = e;
- req->flags = GNU_PRINT_ENUMERATORS;
- gdb_interface(req);
- FREEBUF(req);
- return TRUE;
- }
- /*
- * Given the name of an enum, return its value.
- */
- int
- enumerator_value(char *e, long *value)
- {
- struct datatype_member datatype_member, *dm;
- dm = &datatype_member;
- if (arg_to_datatype(e, dm, RETURN_ON_ERROR)) {
- if ((dm->size >= 0) &&
- (dm->type == ENUM) && dm->tagname) {
- *value = dm->value;
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * Verify that a datatype exists, but return on error.
- */
- int
- datatype_exists(char *s)
- {
- int retval;
- char buf[BUFSIZE], *p;
- struct gnu_request *req;
- strcpy(buf, s);
- if ((p = strstr(buf, ".")))
- *p = NULLCHAR;
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- req->command = GNU_GET_DATATYPE;
- req->name = buf;
- req->flags = GNU_RETURN_ON_ERROR;
- req->fp = pc->nullfp;
- gdb_interface(req);
- retval = req->typecode;
- FREEBUF(req);
- return retval;
- }
- /*
- * Set the output radix if requested, and pass it on to gdb.
- */
- void
- cmd_p(void)
- {
- int c;
- struct syment *sp, *percpu_sp;
- unsigned radix;
- int do_load_module_filter;
- char buf1[BUFSIZE];
- char *cpuspec;
- do_load_module_filter = radix = 0;
- while ((c = getopt(argcnt, args, "dhxu")) != EOF) {
- switch(c)
- {
- case 'd':
- if (radix == 16)
- error(FATAL,
- "-d and -x are mutually exclusive\n");
- radix = 10;
- break;
- case 'h':
- case 'x':
- if (radix == 10)
- error(FATAL,
- "-d and -x are mutually exclusive\n");
- radix = 16;
- break;
- case 'u':
- pc->curcmd_flags |= MEMTYPE_UVADDR;
- break;
- default:
- argerrs++;
- break;
- }
- }
- if (argerrs || !args[optind])
- cmd_usage(pc->curcmd, SYNOPSIS);
- cpuspec = strrchr(args[optind], ':');
- if (cpuspec)
- *cpuspec++ = NULLCHAR;
- sp = NULL;
- if ((sp = symbol_search(args[optind])) && !args[optind+1]) {
- if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
- display_per_cpu_info(percpu_sp, radix, cpuspec))
- return;
- if (module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix))
- do_load_module_filter = TRUE;
- } else if ((percpu_sp = per_cpu_symbol_search(args[optind])) &&
- display_per_cpu_info(percpu_sp, radix, cpuspec))
- return;
- else if (st->flags & LOAD_MODULE_SYMS)
- do_load_module_filter = TRUE;
- if (cpuspec) {
- if (sp)
- error(WARNING, "%s is not percpu; cpuspec ignored.\n",
- sp->name);
- else
- /* maybe a valid C expression (e.g. ':') */
- *(cpuspec-1) = ':';
- }
- process_gdb_output(concat_args(buf1, 0, TRUE), radix,
- sp ? sp->name : NULL, do_load_module_filter);
- }
- static void
- process_gdb_output(char *gdb_request, unsigned radix,
- const char *leader, int do_load_module_filter)
- {
- unsigned restore_radix;
- int success;
- char buf1[BUFSIZE];
- char *p1;
- if (leader || do_load_module_filter)
- open_tmpfile();
- set_temporary_radix(radix, &restore_radix);
- success = gdb_pass_through(gdb_request, NULL, GNU_RETURN_ON_ERROR);
- if (success && (leader || do_load_module_filter)) {
- int firstline;
- if (leader) {
- fprintf(pc->saved_fp, "%s = ", leader);
- fflush(pc->saved_fp);
- }
- firstline = TRUE;
- rewind(pc->tmpfile);
- while (fgets(buf1, BUFSIZE, pc->tmpfile)) {
- if (firstline &&
- (p1 = strstr(buf1, "{")) &&
- !STRNEQ(p1, "{\n")) {
- *p1 = NULLCHAR;
- fprintf(pc->saved_fp, "%s", buf1);
- fprintf(pc->saved_fp, "\n {");
- print_verbatim(pc->saved_fp, p1+1);
- } else
- print_verbatim(pc->saved_fp, do_load_module_filter ?
- load_module_filter(buf1, LM_P_FILTER) :
- buf1);
- firstline = FALSE;
- }
- }
- if (leader || do_load_module_filter)
- close_tmpfile();
- restore_current_radix(restore_radix);
- if (!success)
- error(FATAL, "gdb request failed: %s\n", gdb_request);
- }
- /*
- * Get the type of an expression using gdb's "whatis" command.
- * The returned string is dynamically allocated, and it should
- * be passed to FREEBUF() when no longer needed.
- * Return NULL if the type cannot be determined.
- */
- static char *
- expr_type_name(const char *expr)
- {
- char buf[BUFSIZE], *p;
- open_tmpfile();
- sprintf(buf, "whatis %s", expr);
- if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- return NULL;
- }
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile) && !STRNEQ(buf, "type = "))
- ;
- p = feof(pc->tmpfile) ? NULL : buf + strlen("type = ");
- close_tmpfile();
- if (p) {
- size_t len = strlen(clean_line(p));
- /* GDB reports unknown types as <...descriptive text...> */
- if (p[0] == '<' && p[len-1] == '>')
- return NULL;
- return strcpy(GETBUF(len + 1), p);
- }
- return NULL;
- }
- /*
- * Display the datatype of the per_cpu__xxx symbol and
- * the addresses of each its per-cpu instances.
- */
- static int
- display_per_cpu_info(struct syment *sp, int radix, char *cpuspec)
- {
- ulong *cpus;
- int c;
- ulong addr;
- char buf[BUFSIZE];
- char leader[sizeof("&per_cpu(") + strlen(sp->name) +
- sizeof(", " STR(UINT_MAX) ")")];
- char *typename;
- int do_load_module_filter;
- if (((kt->flags & (SMP|PER_CPU_OFF)) != (SMP|PER_CPU_OFF)) ||
- (!is_percpu_symbol(sp)) ||
- !((sp->type == 'd') || (sp->type == 'D') || (sp->type == 'V')))
- return FALSE;
- if (cpuspec) {
- cpus = get_cpumask_buf();
- if (STREQ(cpuspec, ""))
- SET_BIT(cpus, CURRENT_CONTEXT()->processor);
- else
- make_cpumask(cpuspec, cpus, FAULT_ON_ERROR, NULL);
- } else
- cpus = NULL;
- typename = expr_type_name(sp->name);
- if (!cpus) {
- fprintf(fp, "PER-CPU DATA TYPE:\n ");
- if (!typename)
- fprintf(fp, "[undetermined type] %s;\n", sp->name);
- else
- whatis_variable(sp);
- fprintf(fp, "PER-CPU ADDRESSES:\n");
- }
- do_load_module_filter =
- module_symbol(sp->value, NULL, NULL, NULL, *gdb_output_radix);
- for (c = 0; c < kt->cpus; c++) {
- if (cpus && !NUM_IN_BITMAP(cpus, c))
- continue;
- addr = sp->value + kt->__per_cpu_offset[c];
- if (!cpus)
- fprintf(fp, " [%d]: %lx\n", c, addr);
- else if (typename) {
- snprintf(buf, sizeof buf, "p *(%s*) 0x%lx",
- typename, addr);
- sprintf(leader, "per_cpu(%s, %u)",
- sp->name, c);
- process_gdb_output(buf, radix, leader,
- do_load_module_filter);
- } else {
- snprintf(buf, sizeof buf, "p (void*) 0x%lx", addr);
- sprintf(leader, "&per_cpu(%s, %u)",
- sp->name, c);
- process_gdb_output(buf, radix, leader,
- do_load_module_filter);
- }
- }
- if (typename)
- FREEBUF(typename);
- if (cpus)
- FREEBUF(cpus);
- return TRUE;
- }
- static struct load_module *
- get_module_percpu_sym_owner(struct syment *sp)
- {
- int i;
- struct load_module *lm;
- if (!IS_MODULE_SYMBOL(sp))
- return NULL;
- /*
- * Find out percpu symbol owner module.
- * If found out, sp is module's percpu symbol.
- */
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!MODULE_PERCPU_SYMS_LOADED(lm))
- continue;
- if (IN_MODULE_PERCPU(sp->value, lm))
- return lm;
- }
- return NULL;
- }
- static int
- is_percpu_symbol(struct syment *sp)
- {
- if (sp->value >= st->__per_cpu_start) {
- if (sp->value < st->__per_cpu_end)
- /* kernel percpu symbol */
- return 1;
- else if (get_module_percpu_sym_owner(sp))
- /* module percpu symbol */
- return 2;
- }
- return 0;
- }
- /*
- * As a latch ditch effort before a command is thrown away by exec_command(),
- * args[0] is checked to see whether it's the name of a variable, structure,
- * union, or typedef. If so, args[0] is changed to the appropriate command,
- * i.e., "p", "struct", "union", or "whatis", and the original args are all
- * shifted into the next higer args[] location.
- */
- int
- is_datatype_command(void)
- {
- int i;
- long len;
- char *command;
- struct datatype_member datatype_member, *dm;
- struct syment *sp;
- char *rdarg;
- char buf[BUFSIZE];
- if (!args[0])
- return FALSE;
- strcpy(buf, args[0]);
- dm = &datatype_member;
- if ((sp = symbol_search(args[0])) && (argcnt == 1)) {
- if (is_gdb_command(FALSE, RETURN_ON_ERROR)) {
- pc->curcmd = pc->program_name;
- error(FATAL,
- "ambiguous command: %s (symbol and gdb command)\n",
- args[0]);
- }
- command = "p";
- } else if (STREQ(args[0], "enum"))
- command = "whatis";
- else if (!datatype_exists(args[0]))
- return FALSE;
- else if (!arg_to_datatype(buf, dm, RETURN_ON_ERROR|DATATYPE_QUERY))
- return FALSE;
- else {
- if (is_gdb_command(FALSE, RETURN_ON_ERROR)) {
- pc->curcmd = pc->program_name;
- error(FATAL,
- "ambiguous command: %s (symbol/data type and gdb command)\n",
- args[0]);
- }
- if ((sp = symbol_search(args[0])) && (argcnt == 1)) {
- command = "p";
- dm->type = 0;
- } else if ((len = DATATYPE_SIZE(dm)) < 0) {
- return FALSE;
- } else if (sp) {
- command = "p";
- dm->type = 0;
- }
- switch (dm->type)
- {
- case STRUCT_REQUEST:
- if ((dm->flags & TYPEDEF) && (argcnt == 1))
- command = "whatis";
- else
- command = "struct";
- break;
- case UNION_REQUEST:
- if ((dm->flags & TYPEDEF) && (argcnt == 1))
- command = "whatis";
- else
- command = "union";
- break;
- case POINTER:
- command = "whatis";
- break;
- case ARRAY:
- command = "whatis";
- break;
- case FUNCTION:
- command = "whatis";
- break;
- case ENUM:
- command = "whatis";
- break;
- default:
- if (dm->type & INTEGER_TYPE) {
- switch (dm->type)
- {
- case INT64: rdarg = "-64"; break;
- case INT32: rdarg = "-32"; break;
- case INT16: rdarg = "-16"; break;
- case INT8: rdarg = "-8"; break;
- default: rdarg = NULL; break;
- }
- if (args[1]) {
- if ((sp = symbol_search(args[1]))) {
- command = "p";
- args[0] = args[1];
- argcnt--;
- } else {
- command = "rd";
- args[0] = rdarg;
- }
- } else
- command = "whatis";
- } else
- return FALSE;
- break;
- }
- }
- for (i = argcnt; i; i--)
- args[i] = args[i-1];
- args[0] = command;
- argcnt++;
- return TRUE;
- }
- /*
- * Given a structure name and an address, have gdb do most of the work.
- */
- static void
- print_struct(char *s, ulong addr)
- {
- char buf[BUFSIZE];
- if (is_typedef(s))
- sprintf(buf, "output *(%s *)0x%lx", s, addr);
- else
- sprintf(buf, "output *(struct %s *)0x%lx", s, addr);
- fprintf(fp, "struct %s ", s);
- gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
- fprintf(fp, "\n");
- }
- /*
- * Given a union name and an address, let gdb do the work.
- */
- static void
- print_union(char *s, ulong addr)
- {
- char buf[BUFSIZE];
- if (is_typedef(s))
- sprintf(buf, "output *(%s *)0x%lx", s, addr);
- else
- sprintf(buf, "output *(union %s *)0x%lx", s, addr);
- fprintf(fp, "union %s ", s);
- gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
- }
- /*
- * Given a structure or union, find its definition in the datatype symbol
- * file, and dump it. If the verbose flags is set, everything from the
- * file is shown; otherwise the bitpos, size and id data is stripped.
- */
- static void
- whatis_datatype(char *st, ulong flags, FILE *ofp)
- {
- char lookbuf[BUFSIZE];
- if (flags & TYPEDEF)
- sprintf(lookbuf, "ptype %s", st);
- else if (flags & UNION_REQUEST)
- sprintf(lookbuf, "ptype union %s", st);
- else if (flags & STRUCT_REQUEST)
- sprintf(lookbuf, "ptype struct %s", st);
- else
- return;
- if (!gdb_pass_through(lookbuf, ofp, GNU_RETURN_ON_ERROR)) {
- /*
- * When a structure is defined using the format:
- *
- * typedef struct {
- * yada yada yada
- * } type_t;
- *
- * gdb says it's a structure and not a typedef. So
- * if the union or struct pass-through fails, it can't
- * hurt to retry it with just "ptype type_t" before
- * giving up.
- */
- if (flags & (UNION_REQUEST|STRUCT_REQUEST)) {
- sprintf(lookbuf, "ptype %s", st);
- gdb_pass_through(lookbuf, ofp, 0);
- }
- }
- }
- /*
- * Scan the symbol file for a variable declaration.
- */
- static void
- whatis_variable(struct syment *sp)
- {
- char *p1;
- char buf[BUFSIZE];
- open_tmpfile();
- sprintf(buf, "whatis %s", sp->name);
- if (!gdb_pass_through(buf, fp, GNU_RETURN_ON_ERROR)) {
- close_tmpfile();
- error(FATAL, "gdb request failed: whatis %s\n", sp->name);
- }
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (STRNEQ(buf, "type = "))
- break;
- }
- close_tmpfile();
- clean_line(buf);
- if ((p1 = strstr(buf, "["))) {
- shift_string_right(p1, strlen(sp->name));
- BCOPY(sp->name, p1, strlen(sp->name));
- p1 = buf + strlen("type = ");
- fprintf(fp, "%s;\n", p1);
- } else if ((p1 = strstr(buf, "("))) {
- if (index(buf, '(') == rindex(buf, '(')) {
- shift_string_right(p1, strlen(sp->name));
- BCOPY(sp->name, p1, strlen(sp->name));
- } else {
- p1 = strstr(buf, ")");
- shift_string_right(p1, strlen(sp->name));
- BCOPY(sp->name, p1, strlen(sp->name));
- }
- p1 = buf + strlen("type = ");
- fprintf(fp, "%s;\n", p1);
- } else {
- p1 = buf + strlen("type = ");
- fprintf(fp, "%s%s%s;\n", p1, LASTCHAR(p1) == '*' ? "":" ",
- sp->name);
- }
- }
- /*
- * Determines whether the current structure or union member is a typedef.
- */
- int
- is_typedef(char *name)
- {
- struct datatype_member datatype_member, *dm;
- if (!name)
- drop_core("is_typedef() received NULL name string\n");
- dm = &datatype_member;
- BZERO(dm, sizeof(struct datatype_member));
- dm->name = name;
- return (DATATYPE_SIZE(dm) < 0 ? FALSE : (dm->flags & TYPEDEF));
- }
- static void
- dump_datatype_flags(ulong flags, FILE *ofp)
- {
- int others;
- others = 0;
- fprintf(ofp, "(");
- if (flags & UINT8)
- fprintf(ofp, "%sUINT8", others++ ? "|" : "");
- if (flags & INT8)
- fprintf(ofp, "%sINT8", others++ ? "|" : "");
- if (flags & UINT16)
- fprintf(ofp, "%sUINT16", others++ ? "|" : "");
- if (flags & INT16)
- fprintf(ofp, "%sINT16", others++ ? "|" : "");
- if (flags & UINT32)
- fprintf(ofp, "%sUINT32", others++ ? "|" : "");
- if (flags & INT32)
- fprintf(ofp, "%sINT32", others++ ? "|" : "");
- if (flags & UINT64)
- fprintf(ofp, "%sUINT64", others++ ? "|" : "");
- if (flags & INT64)
- fprintf(ofp, "%sINT64", others++ ? "|" : "");
- if (flags & POINTER)
- fprintf(ofp, "%sPOINTER", others++ ? "|" : "");
- if (flags & FUNCTION)
- fprintf(ofp, "%sFUNCTION", others++ ? "|" : "");
- if (flags & ARRAY)
- fprintf(ofp, "%sARRAY", others++ ? "|" : "");
- if (flags & ENUM)
- fprintf(ofp, "%sENUM", others++ ? "|" : "");
- if (flags & TYPEDEF)
- fprintf(ofp, "%sTYPEDEF", others++ ? "|" : "");
- if (flags & STRUCT_VERBOSE)
- fprintf(ofp, "%sSTRUCT_VERBOSE", others++ ? "|" : "");
- if (flags & SHOW_OFFSET)
- fprintf(ofp, "%sSHOW_OFFSET", others++ ? "|" : "");
- if (flags & DATATYPE_QUERY)
- fprintf(ofp, "%sDATATYPE_QUERY", others++ ? "|" : "");
- if (flags & ANON_MEMBER_QUERY)
- fprintf(ofp, "%sANON_MEMBER_QUERY", others++ ? "|" : "");
- if (flags & SHOW_RAW_DATA)
- fprintf(ofp, "%sSHOW_RAW_DATA", others++ ? "|" : "");
- if (flags & DEREF_POINTERS)
- fprintf(ofp, "%sDEREF_POINTERS", others++ ? "|" : "");
- fprintf(ofp, ")\n");
- }
- /*
- * When a request is made to print just a member of a structure or union,
- * the whole datatype is dumped to a temporary file, and this routine
- * parses through it for the targeted member.
- */
- static void
- parse_for_member(struct datatype_member *dm, ulong flag)
- {
- char *s;
- char buf[BUFSIZE];
- char lookfor1[BUFSIZE];
- char lookfor2[BUFSIZE];
- char lookfor3[BUFSIZE];
- char lookfor4[BUFSIZE];
- char lookfor5[BUFSIZE];
- long curpos, last_open_bracket;
- int indent, on, array, embed;
- char *p1;
- s = dm->member;
- indent = 0;
- array = FALSE;
- on = 0;
- embed = 0;
- rewind(pc->tmpfile);
- switch (flag)
- {
- case PARSE_FOR_DATA:
- sprintf(lookfor1, " %s ", s);
- sprintf(lookfor2, " %s[", s);
- next_item:
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (embed && (count_leading_spaces(buf) == embed))
- embed = 0;
- if (!on && !embed && strstr(buf, "= {") && !strstr(buf, lookfor1))
- embed = count_leading_spaces(buf);
- if (embed)
- continue;
- if (strstr(buf, lookfor1) || strstr(buf, lookfor2)) {
- on++;
- if (strstr(buf, "= {"))
- indent = count_leading_spaces(buf);
- if (strstr(buf, "["))
- array = TRUE;
- }
-
- if (on) {
- if ((indent && (on > 1) && (count_leading_spaces(buf) == indent) &&
- !strstr(buf, "}")) || (buf[0] == '}')) {
- break;
- }
- if (!indent) {
- if ((p1 = strstr(buf, ", \n")))
- sprintf(p1, "\n");
- fprintf(pc->saved_fp, "%s", buf);
- break;
- }
- if (strstr(buf, "}") &&
- (count_leading_spaces(buf) == indent)) {
- if ((p1 = strstr(buf, "}, \n")))
- sprintf(p1, "}\n");
- fprintf(pc->saved_fp, "%s", buf);
- break;
- }
- fprintf(pc->saved_fp, "%s", buf);
- on++;
- }
- }
- if (array) {
- on = array = FALSE;
- on = 0;
- goto next_item;
- }
- break;
- case PARSE_FOR_DECLARATION:
- last_open_bracket = curpos = 0;
- sprintf(lookfor1, " %s;", s);
- sprintf(lookfor2, "*%s;", s);
- sprintf(lookfor3, " %s[", s);
- sprintf(lookfor4, "*%s[", s);
- sprintf(lookfor5, " %s :", s);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- indent = count_leading_spaces(buf);
- switch (indent)
- {
- case 0:
- curpos = ftell(pc->tmpfile);
- continue;
- case INITIAL_INDENT:
- if (strstr(buf, "{"))
- last_open_bracket = curpos;
- break;
- default:
- if (!on && (indent != INITIAL_INDENT))
- continue;
- }
- if (strstr(buf, lookfor1) ||
- strstr(buf, lookfor2) ||
- strstr(buf, lookfor3) ||
- strstr(buf, lookfor4) ||
- strstr(buf, lookfor5)) {
- if (strstr(buf, "}") && !on) {
- on = TRUE;
- fseek(pc->tmpfile, last_open_bracket,
- SEEK_SET);
- } else {
- print_verbatim(pc->saved_fp, buf);
- if (indent == INITIAL_INDENT)
- break;
- }
- }
- else if (on)
- print_verbatim(pc->saved_fp, buf);
- curpos = ftell(pc->tmpfile);
- }
- break;
- }
- }
- /*
- * Dig out a member name from a formatted gdb structure declaration dump,
- * and print its offset from the named structure passed in.
- */
- static int
- show_member_offset(FILE *ofp, struct datatype_member *dm, char *inbuf)
- {
- int i, c, len;
- long offset;
- char *t1, *target;
- char *arglist[MAXARGS];
- char buf1[BUFSIZE];
- char fmt[BUFSIZE];
- char workbuf[BUFSIZE];
- int end_of_block;
- if (!STRNEQ(inbuf, " ")) {
- fprintf(ofp, "rejecting: %s", inbuf);
- return FALSE;
- }
- if (STRNEQ(inbuf, " union {"))
- dm->flags |= IN_UNION;
- if (STRNEQ(inbuf, " struct {"))
- dm->flags |= IN_STRUCT;
- end_of_block = STRNEQ(inbuf, " } ");
- switch (*gdb_output_radix)
- {
- default:
- case 10:
- sprintf(buf1, "%ld", dm->size);
- break;
- case 16:
- sprintf(buf1, "0x%lx", dm->size);
- }
- len = strlen(buf1) + 4;
- strcpy(workbuf, inbuf);
- c = parse_line(workbuf, arglist);
- target = NULL;
- if (strstr(inbuf, ":")) {
- for (i = 0; i < c; i++) {
- if (i && STREQ(arglist[i], ":")) {
- target = arglist[i-1];
- break;
- }
- }
- } else if (c) {
- for (i = 0; i < c; i++) {
- if (STRNEQ(arglist[i], "(*")) {
- target = arglist[i]+2;
- if (!(t1 = strstr(target, ")")))
- continue;
- *t1 = NULLCHAR;
- break;
- }
- }
- if (i == c) {
- target = arglist[c-1];
- if (!strstr(target, ";"))
- target = NULL;
- }
- }
- if (!target)
- goto do_empty_offset;
- null_first_space(clean_line(replace_string(target, "*[];()", ' ')));
- if (strlen(target) == 0)
- goto do_empty_offset;
-
- if (dm->member && !STREQ(dm->member, target)) {
- if (end_of_block)
- dm->flags &= ~(IN_UNION|IN_STRUCT);
- return FALSE;
- }
- offset = MEMBER_OFFSET(dm->name, target);
- if (offset == -1)
- offset = ANON_MEMBER_OFFSET(dm->name, target);
- if (offset == -1)
- goto do_empty_offset;
- if (end_of_block && dm->member) {
- if (dm->vaddr)
- sprintf(buf1, " [%lx]", offset + dm->vaddr);
- else
- sprintf(buf1, *gdb_output_radix == 10 ?
- " [%ld]" : " [0x%lx]", offset);
- sprintf(fmt, "%c%ds", '%', len+1);
- fprintf(ofp, fmt, " ");
- switch (dm->flags & (IN_UNION|IN_STRUCT))
- {
- case IN_UNION:
- fprintf(ofp, "union {\n");
- break;
- case IN_STRUCT:
- fprintf(ofp, "struct {\n");
- break;
- }
- dm->flags &= ~(IN_UNION|IN_STRUCT);
- }
- if (dm->vaddr)
- sprintf(buf1, " [%lx]", offset + dm->vaddr);
- else
- sprintf(buf1, *gdb_output_radix == 10 ? " [%ld]" : " [0x%lx]", offset);
- sprintf(fmt, "%c%ds", '%', len);
- fprintf(ofp, fmt, buf1);
- fprintf(ofp, "%s", &inbuf[3]);
- return TRUE;
- do_empty_offset:
- if (end_of_block)
- dm->flags &= ~(IN_UNION|IN_STRUCT);
- if (dm->member)
- return FALSE;
-
- len = strlen(buf1)+1;
- fprintf(ofp, "%s%s", space(len), inbuf);
- return FALSE;
- }
- /*
- * Get and store the size of a "known" array. This function is only called
- * once per requested array; after the first time, ARRAY_LENGTH() should be
- * used.
- *
- * For data symbols, get_symbol_type() does the work.
- * For structure member arrays, datatype_info() does the work.
- * For two-dimension arrays, or if the designated function above fails,
- * then just parse "whatis" or "ptype" commands as a last resort.
- */
- int
- get_array_length(char *s, int *two_dim, long entry_size)
- {
- char copy[BUFSIZE];
- char buf[BUFSIZE];
- char lookfor1[BUFSIZE];
- char lookfor2[BUFSIZE];
- int retval;
- struct datatype_member datatype_member, *dm;
- struct gnu_request gnu_request, *req;
- char *p1, *p2;
-
- strcpy(copy, s);
- dm = &datatype_member;
- BZERO(dm, sizeof(struct datatype_member));
- if ((retval = builtin_array_length(s, 0, two_dim)))
- return retval;
- /* symbol_search cannot be done with just kernel type information */
- if (!(LKCD_KERNTYPES()) && symbol_search(s)) {
- if (!two_dim) {
- req = &gnu_request;
- if ((get_symbol_type(copy, NULL, req) ==
- TYPE_CODE_ARRAY) && req->target_typecode &&
- req->target_length) {
- retval = req->length / req->target_length;
- goto store_builtin;
- }
- }
- sprintf(buf, "whatis %s", s);
- } else {
- if (arg_to_datatype(copy, dm, RETURN_ON_ERROR)) {
- if (!dm->member)
- goto store_builtin;
- datatype_info(dm->name, dm->member, dm);
- switch (dm->type)
- {
- case UNION_REQUEST:
- if (entry_size && dm->member_size &&
- (dm->member_typecode == TYPE_CODE_ARRAY)) {
- retval = dm->member_size/entry_size;
- goto store_builtin;
- }
- sprintf(buf, "ptype union %s", dm->name);
- break;
- case STRUCT_REQUEST:
- if (entry_size && dm->member_size &&
- (dm->member_typecode == TYPE_CODE_ARRAY)) {
- retval = dm->member_size/entry_size;
- goto store_builtin;
- }
- sprintf(buf, "ptype struct %s", dm->name);
- break;
- default:
- goto store_builtin;
- }
- sprintf(lookfor1, " %s[", dm->member);
- sprintf(lookfor2, "*%s[", dm->member);
- } else
- goto store_builtin;
- }
- open_tmpfile2();
- if (two_dim)
- *two_dim = 0;
- gdb_pass_through(buf, pc->tmpfile2, 0);
- rewind(pc->tmpfile2);
- while (fgets(buf, BUFSIZE, pc->tmpfile2)) {
- if (STRNEQ(buf, "type = ") &&
- (p1 = strstr(buf, "[")) &&
- (p2 = strstr(buf, "]")) &&
- (index(buf, '[') == rindex(buf, '['))) {
- *p2 = NULLCHAR;
- p1++;
- if (strlen(p1)) {
- retval = atoi(p1);
- break;
- }
- }
- if (STRNEQ(buf, "type = ") &&
- (count_chars(buf, '[') == 2) &&
- (count_chars(buf, ']') == 2) && two_dim) {
- p1 = strstr(buf, "[");
- p2 = strstr(buf, "]");
- *p2 = NULLCHAR;
- p1++;
- if (strlen(p1))
- *two_dim = atoi(p1);
- else
- break;
- p2++;
- p1 = strstr(p2, "[");
- p2 = strstr(p1, "]");
- p1++;
- if (strlen(p1))
- retval = atoi(p1);
- else {
- retval = 0;
- *two_dim = 0;
- break;
- }
- break;
- }
- if (dm->type &&
- (strstr(buf, lookfor1) || strstr(buf, lookfor2)) &&
- (p1 = strstr(buf, "[")) &&
- (p2 = strstr(buf, "]")) &&
- (index(buf, '[') == rindex(buf, '['))) {
- *p2 = NULLCHAR;
- p1++;
- if (strlen(p1)) {
- retval = atoi(p1);
- break;
- }
- }
- }
- close_tmpfile2();
- store_builtin:
- return (builtin_array_length(s, retval, two_dim));
- }
- /*
- * Get and store the size of a "known" array.
- * A wrapper for get_array_length(), for cases in which
- * the name of the result to be stored is different from the
- * structure.member to be evaluated.
- */
- int
- get_array_length_alt(char *name, char *s, int *two_dim, long entry_size)
- {
- int retval;
- retval = get_array_length(s, two_dim, entry_size);
- if (retval)
- retval = builtin_array_length(name, retval, two_dim);
- return retval;
- }
- /*
- * Designed for use by non-debug kernels, but used by all.
- */
- int
- builtin_array_length(char *s, int len, int *two_dim)
- {
- int *lenptr;
- int *dimptr;
- lenptr = dimptr = NULL;
- if (STREQ(s, "kmem_cache_s.name"))
- lenptr = &array_table.kmem_cache_s_name;
- else if (STREQ(s, "kmem_cache_s.c_name"))
- lenptr = &array_table.kmem_cache_s_c_name;
- else if (STREQ(s, "kmem_cache_s.array"))
- lenptr = &array_table.kmem_cache_s_array;
- else if (STREQ(s, "kmem_cache.array"))
- lenptr = &array_table.kmem_cache_s_array;
- else if (STREQ(s, "kmem_cache_s.cpudata"))
- lenptr = &array_table.kmem_cache_s_cpudata;
- else if (STREQ(s, "log_buf"))
- lenptr = &array_table.log_buf;
- else if (STREQ(s, "irq_desc") || STREQ(s, "_irq_desc"))
- lenptr = &array_table.irq_desc;
- else if (STREQ(s, "irq_action"))
- lenptr = &array_table.irq_action;
- else if (STREQ(s, "timer_vec.vec"))
- lenptr = &array_table.timer_vec_vec;
- else if (STREQ(s, "timer_vec_root.vec"))
- lenptr = &array_table.timer_vec_root_vec;
- else if (STREQ(s, "tvec_s.vec"))
- lenptr = &array_table.tvec_s_vec;
- else if (STREQ(s, "tvec_root_s.vec"))
- lenptr = &array_table.tvec_root_s_vec;
- else if (STREQ(s, "net_device.name"))
- lenptr = &array_table.net_device_name;
- else if (STREQ(s, "neigh_table.hash_buckets"))
- lenptr = &array_table.neigh_table_hash_buckets;
- else if (STREQ(s, "neighbour.ha"))
- lenptr = &array_table.neighbour_ha;
- else if (STREQ(s, "swap_info"))
- lenptr = &array_table.swap_info;
- else if (STREQ(s, "page_hash_table"))
- lenptr = &array_table.page_hash_table;
- else if (STREQ(s, "pglist_data.node_zones"))
- lenptr = &array_table.pglist_data_node_zones;
- else if (STREQ(s, "zone_struct.free_area"))
- lenptr = &array_table.zone_struct_free_area;
- else if (STREQ(s, "zone.free_area"))
- lenptr = &array_table.zone_free_area;
- else if (STREQ(s, "prio_array.queue"))
- lenptr = &array_table.prio_array_queue;
- else if (STREQ(s, "height_to_maxindex"))
- lenptr = &array_table.height_to_maxindex;
- else if (STREQ(s, "pid_hash"))
- lenptr = &array_table.pid_hash;
- else if (STREQ(s, "free_area")) {
- lenptr = &array_table.free_area;
- if (two_dim)
- dimptr = &array_table.free_area_DIMENSION;
- } else if (STREQ(s, "kmem_cache.node"))
- lenptr = &array_table.kmem_cache_node;
- else if (STREQ(s, "kmem_cache.cpu_slab"))
- lenptr = &array_table.kmem_cache_cpu_slab;
- else if (STREQ(s, "rt_prio_array.queue"))
- lenptr = &array_table.rt_prio_array_queue;
- if (!lenptr) /* not stored */
- return(len);
- if (*lenptr) { /* pre-set */
- if (dimptr && two_dim)
- *two_dim = *dimptr;
- return(*lenptr);
- }
- if (len) {
- *lenptr = len; /* initialize passed-in value(s) */
- if (dimptr && two_dim)
- *dimptr = *two_dim;
- return(len);
- }
- return(0); /* in table, but not set yet */
- }
- /*
- * "help -o" output
- */
- void
- dump_offset_table(char *spec, ulong makestruct)
- {
- char buf[BUFSIZE], *p1;
- char revname[BUFSIZE];
- struct new_utsname *uts;
- long long data_debug;
- data_debug = pc->flags & DATADEBUG;
- pc->flags &= ~DATADEBUG;
- uts = NULL;
- if (makestruct) {
- uts = &kt->utsname;
- sprintf(revname, "%s_%s", pc->machine_type, uts->release);
- p1 = revname + strlen(pc->machine_type);
- while (*p1) {
- if (((*p1 >= '0') && (*p1 <= '9')) ||
- ((*p1 >= 'a') && (*p1 <= 'z')) ||
- ((*p1 >= 'A') && (*p1 <= 'Z')))
- p1++;
- else
- *p1++ = '_';
- }
- }
- if (spec || makestruct)
- open_tmpfile();
- fprintf(fp, " offset_table:\n");
- fprintf(fp, " list_head_next: %ld\n",
- OFFSET(list_head_next));
- fprintf(fp, " list_head_prev: %ld\n",
- OFFSET(list_head_prev));
- fprintf(fp, " task_struct_pid: %ld\n",
- OFFSET(task_struct_pid));
- fprintf(fp, " task_struct_state: %ld\n",
- OFFSET(task_struct_state));
- fprintf(fp, " task_struct_exit_state: %ld\n",
- OFFSET(task_struct_exit_state));
- fprintf(fp, " task_struct_comm: %ld\n",
- OFFSET(task_struct_comm));
- fprintf(fp, " task_struct_mm: %ld\n",
- OFFSET(task_struct_mm));
- fprintf(fp, " task_struct_tss: %ld\n",
- OFFSET(task_struct_tss));
- fprintf(fp, " task_struct_thread: %ld\n",
- OFFSET(task_struct_thread));
- fprintf(fp, " task_struct_active_mm: %ld\n",
- OFFSET(task_struct_active_mm));
- fprintf(fp, " task_struct_tss_eip: %ld\n",
- OFFSET(task_struct_tss_eip));
- fprintf(fp, " task_struct_tss_esp: %ld\n",
- OFFSET(task_struct_tss_esp));
- fprintf(fp, " task_struct_tss_ksp: %ld\n",
- OFFSET(task_struct_tss_ksp));
- fprintf(fp, " task_struct_thread_eip: %ld\n",
- OFFSET(task_struct_thread_eip));
- fprintf(fp, " task_struct_thread_esp: %ld\n",
- OFFSET(task_struct_thread_esp));
- fprintf(fp, " task_struct_thread_ksp: %ld\n",
- OFFSET(task_struct_thread_ksp));
- fprintf(fp, " task_struct_thread_context_fp: %ld\n",
- OFFSET(task_struct_thread_context_fp));
- fprintf(fp, " task_struct_thread_context_sp: %ld\n",
- OFFSET(task_struct_thread_context_sp));
- fprintf(fp, " task_struct_thread_context_pc: %ld\n",
- OFFSET(task_struct_thread_context_pc));
- fprintf(fp, " task_struct_processor: %ld\n",
- OFFSET(task_struct_processor));
- fprintf(fp, " task_struct_p_pptr: %ld\n",
- OFFSET(task_struct_p_pptr));
- fprintf(fp, " task_struct_parent: %ld\n",
- OFFSET(task_struct_parent));
- fprintf(fp, " task_struct_has_cpu: %ld\n",
- OFFSET(task_struct_has_cpu));
- fprintf(fp, " task_struct_cpus_runnable: %ld\n",
- OFFSET(task_struct_cpus_runnable));
- fprintf(fp, " task_struct_next_task: %ld\n",
- OFFSET(task_struct_next_task));
- fprintf(fp, " task_struct_files: %ld\n",
- OFFSET(task_struct_files));
- fprintf(fp, " task_struct_fs: %ld\n",
- OFFSET(task_struct_fs));
- fprintf(fp, " task_struct_pidhash_next: %ld\n",
- OFFSET(task_struct_pidhash_next));
- fprintf(fp, " task_struct_next_run: %ld\n",
- OFFSET(task_struct_next_run));
- fprintf(fp, " task_struct_flags: %ld\n",
- OFFSET(task_struct_flags));
- fprintf(fp, " task_struct_sig: %ld\n",
- OFFSET(task_struct_sig));
- fprintf(fp, " task_struct_signal: %ld\n",
- OFFSET(task_struct_signal));
- fprintf(fp, " task_struct_blocked: %ld\n",
- OFFSET(task_struct_blocked));
- fprintf(fp, " task_struct_sigpending: %ld\n",
- OFFSET(task_struct_sigpending));
- fprintf(fp, " task_struct_pending: %ld\n",
- OFFSET(task_struct_pending));
- fprintf(fp, " task_struct_sigqueue: %ld\n",
- OFFSET(task_struct_sigqueue));
- fprintf(fp, " task_struct_sighand: %ld\n",
- OFFSET(task_struct_sighand));
- fprintf(fp, " task_struct_run_list: %ld\n",
- OFFSET(task_struct_run_list));
- fprintf(fp, " task_struct_pgrp: %ld\n",
- OFFSET(task_struct_pgrp));
- fprintf(fp, " task_struct_tgid: %ld\n",
- OFFSET(task_struct_tgid));
- fprintf(fp, " task_struct_namespace: %ld\n",
- OFFSET(task_struct_namespace));
- fprintf(fp, " task_struct_rss_stat: %ld\n",
- OFFSET(task_struct_rss_stat));
- fprintf(fp, " task_rss_stat_count: %ld\n",
- OFFSET(task_rss_stat_count));
- fprintf(fp, " task_struct_pids: %ld\n",
- OFFSET(task_struct_pids));
- fprintf(fp, " task_struct_last_run: %ld\n",
- OFFSET(task_struct_last_run));
- fprintf(fp, " task_struct_timestamp: %ld\n",
- OFFSET(task_struct_timestamp));
- fprintf(fp, " task_struct_sched_info: %ld\n",
- OFFSET(task_struct_sched_info));
- fprintf(fp, " task_struct_rt: %ld\n",
- OFFSET(task_struct_rt));
- fprintf(fp, " sched_rt_entity_run_list: %ld\n",
- OFFSET(sched_rt_entity_run_list));
- fprintf(fp, " sched_info_last_arrival: %ld\n",
- OFFSET(sched_info_last_arrival));
- fprintf(fp, " task_struct_thread_info: %ld\n",
- OFFSET(task_struct_thread_info));
- fprintf(fp, " task_struct_nsproxy: %ld\n",
- OFFSET(task_struct_nsproxy));
- fprintf(fp, " task_struct_rlim: %ld\n",
- OFFSET(task_struct_rlim));
- fprintf(fp, " task_struct_prio: %ld\n",
- OFFSET(task_struct_prio));
- fprintf(fp, " task_struct_on_rq: %ld\n",
- OFFSET(task_struct_on_rq));
- fprintf(fp, " thread_info_task: %ld\n",
- OFFSET(thread_info_task));
- fprintf(fp, " thread_info_cpu: %ld\n",
- OFFSET(thread_info_cpu));
- fprintf(fp, " thread_info_flags: %ld\n",
- OFFSET(thread_info_flags));
- fprintf(fp, " thread_info_previous_esp: %ld\n",
- OFFSET(thread_info_previous_esp));
- fprintf(fp, " nsproxy_mnt_ns: %ld\n",
- OFFSET(nsproxy_mnt_ns));
- fprintf(fp, " mnt_namespace_root: %ld\n",
- OFFSET(mnt_namespace_root));
- fprintf(fp, " mnt_namespace_list: %ld\n",
- OFFSET(mnt_namespace_list));
- fprintf(fp, " pid_link_pid: %ld\n",
- OFFSET(pid_link_pid));
- fprintf(fp, " pid_hash_chain: %ld\n",
- OFFSET(pid_hash_chain));
- fprintf(fp, " pid_numbers: %ld\n",
- OFFSET(pid_numbers));
- fprintf(fp, " upid_nr: %ld\n",
- OFFSET(upid_nr));
- fprintf(fp, " upid_ns: %ld\n",
- OFFSET(upid_ns));
- fprintf(fp, " upid_pid_chain: %ld\n",
- OFFSET(upid_pid_chain));
- fprintf(fp, " pid_tasks: %ld\n",
- OFFSET(pid_tasks));
- fprintf(fp, " hlist_node_next: %ld\n",
- OFFSET(hlist_node_next));
- fprintf(fp, " hlist_node_pprev: %ld\n",
- OFFSET(hlist_node_pprev));
- fprintf(fp, " pid_pid_chain: %ld\n",
- OFFSET(pid_pid_chain));
- fprintf(fp, " thread_struct_eip: %ld\n",
- OFFSET(thread_struct_eip));
- fprintf(fp, " thread_struct_esp: %ld\n",
- OFFSET(thread_struct_esp));
- fprintf(fp, " thread_struct_ksp: %ld\n",
- OFFSET(thread_struct_ksp));
- fprintf(fp, " thread_struct_rip: %ld\n",
- OFFSET(thread_struct_rip));
- fprintf(fp, " thread_struct_rsp: %ld\n",
- OFFSET(thread_struct_rsp));
- fprintf(fp, " thread_struct_rsp0: %ld\n",
- OFFSET(thread_struct_rsp0));
- fprintf(fp, " signal_struct_count: %ld\n",
- OFFSET(signal_struct_count));
- fprintf(fp, " signal_struct_nr_threads: %ld\n",
- OFFSET(signal_struct_nr_threads));
- fprintf(fp, " signal_struct_action: %ld\n",
- OFFSET(signal_struct_action));
- fprintf(fp, " signal_struct_shared_pending: %ld\n",
- OFFSET(signal_struct_shared_pending));
- fprintf(fp, " signal_struct_rlim: %ld\n",
- OFFSET(signal_struct_rlim));
- fprintf(fp, " task_struct_start_time: %ld\n",
- OFFSET(task_struct_start_time));
- fprintf(fp, " task_struct_times: %ld\n",
- OFFSET(task_struct_times));
- fprintf(fp, " task_struct_cpu: %ld\n",
- OFFSET(task_struct_cpu));
- fprintf(fp, " task_struct_utime: %ld\n",
- OFFSET(task_struct_utime));
- fprintf(fp, " task_struct_stime: %ld\n",
- OFFSET(task_struct_stime));
- fprintf(fp, " tms_tms_utime: %ld\n",
- OFFSET(tms_tms_utime));
- fprintf(fp, " tms_tms_stime: %ld\n",
- OFFSET(tms_tms_stime));
- fprintf(fp, " timekeeper_xtime: %ld\n",
- OFFSET(timekeeper_xtime));
- fprintf(fp, " timekeeper_xtime_sec: %ld\n",
- OFFSET(timekeeper_xtime_sec));
- fprintf(fp, " k_sigaction_sa: %ld\n",
- OFFSET(k_sigaction_sa));
- fprintf(fp, " sigaction_sa_handler: %ld\n",
- OFFSET(sigaction_sa_handler));
- fprintf(fp, " sigaction_sa_flags: %ld\n",
- OFFSET(sigaction_sa_flags));
- fprintf(fp, " sigaction_sa_mask: %ld\n",
- OFFSET(sigaction_sa_mask));
- fprintf(fp, " sigpending_head: %ld\n",
- OFFSET(sigpending_head));
- fprintf(fp, " sigpending_signal: %ld\n",
- OFFSET(sigpending_signal));
- fprintf(fp, " sigpending_list: %ld\n",
- OFFSET(sigpending_list));
- fprintf(fp, " signal_queue_next: %ld\n",
- OFFSET(signal_queue_next));
- fprintf(fp, " signal_queue_info: %ld\n",
- OFFSET(signal_queue_info));
- fprintf(fp, " sigqueue_next: %ld\n",
- OFFSET(sigqueue_next));
- fprintf(fp, " sigqueue_info: %ld\n",
- OFFSET(sigqueue_info));
- fprintf(fp, " sigqueue_list: %ld\n",
- OFFSET(sigqueue_list));
- fprintf(fp, " sighand_struct_action: %ld\n",
- OFFSET(sighand_struct_action));
- fprintf(fp, " siginfo_si_signo: %ld\n",
- OFFSET(siginfo_si_signo));
- fprintf(fp, " thread_struct_fph: %ld\n",
- OFFSET(thread_struct_fph));
- fprintf(fp, " thread_struct_cr3: %ld\n",
- OFFSET(thread_struct_cr3));
- fprintf(fp, " thread_struct_ptbr: %ld\n",
- OFFSET(thread_struct_ptbr));
- fprintf(fp, " thread_struct_pg_tables: %ld\n",
- OFFSET(thread_struct_pg_tables));
- fprintf(fp, " switch_stack_r26: %ld\n",
- OFFSET(switch_stack_r26));
- fprintf(fp, " switch_stack_b0: %ld\n",
- OFFSET(switch_stack_b0));
- fprintf(fp, " switch_stack_ar_bspstore: %ld\n",
- OFFSET(switch_stack_ar_bspstore));
- fprintf(fp, " switch_stack_ar_pfs: %ld\n",
- OFFSET(switch_stack_ar_pfs));
- fprintf(fp, " switch_stack_ar_rnat: %ld\n",
- OFFSET(switch_stack_ar_rnat));
- fprintf(fp, " switch_stack_pr: %ld\n",
- OFFSET(switch_stack_pr));
- fprintf(fp, " cpuinfo_ia64_proc_freq: %ld\n",
- OFFSET(cpuinfo_ia64_proc_freq));
- fprintf(fp, " cpuinfo_ia64_unimpl_va_mask: %ld\n",
- OFFSET(cpuinfo_ia64_unimpl_va_mask));
- fprintf(fp, " cpuinfo_ia64_unimpl_pa_mask: %ld\n",
- OFFSET(cpuinfo_ia64_unimpl_pa_mask));
- fprintf(fp, " device_node_type: %ld\n",
- OFFSET(device_node_type));
- fprintf(fp, " device_node_allnext: %ld\n",
- OFFSET(device_node_allnext));
- fprintf(fp, " device_node_properties: %ld\n",
- OFFSET(device_node_properties));
- fprintf(fp, " property_name: %ld\n",
- OFFSET(property_name));
- fprintf(fp, " property_value: %ld\n",
- OFFSET(property_value));
- fprintf(fp, " property_next: %ld\n",
- OFFSET(property_next));
- fprintf(fp, " machdep_calls_setup_residual: %ld\n",
- OFFSET(machdep_calls_setup_residual));
- fprintf(fp, " RESIDUAL_VitalProductData: %ld\n",
- OFFSET(RESIDUAL_VitalProductData));
- fprintf(fp, " VPD_ProcessorHz: %ld\n",
- OFFSET(VPD_ProcessorHz));
- fprintf(fp, " bd_info_bi_intfreq: %ld\n",
- OFFSET(bd_info_bi_intfreq));
- fprintf(fp, " hwrpb_struct_cycle_freq: %ld\n",
- OFFSET(hwrpb_struct_cycle_freq));
- fprintf(fp, " hwrpb_struct_processor_offset: %ld\n",
- OFFSET(hwrpb_struct_processor_offset));
- fprintf(fp, " hwrpb_struct_processor_size: %ld\n",
- OFFSET(hwrpb_struct_processor_size));
- fprintf(fp, " percpu_struct_halt_PC: %ld\n",
- OFFSET(percpu_struct_halt_PC));
- fprintf(fp, " percpu_struct_halt_ra: %ld\n",
- OFFSET(percpu_struct_halt_ra));
- fprintf(fp, " percpu_struct_halt_pv: %ld\n",
- OFFSET(percpu_struct_halt_pv));
- fprintf(fp, " mm_struct_mmap: %ld\n",
- OFFSET(mm_struct_mmap));
- fprintf(fp, " mm_struct_pgd: %ld\n",
- OFFSET(mm_struct_pgd));
- fprintf(fp, " mm_struct_rss: %ld\n",
- OFFSET(mm_struct_rss));
- fprintf(fp, " mm_struct_anon_rss: %ld\n",
- OFFSET(mm_struct_anon_rss));
- fprintf(fp, " mm_struct_file_rss: %ld\n",
- OFFSET(mm_struct_file_rss));
- fprintf(fp, " mm_struct_total_vm: %ld\n",
- OFFSET(mm_struct_total_vm));
- fprintf(fp, " mm_struct_start_code: %ld\n",
- OFFSET(mm_struct_start_code));
- fprintf(fp, " mm_struct_arg_start: %ld\n",
- OFFSET(mm_struct_arg_start));
- fprintf(fp, " mm_struct_arg_end: %ld\n",
- OFFSET(mm_struct_arg_end));
- fprintf(fp, " mm_struct_env_start: %ld\n",
- OFFSET(mm_struct_env_start));
- fprintf(fp, " mm_struct_env_end: %ld\n",
- OFFSET(mm_struct_env_end));
- fprintf(fp, " mm_struct_rss_stat: %ld\n",
- OFFSET(mm_struct_rss_stat));
- fprintf(fp, " mm_rss_stat_count: %ld\n",
- OFFSET(mm_rss_stat_count));
- fprintf(fp, " vm_area_struct_vm_mm: %ld\n",
- OFFSET(vm_area_struct_vm_mm));
- fprintf(fp, " vm_area_struct_vm_next: %ld\n",
- OFFSET(vm_area_struct_vm_next));
- fprintf(fp, " vm_area_struct_vm_start: %ld\n",
- OFFSET(vm_area_struct_vm_start));
- fprintf(fp, " vm_area_struct_vm_end: %ld\n",
- OFFSET(vm_area_struct_vm_end));
- fprintf(fp, " vm_area_struct_vm_flags: %ld\n",
- OFFSET(vm_area_struct_vm_flags));
- fprintf(fp, " vm_area_struct_vm_file: %ld\n",
- OFFSET(vm_area_struct_vm_file));
- fprintf(fp, " vm_area_struct_vm_offset: %ld\n",
- OFFSET(vm_area_struct_vm_offset));
- fprintf(fp, " vm_area_struct_vm_pgoff: %ld\n",
- OFFSET(vm_area_struct_vm_pgoff));
- fprintf(fp, " vm_struct_addr: %ld\n",
- OFFSET(vm_struct_addr));
- fprintf(fp, " vm_struct_size: %ld\n",
- OFFSET(vm_struct_size));
- fprintf(fp, " vm_struct_next: %ld\n",
- OFFSET(vm_struct_next));
- fprintf(fp, " vmap_area_va_start: %ld\n",
- OFFSET(vmap_area_va_start));
- fprintf(fp, " vmap_area_va_end: %ld\n",
- OFFSET(vmap_area_va_end));
- fprintf(fp, " vmap_area_list: %ld\n",
- OFFSET(vmap_area_list));
- fprintf(fp, " vmap_area_vm: %ld\n",
- OFFSET(vmap_area_vm));
- fprintf(fp, " vmap_area_flags: %ld\n",
- OFFSET(vmap_area_flags));
- fprintf(fp, " module_size_of_struct: %ld\n",
- OFFSET(module_size_of_struct));
- fprintf(fp, " module_next: %ld\n",
- OFFSET(module_next));
- fprintf(fp, " module_name: %ld\n",
- OFFSET(module_name));
- fprintf(fp, " module_syms: %ld\n",
- OFFSET(module_syms));
- fprintf(fp, " module_nsyms: %ld\n",
- OFFSET(module_nsyms));
- fprintf(fp, " module_size: %ld\n",
- OFFSET(module_size));
- fprintf(fp, " module_flags: %ld\n",
- OFFSET(module_flags));
- fprintf(fp, " module_num_syms: %ld\n",
- OFFSET(module_num_syms));
- fprintf(fp, " module_gpl_syms: %ld\n",
- OFFSET(module_gpl_syms));
- fprintf(fp, " module_num_gpl_syms: %ld\n",
- OFFSET(module_num_gpl_syms));
- fprintf(fp, " module_list: %ld\n",
- OFFSET(module_list));
- fprintf(fp, " module_module_core: %ld\n",
- OFFSET(module_module_core));
- fprintf(fp, " module_core_size: %ld\n",
- OFFSET(module_core_size));
- fprintf(fp, " module_core_text_size: %ld\n",
- OFFSET(module_core_text_size));
- fprintf(fp, " module_init_size: %ld\n",
- OFFSET(module_init_size));
- fprintf(fp, " module_init_text_size: %ld\n",
- OFFSET(module_init_text_size));
- fprintf(fp, " module_module_init: %ld\n",
- OFFSET(module_module_init));
- fprintf(fp, " module_num_symtab: %ld\n",
- OFFSET(module_num_symtab));
- fprintf(fp, " module_symtab: %ld\n",
- OFFSET(module_symtab));
- fprintf(fp, " module_strtab: %ld\n",
- OFFSET(module_strtab));
- fprintf(fp, " module_percpu: %ld\n",
- OFFSET(module_percpu));
- fprintf(fp, " module_sect_attrs: %ld\n",
- OFFSET(module_sect_attrs));
- fprintf(fp, " module_sect_attrs_attrs: %ld\n",
- OFFSET(module_sect_attrs_attrs));
- fprintf(fp, " module_sect_attrs_nsections: %ld\n",
- OFFSET(module_sect_attrs_nsections));
- fprintf(fp, " module_sect_attr_mattr: %ld\n",
- OFFSET(module_sect_attr_mattr));
- fprintf(fp, " module_sect_attr_name: %ld\n",
- OFFSET(module_sect_attr_name));
- fprintf(fp, " module_sect_attr_address: %ld\n",
- OFFSET(module_sect_attr_address));
- fprintf(fp, " attribute_owner: %ld\n",
- OFFSET(attribute_owner));
- fprintf(fp, " module_sect_attr_attr: %ld\n",
- OFFSET(module_sect_attr_attr));
- fprintf(fp, " module_sections_attrs: %ld\n",
- OFFSET(module_sections_attrs));
- fprintf(fp, " module_attribute_attr: %ld\n",
- OFFSET(module_attribute_attr));
- fprintf(fp, " module_kallsyms_start: %ld\n",
- OFFSET(module_kallsyms_start));
- fprintf(fp, " kallsyms_header_sections: %ld\n",
- OFFSET(kallsyms_header_sections));
- fprintf(fp, " kallsyms_header_section_off: %ld\n",
- OFFSET(kallsyms_header_section_off));
- fprintf(fp, " kallsyms_header_symbols: %ld\n",
- OFFSET(kallsyms_header_symbols));
- fprintf(fp, " kallsyms_header_symbol_off: %ld\n",
- OFFSET(kallsyms_header_symbol_off));
- fprintf(fp, " kallsyms_header_string_off: %ld\n",
- OFFSET(kallsyms_header_string_off));
- fprintf(fp, " kallsyms_symbol_section_off: %ld\n",
- OFFSET(kallsyms_symbol_section_off));
- fprintf(fp, " kallsyms_symbol_symbol_addr: %ld\n",
- OFFSET(kallsyms_symbol_symbol_addr));
- fprintf(fp, " kallsyms_symbol_name_off: %ld\n",
- OFFSET(kallsyms_symbol_name_off));
- fprintf(fp, " kallsyms_section_start: %ld\n",
- OFFSET(kallsyms_section_start));
- fprintf(fp, " kallsyms_section_size: %ld\n",
- OFFSET(kallsyms_section_size));
- fprintf(fp, " kallsyms_section_name_off: %ld\n",
- OFFSET(kallsyms_section_name_off));
- fprintf(fp, " module_taints: %ld\n",
- OFFSET(module_taints));
- fprintf(fp, " module_license_gplok: %ld\n",
- OFFSET(module_license_gplok));
- fprintf(fp, " module_gpgsig_ok: %ld\n",
- OFFSET(module_gpgsig_ok));
- fprintf(fp, " tnt_bit: %ld\n", OFFSET(tnt_bit));
- fprintf(fp, " tnt_true: %ld\n", OFFSET(tnt_true));
- fprintf(fp, " tnt_false: %ld\n", OFFSET(tnt_false));
- fprintf(fp, " page_next: %ld\n", OFFSET(page_next));
- fprintf(fp, " page_prev: %ld\n", OFFSET(page_prev));
- fprintf(fp, " page_next_hash: %ld\n",
- OFFSET(page_next_hash));
- fprintf(fp, " page_list: %ld\n",
- OFFSET(page_list));
- fprintf(fp, " page_list_next: %ld\n",
- OFFSET(page_list_next));
- fprintf(fp, " page_list_prev: %ld\n",
- OFFSET(page_list_prev));
- fprintf(fp, " page_inode: %ld\n",
- OFFSET(page_inode));
- fprintf(fp, " page_offset: %ld\n",
- OFFSET(page_offset));
- fprintf(fp, " page_count: %ld\n",
- OFFSET(page_count));
- fprintf(fp, " page_flags: %ld\n",
- OFFSET(page_flags));
- fprintf(fp, " page_mapping: %ld\n",
- OFFSET(page_mapping));
- fprintf(fp, " page_index: %ld\n",
- OFFSET(page_index));
- fprintf(fp, " page_buffers: %ld\n",
- OFFSET(page_buffers));
- fprintf(fp, " page_lru: %ld\n",
- OFFSET(page_lru));
- fprintf(fp, " page_pte: %ld\n",
- OFFSET(page_pte));
- fprintf(fp, " page_inuse: %ld\n",
- OFFSET(page_inuse));
- fprintf(fp, " page_objects: %ld\n",
- OFFSET(page_objects));
- fprintf(fp, " page_slab: %ld\n",
- OFFSET(page_slab));
- fprintf(fp, " page_slab_page: %ld\n",
- OFFSET(page_slab_page));
- fprintf(fp, " page_first_page: %ld\n",
- OFFSET(page_first_page));
- fprintf(fp, " page_freelist: %ld\n",
- OFFSET(page_freelist));
- fprintf(fp, " page_s_mem: %ld\n",
- OFFSET(page_s_mem));
- fprintf(fp, " page_active: %ld\n",
- OFFSET(page_active));
- fprintf(fp, " trace_print_flags_mask: %ld\n",
- OFFSET(trace_print_flags_mask));
- fprintf(fp, " trace_print_flags_name: %ld\n",
- OFFSET(trace_print_flags_name));
- fprintf(fp, " swap_info_struct_swap_file: %ld\n",
- OFFSET(swap_info_struct_swap_file));
- fprintf(fp, " swap_info_struct_swap_vfsmnt: %ld\n",
- OFFSET(swap_info_struct_swap_vfsmnt));
- fprintf(fp, " swap_info_struct_flags: %ld\n",
- OFFSET(swap_info_struct_flags));
- fprintf(fp, " swap_info_struct_swap_map: %ld\n",
- OFFSET(swap_info_struct_swap_map));
- fprintf(fp, " swap_info_struct_swap_device: %ld\n",
- OFFSET(swap_info_struct_swap_device));
- fprintf(fp, " swap_info_struct_prio: %ld\n",
- OFFSET(swap_info_struct_prio));
- fprintf(fp, " swap_info_struct_max: %ld\n",
- OFFSET(swap_info_struct_max));
- fprintf(fp, " swap_info_struct_pages: %ld\n",
- OFFSET(swap_info_struct_pages));
- fprintf(fp, " swap_info_struct_inuse_pages: %ld\n",
- OFFSET(swap_info_struct_inuse_pages));
- fprintf(fp, "swap_info_struct_old_block_size: %ld\n",
- OFFSET(swap_info_struct_old_block_size));
- fprintf(fp, " block_device_bd_inode: %ld\n",
- OFFSET(block_device_bd_inode));
- fprintf(fp, " block_device_bd_list: %ld\n",
- OFFSET(block_device_bd_list));
- fprintf(fp, " block_device_bd_disk: %ld\n",
- OFFSET(block_device_bd_disk));
- fprintf(fp, " address_space_nrpages: %ld\n",
- OFFSET(address_space_nrpages));
- fprintf(fp, " gendisk_major: %ld\n",
- OFFSET(gendisk_major));
- fprintf(fp, " gendisk_fops: %ld\n",
- OFFSET(gendisk_fops));
- fprintf(fp, " gendisk_disk_name: %ld\n",
- OFFSET(gendisk_disk_name));
- fprintf(fp, " irq_desc_t_status: %ld\n",
- OFFSET(irq_desc_t_status));
- fprintf(fp, " irq_desc_t_handler: %ld\n",
- OFFSET(irq_desc_t_handler));
- fprintf(fp, " irq_desc_t_chip: %ld\n",
- OFFSET(irq_desc_t_chip));
- fprintf(fp, " irq_desc_t_action: %ld\n",
- OFFSET(irq_desc_t_action));
- fprintf(fp, " irq_desc_t_depth: %ld\n",
- OFFSET(irq_desc_t_depth));
- fprintf(fp, " irqdesc_action: %ld\n",
- OFFSET(irqdesc_action));
- fprintf(fp, " irqdesc_ctl: %ld\n",
- OFFSET(irqdesc_ctl));
- fprintf(fp, " irqdesc_level: %ld\n",
- OFFSET(irqdesc_level));
- fprintf(fp, " irq_desc_t_irq_data: %ld\n",
- OFFSET(irq_desc_t_irq_data));
- fprintf(fp, " irq_desc_t_kstat_irqs: %ld\n",
- OFFSET(irq_desc_t_kstat_irqs));
- fprintf(fp, " irq_desc_t_affinity: %ld\n",
- OFFSET(irq_desc_t_affinity));
- fprintf(fp, " irq_data_chip: %ld\n",
- OFFSET(irq_data_chip));
- fprintf(fp, " irq_data_affinity: %ld\n",
- OFFSET(irq_data_affinity));
- fprintf(fp, " kernel_stat_irqs: %ld\n",
- OFFSET(kernel_stat_irqs));
- fprintf(fp, " irqaction_handler: %ld\n",
- OFFSET(irqaction_handler));
- fprintf(fp, " irqaction_flags: %ld\n",
- OFFSET(irqaction_flags));
- fprintf(fp, " irqaction_mask: %ld\n",
- OFFSET(irqaction_mask));
- fprintf(fp, " irqaction_name: %ld\n",
- OFFSET(irqaction_name));
- fprintf(fp, " irqaction_dev_id: %ld\n",
- OFFSET(irqaction_dev_id));
- fprintf(fp, " irqaction_next: %ld\n",
- OFFSET(irqaction_next));
-
- fprintf(fp, " hw_interrupt_type_typename: %ld\n",
- OFFSET(hw_interrupt_type_typename));
- fprintf(fp, " hw_interrupt_type_startup: %ld\n",
- OFFSET(hw_interrupt_type_startup));
- fprintf(fp, " hw_interrupt_type_shutdown: %ld\n",
- OFFSET(hw_interrupt_type_shutdown));
- fprintf(fp, " hw_interrupt_type_handle: %ld\n",
- OFFSET(hw_interrupt_type_handle));
- fprintf(fp, " hw_interrupt_type_enable: %ld\n",
- OFFSET(hw_interrupt_type_enable));
- fprintf(fp, " hw_interrupt_type_disable: %ld\n",
- OFFSET(hw_interrupt_type_disable));
- fprintf(fp, " hw_interrupt_type_ack: %ld\n",
- OFFSET(hw_interrupt_type_ack));
- fprintf(fp, " hw_interrupt_type_end: %ld\n",
- OFFSET(hw_interrupt_type_end));
- fprintf(fp, "hw_interrupt_type_set_affinity: %ld\n",
- OFFSET(hw_interrupt_type_set_affinity));
- fprintf(fp, " irq_chip_typename: %ld\n",
- OFFSET(irq_chip_typename));
- fprintf(fp, " irq_chip_startup: %ld\n",
- OFFSET(irq_chip_startup));
- fprintf(fp, " irq_chip_shutdown: %ld\n",
- OFFSET(irq_chip_shutdown));
- fprintf(fp, " irq_chip_enable: %ld\n",
- OFFSET(irq_chip_enable));
- fprintf(fp, " irq_chip_disable: %ld\n",
- OFFSET(irq_chip_disable));
- fprintf(fp, " irq_chip_ack: %ld\n",
- OFFSET(irq_chip_ack));
- fprintf(fp, " irq_chip_mask: %ld\n",
- OFFSET(irq_chip_mask));
- fprintf(fp, " irq_chip_mask_ack: %ld\n",
- OFFSET(irq_chip_mask_ack));
- fprintf(fp, " irq_chip_unmask: %ld\n",
- OFFSET(irq_chip_unmask));
- fprintf(fp, " irq_chip_eoi: %ld\n",
- OFFSET(irq_chip_eoi));
- fprintf(fp, " irq_chip_end: %ld\n",
- OFFSET(irq_chip_end));
- fprintf(fp, " irq_chip_set_affinity: %ld\n",
- OFFSET(irq_chip_set_affinity));
- fprintf(fp, " irq_chip_retrigger: %ld\n",
- OFFSET(irq_chip_retrigger));
- fprintf(fp, " irq_chip_set_type: %ld\n",
- OFFSET(irq_chip_set_type));
- fprintf(fp, " irq_chip_set_wake: %ld\n",
- OFFSET(irq_chip_set_wake));
- fprintf(fp, "irq_cpustat_t___softirq_active: %ld\n",
- OFFSET(irq_cpustat_t___softirq_active));
- fprintf(fp, " irq_cpustat_t___softirq_mask: %ld\n",
- OFFSET(irq_cpustat_t___softirq_mask));
-
- fprintf(fp, " files_struct_fdt: %ld\n",
- OFFSET(files_struct_fdt));
- fprintf(fp, " fdtable_max_fds: %ld\n",
- OFFSET(fdtable_max_fds));
- fprintf(fp, " fdtable_max_fdset: %ld\n",
- OFFSET(fdtable_max_fdset));
- fprintf(fp, " fdtable_open_fds: %ld\n",
- OFFSET(fdtable_open_fds));
- fprintf(fp, " fdtable_fd: %ld\n",
- OFFSET(fdtable_fd));
- fprintf(fp, " files_struct_max_fds: %ld\n",
- OFFSET(files_struct_max_fds));
- fprintf(fp, " files_struct_max_fdset: %ld\n",
- OFFSET(files_struct_max_fdset));
- fprintf(fp, " files_struct_open_fds: %ld\n",
- OFFSET(files_struct_open_fds));
- fprintf(fp, " files_struct_fd: %ld\n",
- OFFSET(files_struct_fd));
- fprintf(fp, " files_struct_open_fds_init: %ld\n",
- OFFSET(files_struct_open_fds_init));
- fprintf(fp, " file_f_dentry: %ld\n",
- OFFSET(file_f_dentry));
- fprintf(fp, " file_f_vfsmnt: %ld\n",
- OFFSET(file_f_vfsmnt));
- fprintf(fp, " file_f_count: %ld\n",
- OFFSET(file_f_count));
- fprintf(fp, " file_f_path: %ld\n",
- OFFSET(file_f_path));
- fprintf(fp, " path_mnt: %ld\n",
- OFFSET(path_mnt));
- fprintf(fp, " path_dentry: %ld\n",
- OFFSET(path_dentry));
- fprintf(fp, " fs_struct_root: %ld\n",
- OFFSET(fs_struct_root));
- fprintf(fp, " fs_struct_pwd: %ld\n",
- OFFSET(fs_struct_pwd));
- fprintf(fp, " fs_struct_rootmnt: %ld\n",
- OFFSET(fs_struct_rootmnt));
- fprintf(fp, " fs_struct_pwdmnt: %ld\n",
- OFFSET(fs_struct_pwdmnt));
- fprintf(fp, " dentry_d_inode: %ld\n",
- OFFSET(dentry_d_inode));
- fprintf(fp, " dentry_d_parent: %ld\n",
- OFFSET(dentry_d_parent));
- fprintf(fp, " dentry_d_name: %ld\n",
- OFFSET(dentry_d_name));
- fprintf(fp, " dentry_d_iname: %ld\n",
- OFFSET(dentry_d_iname));
- fprintf(fp, " dentry_d_covers: %ld\n",
- OFFSET(dentry_d_covers));
- fprintf(fp, " qstr_len: %ld\n", OFFSET(qstr_len));
- fprintf(fp, " qstr_name: %ld\n", OFFSET(qstr_name));
- fprintf(fp, " inode_i_mode: %ld\n",
- OFFSET(inode_i_mode));
- fprintf(fp, " inode_i_op: %ld\n",
- OFFSET(inode_i_op));
- fprintf(fp, " inode_i_sb: %ld\n",
- OFFSET(inode_i_sb));
- fprintf(fp, " inode_u: %ld\n", OFFSET(inode_u));
- fprintf(fp, " inode_i_flock: %ld\n",
- OFFSET(inode_i_flock));
- fprintf(fp, " inode_i_fop: %ld\n",
- OFFSET(inode_i_fop));
- fprintf(fp, " inode_i_mapping: %ld\n",
- OFFSET(inode_i_mapping));
- fprintf(fp, " vfsmount_mnt_next: %ld\n",
- OFFSET(vfsmount_mnt_next));
- fprintf(fp, " vfsmount_mnt_devname: %ld\n",
- OFFSET(vfsmount_mnt_devname));
- fprintf(fp, " vfsmount_mnt_dirname: %ld\n",
- OFFSET(vfsmount_mnt_dirname));
- fprintf(fp, " vfsmount_mnt_sb: %ld\n",
- OFFSET(vfsmount_mnt_sb));
- fprintf(fp, " vfsmount_mnt_list: %ld\n",
- OFFSET(vfsmount_mnt_list));
- fprintf(fp, " vfsmount_mnt_mountpoint: %ld\n",
- OFFSET(vfsmount_mnt_mountpoint));
- fprintf(fp, " vfsmount_mnt_parent: %ld\n",
- OFFSET(vfsmount_mnt_parent));
- fprintf(fp, " mount_mnt_parent: %ld\n",
- OFFSET(mount_mnt_parent));
- fprintf(fp, " mount_mnt_mountpoint: %ld\n",
- OFFSET(mount_mnt_mountpoint));
- fprintf(fp, " mount_mnt_list: %ld\n",
- OFFSET(mount_mnt_list));
- fprintf(fp, " mount_mnt_devname: %ld\n",
- OFFSET(mount_mnt_devname));
- fprintf(fp, " mount_mnt: %ld\n",
- OFFSET(mount_mnt));
- fprintf(fp, " namespace_root: %ld\n",
- OFFSET(namespace_root));
- fprintf(fp, " namespace_list: %ld\n",
- OFFSET(namespace_list));
- fprintf(fp, " super_block_s_dirty: %ld\n",
- OFFSET(super_block_s_dirty));
- fprintf(fp, " super_block_s_type: %ld\n",
- OFFSET(super_block_s_type));
- fprintf(fp, " super_block_s_files: %ld\n",
- OFFSET(super_block_s_files));
- fprintf(fp, " nlm_file_f_file: %ld\n",
- OFFSET(nlm_file_f_file));
- fprintf(fp, " file_system_type_name: %ld\n",
- OFFSET(file_system_type_name));
- fprintf(fp, " file_lock_fl_owner: %ld\n",
- OFFSET(file_lock_fl_owner));
- fprintf(fp, " nlm_host_h_exportent: %ld\n",
- OFFSET(nlm_host_h_exportent));
- fprintf(fp, " svc_client_cl_ident: %ld\n",
- OFFSET(svc_client_cl_ident));
- fprintf(fp, " kmem_cache_s_c_nextp: %ld\n",
- OFFSET(kmem_cache_s_c_nextp));
- fprintf(fp, " kmem_cache_s_c_name: %ld\n",
- OFFSET(kmem_cache_s_c_name));
- fprintf(fp, " kmem_cache_s_c_num: %ld\n",
- OFFSET(kmem_cache_s_c_num));
- fprintf(fp, " kmem_cache_s_c_org_size: %ld\n",
- OFFSET(kmem_cache_s_c_org_size));
- fprintf(fp, " kmem_cache_s_c_flags: %ld\n",
- OFFSET(kmem_cache_s_c_flags));
- fprintf(fp, " kmem_cache_s_c_offset: %ld\n",
- OFFSET(kmem_cache_s_c_offset));
- fprintf(fp, " kmem_cache_s_c_firstp: %ld\n",
- OFFSET(kmem_cache_s_c_firstp));
- fprintf(fp, " kmem_cache_s_c_gfporder: %ld\n",
- OFFSET(kmem_cache_s_c_gfporder));
- fprintf(fp, " kmem_cache_s_c_magic: %ld\n",
- OFFSET(kmem_cache_s_c_magic));
- fprintf(fp, " kmem_cache_s_c_align: %ld\n",
- OFFSET(kmem_cache_s_c_align));
- fprintf(fp, " kmem_cache_s_num: %ld\n",
- OFFSET(kmem_cache_s_num));
- fprintf(fp, " kmem_cache_s_next: %ld\n",
- OFFSET(kmem_cache_s_next));
- fprintf(fp, " kmem_cache_s_name: %ld\n",
- OFFSET(kmem_cache_s_name));
- fprintf(fp, " kmem_cache_s_objsize: %ld\n",
- OFFSET(kmem_cache_s_objsize));
- fprintf(fp, " kmem_cache_s_flags: %ld\n",
- OFFSET(kmem_cache_s_flags));
- fprintf(fp, " kmem_cache_s_gfporder: %ld\n",
- OFFSET(kmem_cache_s_gfporder));
- fprintf(fp, " kmem_cache_s_slabs: %ld\n",
- OFFSET(kmem_cache_s_slabs));
- fprintf(fp, " kmem_cache_s_slabs_full: %ld\n",
- OFFSET(kmem_cache_s_slabs_full));
- fprintf(fp, " kmem_cache_s_slabs_partial: %ld\n",
- OFFSET(kmem_cache_s_slabs_partial));
- fprintf(fp, " kmem_cache_s_slabs_free: %ld\n",
- OFFSET(kmem_cache_s_slabs_free));
- fprintf(fp, " kmem_cache_s_cpudata: %ld\n",
- OFFSET(kmem_cache_s_cpudata));
- fprintf(fp, " kmem_cache_s_colour_off: %ld\n",
- OFFSET(kmem_cache_s_colour_off));
- fprintf(fp, " cpucache_s_avail: %ld\n",
- OFFSET(cpucache_s_avail));
- fprintf(fp, " cpucache_s_limit: %ld\n",
- OFFSET(cpucache_s_limit));
- fprintf(fp, " array_cache_avail: %ld\n",
- OFFSET(array_cache_avail));
- fprintf(fp, " array_cache_limit: %ld\n",
- OFFSET(array_cache_limit));
- fprintf(fp, " kmem_cache_s_array: %ld\n",
- OFFSET(kmem_cache_s_array));
- fprintf(fp, " kmem_cache_s_lists: %ld\n",
- OFFSET(kmem_cache_s_lists));
- fprintf(fp, " kmem_list3_slabs_partial: %ld\n",
- OFFSET(kmem_list3_slabs_partial));
- fprintf(fp, " kmem_list3_slabs_full: %ld\n",
- OFFSET(kmem_list3_slabs_full));
- fprintf(fp, " kmem_list3_slabs_free: %ld\n",
- OFFSET(kmem_list3_slabs_free));
- fprintf(fp, " kmem_list3_free_objects: %ld\n",
- OFFSET(kmem_list3_free_objects));
- fprintf(fp, " kmem_list3_shared: %ld\n",
- OFFSET(kmem_list3_shared));
- fprintf(fp, " kmem_slab_s_s_nextp: %ld\n",
- OFFSET(kmem_slab_s_s_nextp));
- fprintf(fp, " kmem_slab_s_s_freep: %ld\n",
- OFFSET(kmem_slab_s_s_freep));
- fprintf(fp, " kmem_slab_s_s_inuse: %ld\n",
- OFFSET(kmem_slab_s_s_inuse));
- fprintf(fp, " kmem_slab_s_s_mem: %ld\n",
- OFFSET(kmem_slab_s_s_mem));
- fprintf(fp, " kmem_slab_s_s_index: %ld\n",
- OFFSET(kmem_slab_s_s_index));
- fprintf(fp, " kmem_slab_s_s_offset: %ld\n",
- OFFSET(kmem_slab_s_s_offset));
- fprintf(fp, " kmem_slab_s_s_magic: %ld\n",
- OFFSET(kmem_slab_s_s_magic));
- fprintf(fp, " slab_s_list: %ld\n",
- OFFSET(slab_s_list));
- fprintf(fp, " slab_s_s_mem: %ld\n",
- OFFSET(slab_s_s_mem));
- fprintf(fp, " slab_s_inuse: %ld\n",
- OFFSET(slab_s_inuse));
- fprintf(fp, " slab_s_free: %ld\n",
- OFFSET(slab_s_free));
- fprintf(fp, " slab_list: %ld\n",
- OFFSET(slab_list));
- fprintf(fp, " slab_s_mem: %ld\n",
- OFFSET(slab_s_mem));
- fprintf(fp, " slab_inuse: %ld\n",
- OFFSET(slab_inuse));
- fprintf(fp, " slab_free: %ld\n",
- OFFSET(slab_free));
- fprintf(fp, " kmem_cache_size: %ld\n",
- OFFSET(kmem_cache_size));
- fprintf(fp, " kmem_cache_objsize: %ld\n",
- OFFSET(kmem_cache_objsize));
- fprintf(fp, " kmem_cache_offset: %ld\n",
- OFFSET(kmem_cache_offset));
- fprintf(fp, " kmem_cache_order: %ld\n",
- OFFSET(kmem_cache_order));
- fprintf(fp, " kmem_cache_local_node: %ld\n",
- OFFSET(kmem_cache_local_node));
- fprintf(fp, " kmem_cache_objects: %ld\n",
- OFFSET(kmem_cache_objects));
- fprintf(fp, " kmem_cache_inuse: %ld\n",
- OFFSET(kmem_cache_inuse));
- fprintf(fp, " kmem_cache_align: %ld\n",
- OFFSET(kmem_cache_align));
- fprintf(fp, " kmem_cache_name: %ld\n",
- OFFSET(kmem_cache_name));
- fprintf(fp, " kmem_cache_list: %ld\n",
- OFFSET(kmem_cache_list));
- fprintf(fp, " kmem_cache_node: %ld\n",
- OFFSET(kmem_cache_node));
- fprintf(fp, " kmem_cache_cpu_slab: %ld\n",
- OFFSET(kmem_cache_cpu_slab));
- fprintf(fp, " kmem_cache_cpu_partial: %ld\n",
- OFFSET(kmem_cache_cpu_partial));
- fprintf(fp, " kmem_cache_oo: %ld\n",
- OFFSET(kmem_cache_oo));
- fprintf(fp, " kmem_cache_node_nr_partial: %ld\n",
- OFFSET(kmem_cache_node_nr_partial));
- fprintf(fp, " kmem_cache_node_nr_slabs: %ld\n",
- OFFSET(kmem_cache_node_nr_slabs));
- fprintf(fp, " kmem_cache_node_partial: %ld\n",
- OFFSET(kmem_cache_node_partial));
- fprintf(fp, " kmem_cache_node_full: %ld\n",
- OFFSET(kmem_cache_node_full));
- fprintf(fp, " kmem_cache_cpu_freelist: %ld\n",
- OFFSET(kmem_cache_cpu_freelist));
- fprintf(fp, " kmem_cache_cpu_page: %ld\n",
- OFFSET(kmem_cache_cpu_page));
- fprintf(fp, " kmem_cache_cpu_node: %ld\n",
- OFFSET(kmem_cache_cpu_node));
- fprintf(fp, " kmem_cache_flags: %ld\n",
- OFFSET(kmem_cache_flags));
- fprintf(fp, " net_device_next: %ld\n",
- OFFSET(net_device_next));
- fprintf(fp, " net_device_name: %ld\n",
- OFFSET(net_device_name));
- fprintf(fp, " net_device_type: %ld\n",
- OFFSET(net_device_type));
- fprintf(fp, " net_device_addr_len: %ld\n",
- OFFSET(net_device_addr_len));
- fprintf(fp, " net_device_ip_ptr: %ld\n",
- OFFSET(net_device_ip_ptr));
- fprintf(fp, " net_device_dev_list: %ld\n",
- OFFSET(net_device_dev_list));
- fprintf(fp, " net_dev_base_head: %ld\n",
- OFFSET(net_dev_base_head));
- fprintf(fp, " device_next: %ld\n",
- OFFSET(device_next));
- fprintf(fp, " device_name: %ld\n",
- OFFSET(device_name));
- fprintf(fp, " device_type: %ld\n",
- OFFSET(device_type));
- fprintf(fp, " device_ip_ptr: %ld\n",
- OFFSET(device_ip_ptr));
- fprintf(fp, " device_addr_len: %ld\n",
- OFFSET(device_addr_len));
- fprintf(fp, " socket_sk: %ld\n", OFFSET(socket_sk));
- fprintf(fp, " sock_daddr: %ld\n",
- OFFSET(sock_daddr));
- fprintf(fp, " sock_rcv_saddr: %ld\n",
- OFFSET(sock_rcv_saddr));
- fprintf(fp, " sock_dport: %ld\n",
- OFFSET(sock_dport));
- fprintf(fp, " sock_sport: %ld\n",
- OFFSET(sock_sport));
- fprintf(fp, " sock_num: %ld\n", OFFSET(sock_num));
- fprintf(fp, " sock_family: %ld\n",
- OFFSET(sock_family));
- fprintf(fp, " sock_type: %ld\n", OFFSET(sock_type));
- fprintf(fp, " sock_sk_type: %ld\n",
- OFFSET(sock_sk_type));
- fprintf(fp, " sock_common_skc_family: %ld\n",
- OFFSET(sock_common_skc_family));
- fprintf(fp, " socket_alloc_vfs_inode: %ld\n",
- OFFSET(socket_alloc_vfs_inode));
- fprintf(fp, " inet_sock_inet: %ld\n",
- OFFSET(inet_sock_inet));
- fprintf(fp, " inet_opt_daddr: %ld\n",
- OFFSET(inet_opt_daddr));
- fprintf(fp, " inet_opt_rcv_saddr: %ld\n",
- OFFSET(inet_opt_rcv_saddr));
- fprintf(fp, " inet_opt_dport: %ld\n",
- OFFSET(inet_opt_dport));
- fprintf(fp, " inet_opt_sport: %ld\n",
- OFFSET(inet_opt_sport));
- fprintf(fp, " inet_opt_num: %ld\n",
- OFFSET(inet_opt_num));
- fprintf(fp, " ipv6_pinfo_rcv_saddr: %ld\n",
- OFFSET(ipv6_pinfo_rcv_saddr));
- fprintf(fp, " ipv6_pinfo_daddr: %ld\n",
- OFFSET(ipv6_pinfo_daddr));
- fprintf(fp, " timer_list_list: %ld\n",
- OFFSET(timer_list_list));
- fprintf(fp, " timer_list_next: %ld\n",
- OFFSET(timer_list_next));
- fprintf(fp, " timer_list_entry: %ld\n",
- OFFSET(timer_list_entry));
- fprintf(fp, " timer_list_expires: %ld\n",
- OFFSET(timer_list_expires));
- fprintf(fp, " timer_list_function: %ld\n",
- OFFSET(timer_list_function));
- fprintf(fp, " timer_vec_root_vec: %ld\n",
- OFFSET(timer_vec_root_vec));
- fprintf(fp, " timer_vec_vec: %ld\n",
- OFFSET(timer_vec_vec));
- fprintf(fp, " tvec_root_s_vec: %ld\n",
- OFFSET(tvec_root_s_vec));
- fprintf(fp, " tvec_s_vec: %ld\n",
- OFFSET(tvec_s_vec));
- fprintf(fp, " tvec_t_base_s_tv1: %ld\n",
- OFFSET(tvec_t_base_s_tv1));
- fprintf(fp, " wait_queue_task: %ld\n",
- OFFSET(wait_queue_task));
- fprintf(fp, " wait_queue_next: %ld\n",
- OFFSET(wait_queue_next));
- fprintf(fp, " __wait_queue_task: %ld\n",
- OFFSET(__wait_queue_task));
- fprintf(fp, " __wait_queue_head_task_list: %ld\n",
- OFFSET(__wait_queue_head_task_list));
- fprintf(fp, " __wait_queue_task_list: %ld\n",
- OFFSET(__wait_queue_task_list));
-
- fprintf(fp, " pglist_data_node_zones: %ld\n",
- OFFSET(pglist_data_node_zones));
- fprintf(fp, " pglist_data_node_mem_map: %ld\n",
- OFFSET(pglist_data_node_mem_map));
- fprintf(fp, " pglist_data_node_start_paddr: %ld\n",
- OFFSET(pglist_data_node_start_paddr));
- fprintf(fp, " pglist_data_node_start_mapnr: %ld\n",
- OFFSET(pglist_data_node_start_mapnr));
- fprintf(fp, " pglist_data_node_size: %ld\n",
- OFFSET(pglist_data_node_size));
- fprintf(fp, " pglist_data_node_id: %ld\n",
- OFFSET(pglist_data_node_id));
- fprintf(fp, " pglist_data_node_next: %ld\n",
- OFFSET(pglist_data_node_next));
- fprintf(fp, " pglist_data_bdata: %ld\n",
- OFFSET(pglist_data_bdata));
- fprintf(fp, " pglist_data_nr_zones: %ld\n",
- OFFSET(pglist_data_nr_zones));
- fprintf(fp, " pglist_data_node_start_pfn: %ld\n",
- OFFSET(pglist_data_node_start_pfn));
- fprintf(fp, " pglist_data_pgdat_next: %ld\n",
- OFFSET(pglist_data_pgdat_next));
- fprintf(fp, "pglist_data_node_present_pages: %ld\n",
- OFFSET(pglist_data_node_present_pages));
- fprintf(fp, "pglist_data_node_spanned_pages: %ld\n",
- OFFSET(pglist_data_node_spanned_pages));
- fprintf(fp, " page_cache_bucket_chain: %ld\n",
- OFFSET(page_cache_bucket_chain));
- fprintf(fp, " zone_struct_free_pages: %ld\n",
- OFFSET(zone_struct_free_pages));
- fprintf(fp, " zone_struct_free_area: %ld\n",
- OFFSET(zone_struct_free_area));
- fprintf(fp, " zone_struct_zone_pgdat: %ld\n",
- OFFSET(zone_struct_zone_pgdat));
- fprintf(fp, " zone_struct_name: %ld\n",
- OFFSET(zone_struct_name));
- fprintf(fp, " zone_struct_size: %ld\n",
- OFFSET(zone_struct_size));
- fprintf(fp, " zone_struct_memsize: %ld\n",
- OFFSET(zone_struct_memsize));
- fprintf(fp, " zone_struct_zone_start_pfn: %ld\n",
- OFFSET(zone_struct_zone_start_pfn));
- fprintf(fp, " zone_struct_zone_start_paddr: %ld\n",
- OFFSET(zone_struct_zone_start_paddr));
- fprintf(fp, " zone_struct_zone_start_mapnr: %ld\n",
- OFFSET(zone_struct_zone_start_mapnr));
- fprintf(fp, " zone_struct_zone_mem_map: %ld\n",
- OFFSET(zone_struct_zone_mem_map));
- fprintf(fp, "zone_struct_inactive_clean_pages: %ld\n",
- OFFSET(zone_struct_inactive_clean_pages));
- fprintf(fp, "zone_struct_inactive_clean_list: %ld\n",
- OFFSET(zone_struct_inactive_clean_list));
- fprintf(fp, "zone_struct_inactive_dirty_pages: %ld\n",
- OFFSET(zone_struct_inactive_dirty_pages));
- fprintf(fp, " zone_struct_active_pages: %ld\n",
- OFFSET(zone_struct_active_pages));
- fprintf(fp, " zone_struct_pages_min: %ld\n",
- OFFSET(zone_struct_pages_min));
- fprintf(fp, " zone_struct_pages_low: %ld\n",
- OFFSET(zone_struct_pages_low));
- fprintf(fp, " zone_struct_pages_high: %ld\n",
- OFFSET(zone_struct_pages_high));
- fprintf(fp, " zone_free_pages: %ld\n",
- OFFSET(zone_free_pages));
- fprintf(fp, " zone_watermark: %ld\n",
- OFFSET(zone_watermark));
- fprintf(fp, " zone_free_area: %ld\n",
- OFFSET(zone_free_area));
- fprintf(fp, " zone_zone_pgdat: %ld\n",
- OFFSET(zone_zone_pgdat));
- fprintf(fp, " zone_zone_mem_map: %ld\n",
- OFFSET(zone_zone_mem_map));
- fprintf(fp, " zone_name: %ld\n",
- OFFSET(zone_name));
- fprintf(fp, " zone_spanned_pages: %ld\n",
- OFFSET(zone_spanned_pages));
- fprintf(fp, " zone_present_pages: %ld\n",
- OFFSET(zone_present_pages));
- fprintf(fp, " zone_zone_start_pfn: %ld\n",
- OFFSET(zone_zone_start_pfn));
- fprintf(fp, " zone_pages_min: %ld\n",
- OFFSET(zone_pages_min));
- fprintf(fp, " zone_pages_low: %ld\n",
- OFFSET(zone_pages_low));
- fprintf(fp, " zone_pages_high: %ld\n",
- OFFSET(zone_pages_high));
- fprintf(fp, " zone_vm_stat: %ld\n",
- OFFSET(zone_vm_stat));
- fprintf(fp, " zone_nr_active: %ld\n",
- OFFSET(zone_nr_active));
- fprintf(fp, " zone_nr_inactive: %ld\n",
- OFFSET(zone_nr_inactive));
- fprintf(fp, " zone_all_unreclaimable: %ld\n",
- OFFSET(zone_all_unreclaimable));
- fprintf(fp, " zone_flags: %ld\n",
- OFFSET(zone_flags));
- fprintf(fp, " zone_pages_scanned: %ld\n",
- OFFSET(zone_pages_scanned));
- fprintf(fp, " neighbour_next: %ld\n",
- OFFSET(neighbour_next));
- fprintf(fp, " neighbour_primary_key: %ld\n",
- OFFSET(neighbour_primary_key));
- fprintf(fp, " neighbour_ha: %ld\n",
- OFFSET(neighbour_ha));
- fprintf(fp, " neighbour_dev: %ld\n",
- OFFSET(neighbour_dev));
- fprintf(fp, " neighbour_nud_state: %ld\n",
- OFFSET(neighbour_nud_state));
- fprintf(fp, " neigh_table_hash_buckets: %ld\n",
- OFFSET(neigh_table_hash_buckets));
- fprintf(fp, " neigh_table_hash_mask: %ld\n",
- OFFSET(neigh_table_hash_mask));
- fprintf(fp, " neigh_table_hash_shift: %ld\n",
- OFFSET(neigh_table_hash_shift));
- fprintf(fp, " neigh_table_nht_ptr: %ld\n",
- OFFSET(neigh_table_nht_ptr));
- fprintf(fp, " neigh_table_key_len: %ld\n",
- OFFSET(neigh_table_key_len));
- fprintf(fp, " in_device_ifa_list: %ld\n",
- OFFSET(in_device_ifa_list));
- fprintf(fp, " in_ifaddr_ifa_next: %ld\n",
- OFFSET(in_ifaddr_ifa_next));
- fprintf(fp, " in_ifaddr_ifa_address: %ld\n",
- OFFSET(in_ifaddr_ifa_address));
- fprintf(fp, " pci_dev_global_list: %ld\n",
- OFFSET(pci_dev_global_list));
- fprintf(fp, " pci_dev_next: %ld\n",
- OFFSET(pci_dev_next));
- fprintf(fp, " pci_dev_bus: %ld\n",
- OFFSET(pci_dev_bus));
- fprintf(fp, " pci_dev_devfn: %ld\n",
- OFFSET(pci_dev_devfn));
- fprintf(fp, " pci_dev_class: %ld\n",
- OFFSET(pci_dev_class));
- fprintf(fp, " pci_dev_device: %ld\n",
- OFFSET(pci_dev_device));
- fprintf(fp, " pci_dev_vendor: %ld\n",
- OFFSET(pci_dev_vendor));
- fprintf(fp, " pci_bus_number: %ld\n",
- OFFSET(pci_bus_number));
- fprintf(fp, " resource_entry_t_from: %ld\n",
- OFFSET(resource_entry_t_from));
- fprintf(fp, " resource_entry_t_num: %ld\n",
- OFFSET(resource_entry_t_num));
- fprintf(fp, " resource_entry_t_name: %ld\n",
- OFFSET(resource_entry_t_name));
- fprintf(fp, " resource_entry_t_next: %ld\n",
- OFFSET(resource_entry_t_next));
- fprintf(fp, " resource_name: %ld\n",
- OFFSET(resource_name));
- fprintf(fp, " resource_start: %ld\n",
- OFFSET(resource_start));
- fprintf(fp, " resource_end: %ld\n",
- OFFSET(resource_end));
- fprintf(fp, " resource_sibling: %ld\n",
- OFFSET(resource_sibling));
- fprintf(fp, " resource_child: %ld\n",
- OFFSET(resource_child));
- fprintf(fp, " runqueue_curr: %ld\n",
- OFFSET(runqueue_curr));
- fprintf(fp, " runqueue_idle: %ld\n",
- OFFSET(runqueue_idle));
- fprintf(fp, " runqueue_active: %ld\n",
- OFFSET(runqueue_active));
- fprintf(fp, " runqueue_expired: %ld\n",
- OFFSET(runqueue_expired));
- fprintf(fp, " runqueue_arrays: %ld\n",
- OFFSET(runqueue_arrays));
- fprintf(fp, " runqueue_cpu: %ld\n",
- OFFSET(runqueue_cpu));
- fprintf(fp, " cpu_s_idle: %ld\n",
- OFFSET(cpu_s_idle));
- fprintf(fp, " cpu_s_curr: %ld\n",
- OFFSET(cpu_s_curr));
- fprintf(fp, " prio_array_queue: %ld\n",
- OFFSET(prio_array_queue));
- fprintf(fp, " rt_prio_array_queue: %ld\n",
- OFFSET(rt_prio_array_queue));
- fprintf(fp, " prio_array_nr_active: %ld\n",
- OFFSET(prio_array_nr_active));
- fprintf(fp, " user_regs_struct_ebp: %ld\n",
- OFFSET(user_regs_struct_ebp));
- fprintf(fp, " user_regs_struct_eip: %ld\n",
- OFFSET(user_regs_struct_eip));
- fprintf(fp, " user_regs_struct_esp: %ld\n",
- OFFSET(user_regs_struct_esp));
- fprintf(fp, " user_regs_struct_rip: %ld\n",
- OFFSET(user_regs_struct_rip));
- fprintf(fp, " user_regs_struct_rsp: %ld\n",
- OFFSET(user_regs_struct_rsp));
- fprintf(fp, " user_regs_struct_eflags: %ld\n",
- OFFSET(user_regs_struct_eflags));
- fprintf(fp, " user_regs_struct_cs: %ld\n",
- OFFSET(user_regs_struct_cs));
- fprintf(fp, " user_regs_struct_ss: %ld\n",
- OFFSET(user_regs_struct_ss));
- fprintf(fp, " user_regs_struct_eip: %ld\n",
- OFFSET(user_regs_struct_eip));
- fprintf(fp, " user_regs_struct_rax: %ld\n",
- OFFSET(user_regs_struct_rax));
- fprintf(fp, " user_regs_struct_eax: %ld\n",
- OFFSET(user_regs_struct_eax));
- fprintf(fp, " user_regs_struct_rbx: %ld\n",
- OFFSET(user_regs_struct_rbx));
- fprintf(fp, " user_regs_struct_ebx: %ld\n",
- OFFSET(user_regs_struct_ebx));
- fprintf(fp, " user_regs_struct_rcx: %ld\n",
- OFFSET(user_regs_struct_rcx));
- fprintf(fp, " user_regs_struct_ecx: %ld\n",
- OFFSET(user_regs_struct_ecx));
- fprintf(fp, " user_regs_struct_rdx: %ld\n",
- OFFSET(user_regs_struct_rdx));
- fprintf(fp, " user_regs_struct_edx: %ld\n",
- OFFSET(user_regs_struct_edx));
- fprintf(fp, " user_regs_struct_rsi: %ld\n",
- OFFSET(user_regs_struct_rsi));
- fprintf(fp, " user_regs_struct_esi: %ld\n",
- OFFSET(user_regs_struct_esi));
- fprintf(fp, " user_regs_struct_rdi: %ld\n",
- OFFSET(user_regs_struct_rdi));
- fprintf(fp, " user_regs_struct_edi: %ld\n",
- OFFSET(user_regs_struct_edi));
- fprintf(fp, " user_regs_struct_ds: %ld\n",
- OFFSET(user_regs_struct_ds));
- fprintf(fp, " user_regs_struct_es: %ld\n",
- OFFSET(user_regs_struct_es));
- fprintf(fp, " user_regs_struct_fs: %ld\n",
- OFFSET(user_regs_struct_fs));
- fprintf(fp, " user_regs_struct_gs: %ld\n",
- OFFSET(user_regs_struct_gs));
- fprintf(fp, " user_regs_struct_rbp: %ld\n",
- OFFSET(user_regs_struct_rbp));
- fprintf(fp, " user_regs_struct_r8: %ld\n",
- OFFSET(user_regs_struct_r8));
- fprintf(fp, " user_regs_struct_r9: %ld\n",
- OFFSET(user_regs_struct_r9));
- fprintf(fp, " user_regs_struct_r10: %ld\n",
- OFFSET(user_regs_struct_r10));
- fprintf(fp, " user_regs_struct_r11: %ld\n",
- OFFSET(user_regs_struct_r11));
- fprintf(fp, " user_regs_struct_r12: %ld\n",
- OFFSET(user_regs_struct_r12));
- fprintf(fp, " user_regs_struct_r13: %ld\n",
- OFFSET(user_regs_struct_r13));
- fprintf(fp, " user_regs_struct_r14: %ld\n",
- OFFSET(user_regs_struct_r14));
- fprintf(fp, " user_regs_struct_r15: %ld\n",
- OFFSET(user_regs_struct_r15));
- fprintf(fp, " e820map_nr_map: %ld\n",
- OFFSET(e820map_nr_map));
- fprintf(fp, " e820entry_addr: %ld\n",
- OFFSET(e820entry_addr));
- fprintf(fp, " e820entry_size: %ld\n",
- OFFSET(e820entry_size));
- fprintf(fp, " e820entry_type: %ld\n",
- OFFSET(e820entry_type));
- fprintf(fp, " char_device_struct_name: %ld\n",
- OFFSET(char_device_struct_name));
- fprintf(fp, " char_device_struct_next: %ld\n",
- OFFSET(char_device_struct_next));
- fprintf(fp, " char_device_struct_fops: %ld\n",
- OFFSET(char_device_struct_fops));
- fprintf(fp, " char_device_struct_major: %ld\n",
- OFFSET(char_device_struct_major));
- fprintf(fp, " char_device_struct_baseminor: %ld\n",
- OFFSET(char_device_struct_baseminor));
- fprintf(fp, " char_device_struct_cdev: %ld\n",
- OFFSET(char_device_struct_cdev));
- fprintf(fp, " cdev_ops: %ld\n", OFFSET(cdev_ops));
- fprintf(fp, " probe_next: %ld\n",
- OFFSET(probe_next));
- fprintf(fp, " probe_dev: %ld\n",
- OFFSET(probe_dev));
- fprintf(fp, " probe_data: %ld\n",
- OFFSET(probe_data));
- fprintf(fp, " kobj_map_probes: %ld\n",
- OFFSET(kobj_map_probes));
- fprintf(fp, " blk_major_name_next: %ld\n",
- OFFSET(blk_major_name_next));
- fprintf(fp, " blk_major_name_major: %ld\n",
- OFFSET(blk_major_name_major));
- fprintf(fp, " blk_major_name_name: %ld\n",
- OFFSET(blk_major_name_name));
- fprintf(fp, " radix_tree_root_height: %ld\n",
- OFFSET(radix_tree_root_height));
- fprintf(fp, " radix_tree_root_rnode: %ld\n",
- OFFSET(radix_tree_root_rnode));
- fprintf(fp, " radix_tree_node_slots: %ld\n",
- OFFSET(radix_tree_node_slots));
- fprintf(fp, " radix_tree_node_height: %ld\n",
- OFFSET(radix_tree_node_height));
- fprintf(fp, " rb_root_rb_node: %ld\n",
- OFFSET(rb_root_rb_node));
- fprintf(fp, " rb_node_rb_left: %ld\n",
- OFFSET(rb_node_rb_left));
- fprintf(fp, " rb_node_rb_right: %ld\n",
- OFFSET(rb_node_rb_right));
- fprintf(fp, " x8664_pda_pcurrent: %ld\n",
- OFFSET(x8664_pda_pcurrent));
- fprintf(fp, " x8664_pda_data_offset: %ld\n",
- OFFSET(x8664_pda_data_offset));
- fprintf(fp, " x8664_pda_kernelstack: %ld\n",
- OFFSET(x8664_pda_kernelstack));
- fprintf(fp, " x8664_pda_irqrsp: %ld\n",
- OFFSET(x8664_pda_irqrsp));
- fprintf(fp, " x8664_pda_cpunumber: %ld\n",
- OFFSET(x8664_pda_cpunumber));
- fprintf(fp, " x8664_pda_irqstackptr: %ld\n",
- OFFSET(x8664_pda_irqstackptr));
- fprintf(fp, " x8664_pda_level4_pgt: %ld\n",
- OFFSET(x8664_pda_level4_pgt));
- fprintf(fp, " x8664_pda_me: %ld\n",
- OFFSET(x8664_pda_me));
- fprintf(fp, " tss_struct_ist: %ld\n",
- OFFSET(tss_struct_ist));
- fprintf(fp, " mem_section_section_mem_map: %ld\n",
- OFFSET(mem_section_section_mem_map));
- fprintf(fp, " vcpu_guest_context_user_regs: %ld\n",
- OFFSET(vcpu_guest_context_user_regs));
- fprintf(fp, " cpu_user_regs_eip: %ld\n",
- OFFSET(cpu_user_regs_eip));
- fprintf(fp, " cpu_user_regs_esp: %ld\n",
- OFFSET(cpu_user_regs_esp));
- fprintf(fp, " cpu_user_regs_rip: %ld\n",
- OFFSET(cpu_user_regs_rip));
- fprintf(fp, " cpu_user_regs_rsp: %ld\n",
- OFFSET(cpu_user_regs_rsp));
- fprintf(fp, " unwind_table_core: %ld\n",
- OFFSET(unwind_table_core));
- fprintf(fp, " unwind_table_init: %ld\n",
- OFFSET(unwind_table_init));
- fprintf(fp, " unwind_table_address: %ld\n",
- OFFSET(unwind_table_address));
- fprintf(fp, " unwind_table_size: %ld\n",
- OFFSET(unwind_table_size));
- fprintf(fp, " unwind_table_link: %ld\n",
- OFFSET(unwind_table_link));
- fprintf(fp, " unwind_table_name: %ld\n",
- OFFSET(unwind_table_name));
- fprintf(fp, " rq_cfs: %ld\n",
- OFFSET(rq_cfs));
- fprintf(fp, " rq_rt: %ld\n",
- OFFSET(rq_rt));
- fprintf(fp, " cfs_rq_curr: %ld\n",
- OFFSET(cfs_rq_curr));
- fprintf(fp, " rq_nr_running: %ld\n",
- OFFSET(rq_nr_running));
- fprintf(fp, " rq_timestamp: %ld\n",
- OFFSET(rq_timestamp));
- fprintf(fp, " task_struct_se: %ld\n",
- OFFSET(task_struct_se));
- fprintf(fp, " sched_entity_run_node: %ld\n",
- OFFSET(sched_entity_run_node));
- fprintf(fp, " sched_entity_cfs_rq: %ld\n",
- OFFSET(sched_entity_cfs_rq));
- fprintf(fp, " sched_entity_my_q: %ld\n",
- OFFSET(sched_entity_my_q));
- fprintf(fp, " sched_entity_on_rq: %ld\n",
- OFFSET(sched_entity_on_rq));
- fprintf(fp, " cfs_rq_nr_running: %ld\n",
- OFFSET(cfs_rq_nr_running));
- fprintf(fp, " cfs_rq_rb_leftmost: %ld\n",
- OFFSET(cfs_rq_rb_leftmost));
- fprintf(fp, " cfs_rq_tasks_timeline: %ld\n",
- OFFSET(cfs_rq_tasks_timeline));
- fprintf(fp, " rt_rq_active: %ld\n",
- OFFSET(rt_rq_active));
- fprintf(fp, " pcpu_info_vcpu: %ld\n",
- OFFSET(pcpu_info_vcpu));
- fprintf(fp, " pcpu_info_idle: %ld\n",
- OFFSET(pcpu_info_idle));
- fprintf(fp, " vcpu_struct_rq: %ld\n",
- OFFSET(vcpu_struct_rq));
- fprintf(fp, " s390_lowcore_psw_save_area: %ld\n",
- OFFSET(s390_lowcore_psw_save_area));
- fprintf(fp, " s390_stack_frame_back_chain: %ld\n",
- OFFSET(s390_stack_frame_back_chain));
- fprintf(fp, " s390_stack_frame_r14: %ld\n",
- OFFSET(s390_stack_frame_r14));
- fprintf(fp, " cpu_context_save_fp: %ld\n",
- OFFSET(cpu_context_save_fp));
- fprintf(fp, " cpu_context_save_sp: %ld\n",
- OFFSET(cpu_context_save_sp));
- fprintf(fp, " cpu_context_save_pc: %ld\n",
- OFFSET(cpu_context_save_pc));
- fprintf(fp, " elf_prstatus_pr_pid: %ld\n",
- OFFSET(elf_prstatus_pr_pid));
- fprintf(fp, " elf_prstatus_pr_reg: %ld\n",
- OFFSET(elf_prstatus_pr_reg));
- fprintf(fp, " irq_desc_t_name: %ld\n",
- OFFSET(irq_desc_t_name));
- fprintf(fp, " thread_info_cpu_context: %ld\n",
- OFFSET(thread_info_cpu_context));
- fprintf(fp, " unwind_table_list: %ld\n",
- OFFSET(unwind_table_list));
- fprintf(fp, " unwind_table_start: %ld\n",
- OFFSET(unwind_table_start));
- fprintf(fp, " unwind_table_stop: %ld\n",
- OFFSET(unwind_table_stop));
- fprintf(fp, " unwind_table_begin_addr: %ld\n",
- OFFSET(unwind_table_begin_addr));
- fprintf(fp, " unwind_table_end_addr: %ld\n",
- OFFSET(unwind_table_end_addr));
- fprintf(fp, " unwind_idx_addr: %ld\n",
- OFFSET(unwind_idx_addr));
- fprintf(fp, " unwind_idx_insn: %ld\n",
- OFFSET(unwind_idx_insn));
- fprintf(fp, " class_devices: %ld\n",
- OFFSET(class_devices));
- fprintf(fp, " class_p: %ld\n",
- OFFSET(class_p));
- fprintf(fp, " class_private_devices: %ld\n",
- OFFSET(class_private_devices));
- fprintf(fp, " device_knode_class: %ld\n",
- OFFSET(device_knode_class));
- fprintf(fp, " device_node: %ld\n",
- OFFSET(device_node));
- fprintf(fp, " gendisk_dev: %ld\n",
- OFFSET(gendisk_dev));
- fprintf(fp, " gendisk_kobj: %ld\n",
- OFFSET(gendisk_kobj));
- fprintf(fp, " gendisk_part0: %ld\n",
- OFFSET(gendisk_part0));
- fprintf(fp, " gendisk_queue: %ld\n",
- OFFSET(gendisk_queue));
- fprintf(fp, " hd_struct_dev: %ld\n",
- OFFSET(hd_struct_dev));
- fprintf(fp, " klist_k_list: %ld\n",
- OFFSET(klist_k_list));
- fprintf(fp, " klist_node_n_klist: %ld\n",
- OFFSET(klist_node_n_klist));
- fprintf(fp, " klist_node_n_node: %ld\n",
- OFFSET(klist_node_n_node));
- fprintf(fp, " kobject_entry: %ld\n",
- OFFSET(kobject_entry));
- fprintf(fp, " kset_list: %ld\n",
- OFFSET(kset_list));
- fprintf(fp, " request_list_count: %ld\n",
- OFFSET(request_list_count));
- fprintf(fp, " request_queue_in_flight: %ld\n",
- OFFSET(request_queue_in_flight));
- fprintf(fp, " request_queue_rq: %ld\n",
- OFFSET(request_queue_rq));
- fprintf(fp, " subsys_private_klist_devices: %ld\n",
- OFFSET(subsys_private_klist_devices));
- fprintf(fp, " subsystem_kset: %ld\n",
- OFFSET(subsystem_kset));
- fprintf(fp, " file_f_op: %ld\n",
- OFFSET(file_f_op));
- fprintf(fp, " file_private_data: %ld\n",
- OFFSET(file_private_data));
- fprintf(fp, " hstate_order: %ld\n",
- OFFSET(hstate_order));
- fprintf(fp, " hstate_nr_huge_pages: %ld\n",
- OFFSET(hstate_nr_huge_pages));
- fprintf(fp, " hstate_free_huge_pages: %ld\n",
- OFFSET(hstate_free_huge_pages));
- fprintf(fp, " hstate_name: %ld\n",
- OFFSET(hstate_name));
- fprintf(fp, " hugetlbfs_sb_info_hstate: %ld\n",
- OFFSET(hugetlbfs_sb_info_hstate));
- fprintf(fp, " idr_layer_ary: %ld\n",
- OFFSET(idr_layer_ary));
- fprintf(fp, " idr_layer_layer: %ld\n",
- OFFSET(idr_layer_layer));
- fprintf(fp, " idr_layers: %ld\n",
- OFFSET(idr_layers));
- fprintf(fp, " idr_top: %ld\n",
- OFFSET(idr_top));
- fprintf(fp, " ipc_id_ary_p: %ld\n",
- OFFSET(ipc_id_ary_p));
- fprintf(fp, " ipc_ids_entries: %ld\n",
- OFFSET(ipc_ids_entries));
- fprintf(fp, " ipc_ids_max_id: %ld\n",
- OFFSET(ipc_ids_max_id));
- fprintf(fp, " ipc_ids_ipcs_idr: %ld\n",
- OFFSET(ipc_ids_ipcs_idr));
- fprintf(fp, " ipc_ids_in_use: %ld\n",
- OFFSET(ipc_ids_in_use));
- fprintf(fp, " ipc_namespace_ids: %ld\n",
- OFFSET(ipc_namespace_ids));
- fprintf(fp, " kern_ipc_perm_deleted: %ld\n",
- OFFSET(kern_ipc_perm_deleted));
- fprintf(fp, " kern_ipc_perm_key: %ld\n",
- OFFSET(kern_ipc_perm_key));
- fprintf(fp, " kern_ipc_perm_mode: %ld\n",
- OFFSET(kern_ipc_perm_mode));
- fprintf(fp, " kern_ipc_perm_uid: %ld\n",
- OFFSET(kern_ipc_perm_uid));
- fprintf(fp, " kern_ipc_perm_id: %ld\n",
- OFFSET(kern_ipc_perm_id));
- fprintf(fp, " kern_ipc_perm_seq: %ld\n",
- OFFSET(kern_ipc_perm_seq));
- fprintf(fp, " nsproxy_ipc_ns: %ld\n",
- OFFSET(nsproxy_ipc_ns));
- fprintf(fp, " shmem_inode_info_swapped: %ld\n",
- OFFSET(shmem_inode_info_swapped));
- fprintf(fp, " shmem_inode_info_vfs_inode: %ld\n",
- OFFSET(shmem_inode_info_vfs_inode));
- fprintf(fp, " shm_file_data_file: %ld\n",
- OFFSET(shm_file_data_file));
- fprintf(fp, " shmid_kernel_shm_file: %ld\n",
- OFFSET(shmid_kernel_shm_file));
- fprintf(fp, " shmid_kernel_shm_nattch: %ld\n",
- OFFSET(shmid_kernel_shm_nattch));
- fprintf(fp, " shmid_kernel_shm_perm: %ld\n",
- OFFSET(shmid_kernel_shm_perm));
- fprintf(fp, " shmid_kernel_shm_segsz: %ld\n",
- OFFSET(shmid_kernel_shm_segsz));
- fprintf(fp, " shmid_kernel_id: %ld\n",
- OFFSET(shmid_kernel_id));
- fprintf(fp, " sem_array_sem_perm: %ld\n",
- OFFSET(sem_array_sem_perm));
- fprintf(fp, " sem_array_sem_id: %ld\n",
- OFFSET(sem_array_sem_id));
- fprintf(fp, " sem_array_sem_nsems: %ld\n",
- OFFSET(sem_array_sem_nsems));
- fprintf(fp, " msg_queue_q_perm: %ld\n",
- OFFSET(msg_queue_q_perm));
- fprintf(fp, " msg_queue_q_id: %ld\n",
- OFFSET(msg_queue_q_id));
- fprintf(fp, " msg_queue_q_cbytes: %ld\n",
- OFFSET(msg_queue_q_cbytes));
- fprintf(fp, " msg_queue_q_qnum: %ld\n",
- OFFSET(msg_queue_q_qnum));
- fprintf(fp, " super_block_s_fs_info: %ld\n",
- OFFSET(super_block_s_fs_info));
- fprintf(fp, " log_ts_nsec: %ld\n",
- OFFSET(log_ts_nsec));
- fprintf(fp, " log_len: %ld\n",
- OFFSET(log_len));
- fprintf(fp, " log_text_len: %ld\n",
- OFFSET(log_text_len));
- fprintf(fp, " log_dict_len: %ld\n",
- OFFSET(log_dict_len));
- fprintf(fp, " log_level: %ld\n",
- OFFSET(log_level));
- fprintf(fp, " log_flags_level: %ld\n",
- OFFSET(log_flags_level));
- fprintf(fp, " sched_rt_entity_my_q: %ld\n",
- OFFSET(sched_rt_entity_my_q));
- fprintf(fp, " task_group_parent: %ld\n",
- OFFSET(task_group_parent));
- fprintf(fp, " task_group_css: %ld\n",
- OFFSET(task_group_css));
- fprintf(fp, " cgroup_subsys_state_cgroup: %ld\n",
- OFFSET(cgroup_subsys_state_cgroup));
- fprintf(fp, " cgroup_dentry: %ld\n",
- OFFSET(cgroup_dentry));
- fprintf(fp, " cgroup_kn: %ld\n",
- OFFSET(cgroup_kn));
- fprintf(fp, " kernfs_node_name: %ld\n",
- OFFSET(kernfs_node_name));
- fprintf(fp, " kernfs_node_parent: %ld\n",
- OFFSET(kernfs_node_parent));
- fprintf(fp, " task_group_rt_rq: %ld\n",
- OFFSET(task_group_rt_rq));
- fprintf(fp, " rt_rq_tg: %ld\n",
- OFFSET(rt_rq_tg));
- fprintf(fp, " task_group_cfs_rq: %ld\n",
- OFFSET(task_group_cfs_rq));
- fprintf(fp, " cfs_rq_tg: %ld\n",
- OFFSET(cfs_rq_tg));
- fprintf(fp, " task_group_siblings: %ld\n",
- OFFSET(task_group_siblings));
- fprintf(fp, " task_group_children: %ld\n",
- OFFSET(task_group_children));
- fprintf(fp, " task_group_cfs_bandwidth: %ld\n",
- OFFSET(task_group_cfs_bandwidth));
- fprintf(fp, " cfs_rq_throttled: %ld\n",
- OFFSET(cfs_rq_throttled));
- fprintf(fp, " task_group_rt_bandwidth: %ld\n",
- OFFSET(task_group_rt_bandwidth));
- fprintf(fp, " rt_rq_rt_throttled: %ld\n",
- OFFSET(rt_rq_rt_throttled));
- fprintf(fp, " rt_rq_highest_prio: %ld\n",
- OFFSET(rt_rq_highest_prio));
- fprintf(fp, " rt_rq_rt_nr_running: %ld\n",
- OFFSET(rt_rq_rt_nr_running));
- fprintf(fp, " hrtimer_cpu_base_clock_base: %ld\n",
- OFFSET(hrtimer_cpu_base_clock_base));
- fprintf(fp, " hrtimer_clock_base_offset: %ld\n",
- OFFSET(hrtimer_clock_base_offset));
- fprintf(fp, " hrtimer_clock_base_active: %ld\n",
- OFFSET(hrtimer_clock_base_active));
- fprintf(fp, " hrtimer_clock_base_first: %ld\n",
- OFFSET(hrtimer_clock_base_first));
- fprintf(fp, " hrtimer_clock_base_get_time: %ld\n",
- OFFSET(hrtimer_clock_base_get_time));
- fprintf(fp, " hrtimer_base_first: %ld\n",
- OFFSET(hrtimer_base_first));
- fprintf(fp, " hrtimer_base_pending: %ld\n",
- OFFSET(hrtimer_base_pending));
- fprintf(fp, " hrtimer_base_get_time: %ld\n",
- OFFSET(hrtimer_base_get_time));
- fprintf(fp, " hrtimer_node: %ld\n",
- OFFSET(hrtimer_node));
- fprintf(fp, " hrtimer_list: %ld\n",
- OFFSET(hrtimer_list));
- fprintf(fp, " hrtimer_softexpires: %ld\n",
- OFFSET(hrtimer_softexpires));
- fprintf(fp, " hrtimer_expires: %ld\n",
- OFFSET(hrtimer_expires));
- fprintf(fp, " hrtimer_function: %ld\n",
- OFFSET(hrtimer_function));
- fprintf(fp, " timerqueue_head_next: %ld\n",
- OFFSET(timerqueue_head_next));
- fprintf(fp, " timerqueue_node_expires: %ld\n",
- OFFSET(timerqueue_node_expires));
- fprintf(fp, " timerqueue_node_node: %ld\n",
- OFFSET(timerqueue_node_node));
- fprintf(fp, " ktime_t_tv64: %ld\n",
- OFFSET(ktime_t_tv64));
- fprintf(fp, " ktime_t_sec: %ld\n",
- OFFSET(ktime_t_sec));
- fprintf(fp, " ktime_t_nsec: %ld\n",
- OFFSET(ktime_t_nsec));
- fprintf(fp, "\n size_table:\n");
- fprintf(fp, " page: %ld\n", SIZE(page));
- fprintf(fp, " page_flags: %ld\n", SIZE(page_flags));
- fprintf(fp, " trace_print_flags: %ld\n", SIZE(trace_print_flags));
- fprintf(fp, " free_area_struct: %ld\n",
- SIZE(free_area_struct));
- fprintf(fp, " free_area: %ld\n",
- SIZE(free_area));
- fprintf(fp, " zone_struct: %ld\n", SIZE(zone_struct));
- fprintf(fp, " zone: %ld\n", SIZE(zone));
- fprintf(fp, " kmem_slab_s: %ld\n", SIZE(kmem_slab_s));
- fprintf(fp, " slab_s: %ld\n", SIZE(slab_s));
- fprintf(fp, " slab: %ld\n", SIZE(slab));
- fprintf(fp, " kmem_cache_s: %ld\n",
- SIZE(kmem_cache_s));
- fprintf(fp, " cpucache_s: %ld\n", SIZE(cpucache_s));
- fprintf(fp, " array_cache: %ld\n", SIZE(array_cache));
- fprintf(fp, " kmem_bufctl_t: %ld\n",
- SIZE(kmem_bufctl_t));
- fprintf(fp, " kmem_cache: %ld\n", SIZE(kmem_cache));
- fprintf(fp, " kmem_cache_node: %ld\n", SIZE(kmem_cache_node));
- fprintf(fp, " kmem_cache_cpu: %ld\n", SIZE(kmem_cache_cpu));
- fprintf(fp, " swap_info_struct: %ld\n",
- SIZE(swap_info_struct));
- fprintf(fp, " vm_area_struct: %ld\n",
- SIZE(vm_area_struct));
- fprintf(fp, " mm_struct: %ld\n", SIZE(mm_struct));
- fprintf(fp, " pglist_data: %ld\n", SIZE(pglist_data));
- fprintf(fp, " page_cache_bucket: %ld\n",
- SIZE(page_cache_bucket));
- fprintf(fp, " pt_regs: %ld\n", SIZE(pt_regs));
- fprintf(fp, " task_struct: %ld\n", SIZE(task_struct));
- fprintf(fp, " thread_info: %ld\n", SIZE(thread_info));
- fprintf(fp, " softirq_state: %ld\n",
- SIZE(softirq_state));
- fprintf(fp, " softirq_action: %ld\n",
- SIZE(softirq_action));
- fprintf(fp, " desc_struct: %ld\n", SIZE(desc_struct));
- fprintf(fp, " umode_t: %ld\n", SIZE(umode_t));
- fprintf(fp, " dentry: %ld\n", SIZE(dentry));
- fprintf(fp, " fs_struct: %ld\n", SIZE(fs_struct));
- fprintf(fp, " files_struct: %ld\n",
- SIZE(files_struct));
- fprintf(fp, " fdtable: %ld\n", SIZE(fdtable));
- fprintf(fp, " file: %ld\n", SIZE(file));
- fprintf(fp, " inode: %ld\n", SIZE(inode));
- fprintf(fp, " vfsmount: %ld\n", SIZE(vfsmount));
- fprintf(fp, " mount: %ld\n", SIZE(mount));
- fprintf(fp, " super_block: %ld\n",
- SIZE(super_block));
- fprintf(fp, " irqdesc: %ld\n", SIZE(irqdesc));
- fprintf(fp, " module: %ld\n", SIZE(module));
- fprintf(fp, " module_sect_attr: %ld\n", SIZE(module_sect_attr));
- fprintf(fp, " list_head: %ld\n", SIZE(list_head));
- fprintf(fp, " hlist_head: %ld\n", SIZE(hlist_head));
- fprintf(fp, " hlist_node: %ld\n", SIZE(hlist_node));
- fprintf(fp, " irq_cpustat_t: %ld\n",
- SIZE(irq_cpustat_t));
- fprintf(fp, " cpuinfo_x86: %ld\n", SIZE(cpuinfo_x86));
- fprintf(fp, " cpuinfo_ia64: %ld\n",
- SIZE(cpuinfo_ia64));
- fprintf(fp, " timer_list: %ld\n", SIZE(timer_list));
- fprintf(fp, " timer_vec_root: %ld\n",
- SIZE(timer_vec_root));
- fprintf(fp, " timer_vec: %ld\n", SIZE(timer_vec));
- fprintf(fp, " tvec_root_s: %ld\n",
- SIZE(tvec_root_s));
- fprintf(fp, " tvec_s: %ld\n", SIZE(tvec_s));
- fprintf(fp, " tvec_t_base_s: %ld\n",
- SIZE(tvec_t_base_s));
- fprintf(fp, " wait_queue: %ld\n", SIZE(wait_queue));
- fprintf(fp, " __wait_queue: %ld\n",
- SIZE(__wait_queue));
- fprintf(fp, " device: %ld\n", SIZE(device));
- fprintf(fp, " net_device: %ld\n", SIZE(net_device));
- fprintf(fp, " sock: %ld\n", SIZE(sock));
- fprintf(fp, " inet_sock: %ld\n", SIZE(inet_sock));
- fprintf(fp, " socket: %ld\n", SIZE(socket));
- fprintf(fp, " in6_addr: %ld\n", SIZE(in6_addr));
- fprintf(fp, " signal_struct: %ld\n",
- SIZE(signal_struct));
- fprintf(fp, " sigpending_signal: %ld\n",
- SIZE(sigpending_signal));
- fprintf(fp, " signal_queue: %ld\n",
- SIZE(signal_queue));
- fprintf(fp, " sigqueue: %ld\n", SIZE(sigqueue));
- fprintf(fp, " k_sigaction: %ld\n",
- SIZE(k_sigaction));
- fprintf(fp, " sighand_struct: %ld\n",
- SIZE(sighand_struct));
- fprintf(fp, " resource_entry_t: %ld\n",
- SIZE(resource_entry_t));
- fprintf(fp, " resource: %ld\n", SIZE(resource));
- fprintf(fp, " runqueue: %ld\n", SIZE(runqueue));
- fprintf(fp, " irq_desc_t: %ld\n", SIZE(irq_desc_t));
- fprintf(fp, " irq_data: %ld\n", SIZE(irq_data));
- fprintf(fp, " task_union: %ld\n", SIZE(task_union));
- fprintf(fp, " thread_union: %ld\n", SIZE(thread_union));
- fprintf(fp, " prio_array: %ld\n", SIZE(prio_array));
- fprintf(fp, " user_regs_struct: %ld\n",
- SIZE(user_regs_struct));
- fprintf(fp, " switch_stack: %ld\n",
- SIZE(switch_stack));
- fprintf(fp, " vm_area_struct_vm_flags: %ld\n",
- SIZE(vm_area_struct_vm_flags));
- fprintf(fp, " e820map: %ld\n", SIZE(e820map));
- fprintf(fp, " e820entry: %ld\n", SIZE(e820entry));
- fprintf(fp, " cpu_s: %ld\n", SIZE(cpu_s));
- fprintf(fp, " pgd_t: %ld\n", SIZE(pgd_t));
- fprintf(fp, " kallsyms_header: %ld\n",
- SIZE(kallsyms_header));
- fprintf(fp, " kallsyms_symbol: %ld\n",
- SIZE(kallsyms_symbol));
- fprintf(fp, " kallsyms_section: %ld\n",
- SIZE(kallsyms_section));
- fprintf(fp, " block_device: %ld\n",
- SIZE(block_device));
- fprintf(fp, " blk_major_name: %ld\n",
- SIZE(blk_major_name));
- fprintf(fp, " address_space: %ld\n",
- SIZE(address_space));
- fprintf(fp, " gendisk: %ld\n",
- SIZE(gendisk));
- fprintf(fp, " irq_ctx: %ld\n", SIZE(irq_ctx));
- fprintf(fp, " char_device_struct: %ld\n",
- SIZE(char_device_struct));
- fprintf(fp, " spinlock_t: %ld\n",
- SIZE(spinlock_t));
- fprintf(fp, " radix_tree_root: %ld\n",
- SIZE(radix_tree_root));
- fprintf(fp, " radix_tree_node: %ld\n",
- SIZE(radix_tree_node));
- fprintf(fp, " x8664_pda: %ld\n",
- SIZE(x8664_pda));
- fprintf(fp, " ppc64_paca: %ld\n",
- SIZE(ppc64_paca));
- fprintf(fp, " gate_struct: %ld\n",
- SIZE(gate_struct));
- fprintf(fp, " tss_struct: %ld\n",
- SIZE(tss_struct));
- fprintf(fp, " task_struct_start_time: %ld\n",
- SIZE(task_struct_start_time));
- fprintf(fp, " task_struct_utime: %ld\n",
- SIZE(task_struct_utime));
- fprintf(fp, " task_struct_stime: %ld\n",
- SIZE(task_struct_stime));
- fprintf(fp, " cputime_t: %ld\n",
- SIZE(cputime_t));
- fprintf(fp, " mem_section: %ld\n",
- SIZE(mem_section));
- fprintf(fp, " pid_link: %ld\n",
- SIZE(pid_link));
- fprintf(fp, " upid: %ld\n",
- SIZE(upid));
- fprintf(fp, " unwind_table: %ld\n",
- SIZE(unwind_table));
- fprintf(fp, " rlimit: %ld\n",
- SIZE(rlimit));
- fprintf(fp, " cfs_rq: %ld\n",
- SIZE(cfs_rq));
- fprintf(fp, " pcpu_info: %ld\n",
- SIZE(pcpu_info));
- fprintf(fp, " vcpu_struct: %ld\n",
- SIZE(vcpu_struct));
- fprintf(fp, " cdev: %ld\n",
- SIZE(cdev));
- fprintf(fp, " probe: %ld\n",
- SIZE(probe));
- fprintf(fp, " kobj_map: %ld\n",
- SIZE(kobj_map));
- fprintf(fp, " cpu_context_save: %ld\n",
- SIZE(cpu_context_save));
- fprintf(fp, " elf_prstatus: %ld\n",
- SIZE(elf_prstatus));
- fprintf(fp, " note_buf: %ld\n",
- SIZE(note_buf));
- fprintf(fp, " unwind_idx: %ld\n",
- SIZE(unwind_idx));
- fprintf(fp, " s390_stack_frame: %ld\n",
- SIZE(s390_stack_frame));
- fprintf(fp, " percpu_data: %ld\n",
- SIZE(percpu_data));
- fprintf(fp, " sched_entity: %ld\n",
- SIZE(sched_entity));
- fprintf(fp, " kernel_stat: %ld\n",
- SIZE(kernel_stat));
- fprintf(fp, " subsystem: %ld\n",
- SIZE(subsystem));
- fprintf(fp, " class_private: %ld\n",
- SIZE(class_private));
- fprintf(fp, " rq_in_flight: %ld\n",
- SIZE(rq_in_flight));
- fprintf(fp, " class_private_devices: %ld\n",
- SIZE(class_private_devices));
- fprintf(fp, " hstate: %ld\n",
- SIZE(hstate));
- fprintf(fp, " ipc_ids: %ld\n",
- SIZE(ipc_ids));
- fprintf(fp, " shmid_kernel: %ld\n",
- SIZE(shmid_kernel));
- fprintf(fp, " sem_array: %ld\n",
- SIZE(sem_array));
- fprintf(fp, " msg_queue: %ld\n",
- SIZE(msg_queue));
- fprintf(fp, " log: %ld\n",
- SIZE(log));
- fprintf(fp, " log_level: %ld\n",
- SIZE(log_level));
- fprintf(fp, " rt_rq: %ld\n",
- SIZE(rt_rq));
- fprintf(fp, " task_group: %ld\n",
- SIZE(task_group));
- fprintf(fp, " vmap_area: %ld\n",
- SIZE(vmap_area));
- fprintf(fp, " hrtimer_clock_base: %ld\n",
- SIZE(hrtimer_clock_base));
- fprintf(fp, " hrtimer_base: %ld\n",
- SIZE(hrtimer_base));
- fprintf(fp, " tnt: %ld\n",
- SIZE(tnt));
- fprintf(fp, "\n array_table:\n");
- /*
- * Use get_array_length() for those fields not set up at init-time;
- * ARRAY_LENGTH() will work for the rest.
- */
- fprintf(fp, " kmem_cache_s_name: %d\n",
- ARRAY_LENGTH(kmem_cache_s_name));
- fprintf(fp, " kmem_cache_s_c_name: %d\n",
- ARRAY_LENGTH(kmem_cache_s_c_name));
- fprintf(fp, " kmem_cache_s_array: %d\n",
- ARRAY_LENGTH(kmem_cache_s_array));
- fprintf(fp, " kmem_cache_s_cpudata: %d\n",
- ARRAY_LENGTH(kmem_cache_s_cpudata));
- fprintf(fp, " log_buf: %d\n",
- ARRAY_LENGTH(log_buf));
- fprintf(fp, " irq_desc: %d\n",
- ARRAY_LENGTH(irq_desc));
- fprintf(fp, " irq_action: %d\n",
- ARRAY_LENGTH(irq_action));
- fprintf(fp, " timer_vec_vec: %d\n",
- get_array_length("timer_vec.vec", NULL, SIZE(list_head)));
- fprintf(fp, " timer_vec_root_vec: %d\n",
- get_array_length("timer_vec_root.vec", NULL, SIZE(list_head)));
- fprintf(fp, " tvec_root_s_vec: %d\n",
- get_array_length("tvec_root_s.vec", NULL, SIZE(list_head)));
- fprintf(fp, " tvec_s_vec: %d\n",
- get_array_length("tvec_s.vec", NULL, SIZE(list_head)));
- fprintf(fp, " page_hash_table: %d\n",
- ARRAY_LENGTH(page_hash_table));
- fprintf(fp, " net_device_name: %d\n",
- ARRAY_LENGTH(net_device_name));
- fprintf(fp, " neigh_table_hash_buckets: %d\n",
- get_array_length("neigh_table.hash_buckets", NULL,
- sizeof(void *)));
- fprintf(fp, " neighbour_ha: %d\n",
- get_array_length("neighbour.ha", NULL, sizeof(char)));
- fprintf(fp, " swap_info: %d\n",
- get_array_length("swap_info", NULL, 0));
- fprintf(fp, " pglist_data_node_zones: %d\n",
- ARRAY_LENGTH(pglist_data_node_zones));
- fprintf(fp, " zone_struct_free_area: %d\n",
- ARRAY_LENGTH(zone_struct_free_area));
- fprintf(fp, " zone_free_area: %d\n",
- ARRAY_LENGTH(zone_free_area));
- fprintf(fp, " free_area: %d\n",
- ARRAY_LENGTH(free_area));
- fprintf(fp, " free_area_DIMENSION: %d\n",
- ARRAY_LENGTH(free_area_DIMENSION));
- fprintf(fp, " prio_array_queue: %d\n",
- get_array_length("prio_array.queue", NULL, SIZE(list_head)));
- fprintf(fp, " height_to_maxindex: %d\n",
- ARRAY_LENGTH(height_to_maxindex));
- fprintf(fp, " pid_hash: %d\n",
- ARRAY_LENGTH(pid_hash));
- fprintf(fp, " kmem_cache_node: %d\n",
- ARRAY_LENGTH(kmem_cache_node));
- fprintf(fp, " kmem_cache_cpu_slab: %d\n",
- ARRAY_LENGTH(kmem_cache_cpu_slab));
- fprintf(fp, " rt_prio_array_queue: %d\n",
- ARRAY_LENGTH(rt_prio_array_queue));
- if (spec) {
- int in_size_table, in_array_table, arrays, offsets, sizes;
- in_size_table = in_array_table = arrays = offsets = sizes = 0;
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (strstr(buf, "size_table:"))
- in_size_table = TRUE;
- if (strstr(buf, "array_table:")) {
- in_array_table = TRUE;
- in_size_table = FALSE;
- }
- if (strstr(buf, spec)) {
- if (in_size_table) {
- if (!sizes)
- fprintf(pc->saved_fp,
- "%s size_table:\n",
- offsets ? "\n" : "");
- sizes++;
- } else if (in_array_table) {
- if (!arrays)
- fprintf(pc->saved_fp,
- "%s array_table:\n",
- offsets || sizes ?
- "\n" : "");
- arrays++;
- } else {
- if (!offsets)
- fprintf(pc->saved_fp,
- " offset_table:\n");
- offsets++;
- }
- if (strstr(buf, " size_table:") ||
- strstr(buf, " array_table:") ||
- strstr(buf, " offset_table:"))
- break;
-
- fprintf(pc->saved_fp, "%s", buf);
- }
- }
- close_tmpfile();
- }
- if (makestruct) {
- fprintf(pc->saved_fp,
- "static struct builtin_debug_table %s;\n\n",
- revname);
- rewind(pc->tmpfile);
- while (fgets(buf, BUFSIZE, pc->tmpfile)) {
- if (strstr(buf, " offset_table:\n")) {
- fprintf(pc->saved_fp,
- "static struct offset_table %s_offset_table = {\n",
- revname);
- continue;
- }
- if (strstr(buf, " size_table:\n")) {
- fprintf(pc->saved_fp,
- "static struct size_table %s_size_table = {\n",
- revname);
- continue;
- }
- if (strstr(buf, " array_table:\n")) {
- fprintf(pc->saved_fp,
- "static struct array_table %s_array_table = {\n",
- revname);
- continue;
- }
- if (STREQ(buf, "\n")) {
- fprintf(pc->saved_fp, "};\n\n");
- continue;
- }
-
- fprintf(pc->saved_fp, "%s,\n", strip_linefeeds(buf));
- }
- fprintf(pc->saved_fp, "};\n\n");
- close_tmpfile();
- fprintf(fp, "static struct builtin_debug_table %s = {\n",
- revname);
- fprintf(fp, " release: \"%s\",\n", uts->release);
- fprintf(fp, " machine_type: \"%s\",\n", pc->machine_type);
- fprintf(fp, " offset_table: &%s_offset_table,\n", revname);
- fprintf(fp, " size_table: &%s_size_table,\n", revname);
- fprintf(fp, " array_table: &%s_array_table,\n", revname);
- fprintf(fp, "};\n\n");
- }
- pc->flags |= data_debug;
- }
- #define NUMARGS_CACHE_ENTRIES (100)
- static struct numargs_cache {
- ulong function;
- int numargs;
- } numargs_cache[NUMARGS_CACHE_ENTRIES] = { {0} };
- static int numargs_cache_index = 0;
- int
- get_function_numargs(ulong callpc)
- {
- int i;
- struct numargs_cache *na;
- struct gnu_request *req;
- int retval;
- ulong func;
- func = closest_symbol_value(callpc);
- if (!func)
- return -1;
- for (i = 0; i < NUMARGS_CACHE_ENTRIES; i++) {
- na = &numargs_cache[i];
- if (!na->function) {
- numargs_cache_index = i;
- break;
- }
- if (na->function == func)
- return na->numargs;
- }
- req = (struct gnu_request *)GETBUF(sizeof(struct gnu_request));
- req->buf = GETBUF(BUFSIZE);
- req->command = GNU_FUNCTION_NUMARGS;
- req->flags |= GNU_RETURN_ON_ERROR;
- req->pc = func;
- gdb_interface(req);
- if (req->flags & GNU_COMMAND_FAILED) {
- retval = -1;
- goto func_done;
- }
- retval = (int)req->value;
- func_done:
- FREEBUF(req->buf);
- FREEBUF(req);
- numargs_cache_index %= NUMARGS_CACHE_ENTRIES;
- na = &numargs_cache[numargs_cache_index++];
- na->function = func;
- na->numargs = retval;
- return retval;
- }
- /*
- * help -c output
- */
- void
- dump_numargs_cache(void)
- {
- int i;
- struct numargs_cache *na;
- char buf[BUFSIZE];
- fprintf(fp, "numargs_cache_index: %d\n", numargs_cache_index);
- for (i = 0; i < NUMARGS_CACHE_ENTRIES; i++) {
- na = &numargs_cache[i];
- if (!na->function)
- break;
- fprintf(fp, "%lx (%s): %d\n",
- na->function,
- value_to_symstr(na->function, buf, 0),
- na->numargs);
- }
- }
- /*
- * This is the call-back function that is passed to bfd_map_over_sections().
- * Based upon the request, check whether the passed-in section has what
- * the caller needs. The MODULE_SECTIONS code is tricky because it has
- * to keep a running alignment value as it walks through the section
- * headers in order to eventually calculate the module's base data address.
- */
- static void
- section_header_info(bfd *bfd, asection *section, void *reqptr)
- {
- int i;
- struct load_module *lm;
- ulong request;
- asection **sec;
- ulong section_end_address;
- request = ((ulong)reqptr);
- switch (request)
- {
- case (ulong)KERNEL_SECTIONS:
- sec = (asection **)st->sections;
- for (i = 0; (i < st->bfd->section_count) && *sec; i++)
- sec++;
- *sec = section;
- if (STREQ(bfd_get_section_name(bfd, section), ".text.init") ||
- STREQ(bfd_get_section_name(bfd, section), ".init.text")) {
- kt->stext_init = (ulong)
- bfd_get_section_vma(bfd, section);
- kt->etext_init = kt->stext_init +
- (ulong)bfd_section_size(bfd, section);
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".text")) {
- st->first_section_start = (ulong)
- bfd_get_section_vma(bfd, section);
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
- STREQ(bfd_get_section_name(bfd, section), ".data")) {
- if (!(bfd_get_section_flags(bfd, section) & SEC_LOAD))
- st->flags |= NO_SEC_LOAD;
- if (!(bfd_get_section_flags(bfd, section) &
- SEC_HAS_CONTENTS))
- st->flags |= NO_SEC_CONTENTS;
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".eh_frame")) {
- st->dwarf_eh_frame_file_offset = (off_t)section->filepos;
- st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, section);
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) {
- st->dwarf_debug_frame_file_offset = (off_t)section->filepos;
- st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd, section);
- }
- if (st->first_section_start != 0) {
- section_end_address =
- (ulong) bfd_get_section_vma(bfd, section) +
- (ulong) bfd_section_size(bfd, section);
- if (section_end_address > st->last_section_end)
- st->last_section_end = section_end_address;
- }
- break;
- case (ulong)MODULE_SECTIONS:
- lm = st->current;
- store_section_data(lm, bfd, section);
- break;
- case (ulong)VERIFY_SECTIONS:
- if (STREQ(bfd_get_section_name(bfd, section), ".text") ||
- STREQ(bfd_get_section_name(bfd, section), ".data")) {
- if (!(bfd_get_section_flags(bfd, section) & SEC_LOAD))
- st->flags |= NO_SEC_LOAD;
- if (!(bfd_get_section_flags(bfd, section) &
- SEC_HAS_CONTENTS))
- st->flags |= NO_SEC_CONTENTS;
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".eh_frame")) {
- st->dwarf_eh_frame_file_offset = (off_t)section->filepos;
- st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, section);
- }
- if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) {
- st->dwarf_debug_frame_file_offset = (off_t)section->filepos;
- st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd, section);
- }
- break;
- default:
- error(FATAL, "invalid call to section_header_info\n");
- break;
- }
- }
- /*
- * Emulate insmod by calculating the priorities of each section.
- * The priority number will be used later by calculate_load_order()
- * to determine the the starting addresses of the text and data
- * sections.
- *
- * insmod uses the following code sequence -- which references the actual ELF
- * section header structure data:
- *
- * ac = 0;
- * if (a->name[0] != '.' || strlen(a->name) != 10 ||
- * strcmp(a->name + 5, ".init")) ac |= 32;
- * if (af & SHF_ALLOC) ac |= 16;
- * if (!(af & SHF_WRITE)) ac |= 8;
- * if (af & SHF_EXECINSTR) ac |= 4;
- * if (a->header.sh_type != SHT_NOBITS) ac |= 2;
- *
- * BFD abstracts the ELF section header into an asection structure, so this
- * code determines the priority using the relevant logic.
- */
- static void
- store_section_data(struct load_module *lm, bfd *bfd, asection *section)
- {
- int i;
- int prio;
- char *name;
- prio = 0;
- name = (char *)bfd_get_section_name(bfd, section);
- if (name[0] != '.' || strlen(name) != 10 || strcmp(name + 5, ".init"))
- prio |= 32;
- if (section->flags & SEC_ALLOC)
- prio |= 16;
- if (section->flags & SEC_READONLY)
- prio |= 8;
- if (section->flags & SEC_CODE)
- prio |= 4;
- if (!STREQ(name, ".bss"))
- prio |= 2;
- i = lm->mod_sections;
- lm->mod_section_data[i].section = section;
- lm->mod_section_data[i].priority = prio;
- lm->mod_section_data[i].flags = section->flags & ~SEC_FOUND;
- /*
- * The percpu section isn't included in kallsyms or module_core area.
- */
- if (lm->mod_percpu &&
- (STREQ(name,".data.percpu") || STREQ(name, ".data..percpu"))) {
- lm->mod_percpu_size = bfd_section_size(bfd, section);
- lm->mod_section_data[i].flags |= SEC_FOUND;
- }
- lm->mod_section_data[i].size = bfd_section_size(bfd, section);
- lm->mod_section_data[i].offset = 0;
- if (strlen(name) < MAX_MOD_SEC_NAME)
- strcpy(lm->mod_section_data[i].name, name);
- else
- strncpy(lm->mod_section_data[i].name, name, MAX_MOD_SEC_NAME-1);
- lm->mod_sections += 1;
- }
- /*
- * insmod first calculates a priority for each module section, and re-orders
- * the sections from their ELF object file position -- that priority was
- * determined in store_section_priority(). Now, based upon a priority-based
- * ordering, this routine calculates the starting offset for each section.
- * This is the code segment from insmod that is being emulated here:
- *
- * unsigned long
- * obj_load_size (struct obj_file *f)
- * {
- * unsigned long dot = 0;
- * struct obj_section *sec;
- *
- * /+ Finalize the positions of the sections relative to one another. +/
- *
- * for (sec = f->load_order; sec ; sec = sec->load_next)
- * {
- * ElfW(Addr) align;
- *
- * align = sec->header.sh_addralign;
- * if (align && (dot & (align - 1)))
- * dot = (dot | (align - 1)) + 1;
- *
- * sec->header.sh_addr = dot;
- * dot += sec->header.sh_size;
- * }
- *
- * return dot;
- * }
- *
- * Another insmod hack extends the .kstrtab section with a string containing
- * the name of the module. If the .kstrtab comes before the .data section,
- * it in turn gets bumped up.
- *
- * BFD abstracts the ELF section header into an asection structure, so this
- * code determines the priority using the relevant logic.
- *
- * Later versions of insmod do the work for us by creating pseudo-symbols
- * that contain the base address of the text, rodata, data and bss sections.
- * When that's the case, veer off to check_insmod_builtin() to potentially
- * override the offset value calculated here.
- */
- static void
- calculate_load_order_v1(struct load_module *lm, bfd *bfd)
- {
- int i;
- asection *section;
- ulong alignment;
- ulong offset;
- offset = 0;
- switch (kt->flags & (KMOD_V1|KMOD_V2))
- {
- case KMOD_V1:
- offset = lm->mod_size_of_struct;
- break;
- case KMOD_V2:
- offset = lm->mod_base;
- break;
- }
- qsort(&lm->mod_section_data[0], lm->mod_sections,
- sizeof(struct mod_section_data), compare_prios);
- for (i = (lm->mod_sections-1); i >= 0; i--) {
- section = lm->mod_section_data[i].section;
- alignment = power(2, bfd_get_section_alignment(bfd, section));
- if (alignment && (offset & (alignment - 1)))
- offset = (offset | (alignment - 1)) + 1;
- lm->mod_section_data[i].offset = offset;
- if (CRASHDEBUG(1))
- fprintf(fp, "%12s prio: %x flags: %x offset: %lx\n",
- lm->mod_section_data[i].name,
- lm->mod_section_data[i].priority,
- lm->mod_section_data[i].flags,
- lm->mod_section_data[i].offset);
- if (st->flags & INSMOD_BUILTIN)
- check_insmod_builtin(lm, i, &offset);
- if (STREQ(lm->mod_section_data[i].name, ".text"))
- lm->mod_text_start = lm->mod_base + offset;
- if (STREQ(lm->mod_section_data[i].name, ".data"))
- lm->mod_data_start = lm->mod_base + offset;
- if (STREQ(lm->mod_section_data[i].name, ".bss"))
- lm->mod_bss_start = lm->mod_base + offset;
- if (STREQ(lm->mod_section_data[i].name, ".rodata"))
- lm->mod_rodata_start = lm->mod_base + offset;
- offset += bfd_section_size(bfd, section);
- if (STREQ(bfd_get_section_name(bfd, section), ".kstrtab"))
- offset += strlen(lm->mod_name)+1;
- }
- }
- /*
- * Later versions of kmod no longer get the help from insmod,
- * and while the heuristics might work, it's relatively
- * straightforward to just try to match the sections in the object file
- * with exported symbols.
- *
- * This works well if kallsyms is set, but may not work so well in other
- * instances.
- */
- static void
- calculate_load_order_v2(struct load_module *lm, bfd *bfd, int dynamic,
- void *minisyms, long symcount, unsigned int size)
- {
- struct syment *s1, *s2;
- ulong sec_start;
- bfd_byte *from, *fromend;
- asymbol *store;
- asymbol *sym;
- symbol_info syminfo;
- char *secname;
- int i;
- if ((store = bfd_make_empty_symbol(bfd)) == NULL)
- error(FATAL, "bfd_make_empty_symbol() failed\n");
- s1 = lm->mod_symtable;
- s2 = lm->mod_symend;
- while (s1 < s2) {
- ulong sym_offset = s1->value - lm->mod_base;
- if (MODULE_PSEUDO_SYMBOL(s1)) {
- s1++;
- continue;
- }
- /* Skip over symbols whose sections have been identified. */
- for (i = 0; i < lm->mod_sections; i++) {
- if ((lm->mod_section_data[i].flags & SEC_FOUND) == 0)
- continue;
- if (sym_offset >= lm->mod_section_data[i].offset
- && sym_offset < lm->mod_section_data[i].offset
- + lm->mod_section_data[i].size) {
- break;
- }
- }
- /* Matched one of the sections. Skip symbol. */
- if (i < lm->mod_sections) {
- if (CRASHDEBUG(2)) {
- fprintf(fp, "skip %lx %s %s\n", s1->value, s1->name,
- lm->mod_section_data[i].name);
- }
- s1++;
- continue;
- }
- /* Find the symbol in the object file. */
- from = (bfd_byte *) minisyms;
- fromend = from + symcount * size;
- secname = NULL;
- for (; from < fromend; from += size) {
- if ((sym = bfd_minisymbol_to_symbol(bfd, dynamic, from,
- store)) == NULL)
- error(FATAL,
- "bfd_minisymbol_to_symbol() failed\n");
- bfd_get_symbol_info(bfd, sym, &syminfo);
- if (CRASHDEBUG(3)) {
- fprintf(fp,"matching sym %s %lx against bfd %s %lx\n",
- s1->name, (long) s1->value, syminfo.name,
- (long) syminfo.value);
- }
- if (strcmp(syminfo.name, s1->name) == 0) {
- secname = (char *)bfd_get_section_name(bfd, sym->section);
- break;
- }
- }
- if (secname == NULL) {
- if (CRASHDEBUG(1)) {
- fprintf(fp, "symbol %s not found in module\n", s1->name);
- }
- s1++;
- continue;
- }
- /* Match the section it came in. */
- for (i = 0; i < lm->mod_sections; i++) {
- if (STREQ(lm->mod_section_data[i].name, secname)) {
- break;
- }
- }
- if (i == lm->mod_sections) {
- fprintf(fp, "?? Section %s not found for symbol %s\n",
- secname, s1->name);
- s1++;
- continue;
- }
- /* Update the offset information for the section */
- sec_start = s1->value - syminfo.value;
- // sec_end = sec_start + lm->mod_section_data[i].size;
- lm->mod_section_data[i].offset = sec_start - lm->mod_base;
- lm->mod_section_data[i].flags |= SEC_FOUND;
- if (CRASHDEBUG(2)) {
- fprintf(fp, "update sec offset sym %s @ %lx val %lx section %s\n",
- s1->name, s1->value, (ulong)syminfo.value, secname);
- }
- if (strcmp(secname, ".text") == 0)
- lm->mod_text_start = sec_start;
- if (strcmp(secname, ".bss") == 0)
- lm->mod_bss_start = sec_start;
- if (strcmp(secname, ".data") == 0)
- lm->mod_data_start = sec_start;
- if (strcmp(secname, ".data") == 0)
- lm->mod_data_start = sec_start;
- if (strcmp(secname, ".rodata") == 0)
- lm->mod_rodata_start = sec_start;
- s1++;
- }
- }
- /*
- * Later versons of insmod store basic address information of each
- * module in a format that looks like the following example of the
- * nfsd module:
- *
- * d004d000 __insmod_nfsd_O/lib/modules/2.2.17/fs/nfsd.o_M3A7EE300_V131601
- * d004d054 __insmod_nfsd_S.text_L30208
- * d0054840 __insmod_nfsd_S.rodata_L8930
- * d0056b40 __insmod_nfsd_S.data_L1220
- * d00570c0 __insmod_nfsd_S.bss_L123840
- *
- * When that's true, override the offset value made by calculate_load_order().
- */
- static void
- check_insmod_builtin(struct load_module *lm, int index, ulong *offset)
- {
- struct syment *sp;
- char buf[BUFSIZE];
- ulong offs;
- sprintf(buf, "__insmod_%s_S%s",
- lm->mod_name,
- lm->mod_section_data[index].name);
- if (symbol_query(buf, NULL, &sp) == 1) {
- if (CRASHDEBUG(1))
- fprintf(fp, "check_insmod_builtin: %lx %s\n",
- sp->value, sp->name);
- offs = sp->value - lm->mod_base;
- if (offs != *offset) {
- if (CRASHDEBUG(1))
- fprintf(fp,
- "check_insmod_builtin: [%s] %s %lx != %lx\n",
- lm->mod_name,
- lm->mod_section_data[index].name,
- offs, *offset);
- *offset = offs;
- }
- }
- }
- /*
- * Determine whether a module symbol is one of the insmod-created symbols
- * described above.
- */
- static int
- is_insmod_builtin(struct load_module *lm, struct syment *sp)
- {
- char buf[BUFSIZE];
- if (!(st->flags & INSMOD_BUILTIN))
- return FALSE;
- sprintf(buf, "__insmod_%s_S", lm->mod_name);
- if (strstr(sp->name, buf))
- return TRUE;
- return FALSE;
- }
- /*
- * Modified from typical "qsort" help functions to simulate section-ordering
- * done by insmod when loading modules.
- */
- static int
- compare_prios(const void *v1, const void *v2)
- {
- struct mod_section_data *md1, *md2;
- md1 = (struct mod_section_data *)v1;
- md2 = (struct mod_section_data *)v2;
- return (md1->priority < md2->priority ? -1 : 1);
- }
- /*
- * This routine scours a module object file namelist for global text and
- * data symbols, sorting and storing them in a static table for quick
- * reference. This allows access to non-EXPORT_SYMBOL() symbols.
- * The object file is then passed to gdb for loading of all symbolic
- * and debugging data.
- *
- * Thanks to David Addison (addy@quadrics.com) for the suggestion.
- */
- int
- load_module_symbols(char *modref, char *namelist, ulong base_addr)
- {
- static bfd *mbfd;
- char **matching;
- long symcount;
- void *minisyms;
- unsigned int size;
- int result;
- struct load_module *lm;
- asymbol *sort_x;
- asymbol *sort_y;
- if (!is_module_name(modref, NULL, &lm))
- error(FATAL, "%s: not a loaded module name\n", modref);
- if ((lm->mod_flags & MOD_LOAD_SYMS) || strlen(lm->mod_namelist)) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: module symbols are already loaded\n",
- modref);
- return TRUE;
- }
- if (CRASHDEBUG(2))
- fprintf(fp, "load_module_symbols: %s %s %lx %lx\n",
- modref, namelist, base_addr, kt->flags);
- switch (kt->flags & (KMOD_V1|KMOD_V2))
- {
- case KMOD_V1:
- break;
- case KMOD_V2:
- st->current = lm;
- BZERO(lm->mod_namelist, MAX_MOD_NAMELIST);
- if (strlen(namelist) < MAX_MOD_NAMELIST)
- strcpy(lm->mod_namelist, namelist);
- else
- strncpy(lm->mod_namelist, namelist, MAX_MOD_NAMELIST-1);
- if (st->flags & USE_OLD_ADD_SYM)
- goto add_symbols;
- }
- if ((mbfd = bfd_openr(namelist, NULL)) == NULL)
- error(FATAL, "cannot open object file: %s\n", namelist);
- if (!bfd_check_format_matches(mbfd, bfd_object, &matching))
- error(FATAL, "cannot determine object file format: %s\n",
- namelist);
- if (LKCD_KERNTYPES() && (file_elf_version(namelist) == EV_DWARFEXTRACT))
- goto add_symbols; /* no symbols, add the debuginfo */
- if (!(bfd_get_file_flags(mbfd) & HAS_SYMS))
- error(FATAL, "no symbols in object file: %s\n", namelist);
- symcount = bfd_read_minisymbols(mbfd, FALSE, &minisyms, &size);
- if (symcount < 0)
- error(FATAL, "cannot access symbol table data: %s\n",
- namelist);
- else if (symcount == 0)
- error(FATAL, "no symbols in object file: %s\n", namelist);
- if (CRASHDEBUG(2)) {
- fprintf(fp, "%ld symbols found in obj file %s\n", symcount,
- namelist);
- }
- sort_x = bfd_make_empty_symbol(mbfd);
- sort_y = bfd_make_empty_symbol(mbfd);
- if (sort_x == NULL || sort_y == NULL)
- error(FATAL, "bfd_make_empty_symbol() failed\n");
- gnu_qsort(mbfd, minisyms, symcount, size, sort_x, sort_y);
- store_load_module_symbols(mbfd, FALSE, minisyms, symcount,
- size, base_addr, namelist);
- free(minisyms);
- bfd_close(mbfd);
- add_symbols:
- result = add_symbol_file(st->current);
- if (CRASHDEBUG(2))
- check_for_dups(st->current);
- st->current = NULL;
- return result;
- }
- /*
- * Add a module's symbol file data to gdb's notion of the world.
- */
- static int
- add_symbol_file(struct load_module *lm)
- {
- struct gnu_request request, *req;
- char buf[BUFSIZE];
- int i, len;
- char *secname;
- req = &request;
- BZERO(req, sizeof(struct gnu_request));
- if ((lm->mod_flags & MOD_KALLSYMS) &&
- add_symbol_file_kallsyms(lm, req))
- return TRUE;
- for (i = len = 0; i < lm->mod_sections; i++)
- {
- secname = lm->mod_section_data[i].name;
- if ((lm->mod_section_data[i].flags & SEC_FOUND) &&
- (!STREQ(secname, ".text") &&
- !STREQ(secname, ".data.percpu") &&
- !STREQ(secname, ".data..percpu"))) {
- sprintf(buf, " -s %s 0x%lx", secname,
- lm->mod_section_data[i].offset + lm->mod_base);
- len += strlen(buf);
- }
- }
- for (i = 0; i < lm->mod_sections; i++)
- {
- secname = lm->mod_section_data[i].name;
- if ((lm->mod_section_data[i].flags & SEC_FOUND) &&
- (STREQ(secname, ".data.percpu") ||
- STREQ(secname, ".data..percpu"))) {
- sprintf(buf, " -s %s 0x%lx", secname, lm->mod_percpu);
- len += strlen(buf);
- }
- }
- if (pc->curcmd_flags & MOD_READNOW)
- lm->mod_flags |= MOD_DO_READNOW;
- req->command = GNU_ADD_SYMBOL_FILE;
- req->addr = (ulong)lm;
- req->buf = GETBUF(len+BUFSIZE);
- if (!CRASHDEBUG(1))
- req->fp = pc->nullfp;
- st->flags |= ADD_SYMBOL_FILE;
- gdb_interface(req);
- st->flags &= ~ADD_SYMBOL_FILE;
- FREEBUF(req->buf);
- sprintf(buf, "set complaints 0");
- gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
- return(!(req->flags & GNU_COMMAND_FAILED));
- }
- static int
- add_symbol_file_percpu(struct load_module *lm, struct gnu_request *req, int buflen)
- {
- char pbuf[BUFSIZE];
- int i, len;
- char *secname;
- len = strlen(req->buf);
- for (i = 0; i < lm->mod_sections; i++) {
- secname = lm->mod_section_data[i].name;
- if ((lm->mod_section_data[i].flags & SEC_FOUND) &&
- (STREQ(secname, ".data.percpu") ||
- STREQ(secname, ".data..percpu"))) {
- sprintf(pbuf, " -s %s 0x%lx", secname, lm->mod_percpu);
- while ((len + strlen(pbuf)) >= buflen) {
- RESIZEBUF(req->buf, buflen, buflen * 2);
- buflen *= 2;
- }
- strcat(req->buf, pbuf);
- len += strlen(pbuf);
- }
- }
- return buflen;
- }
- /*
- * Gather the module section data from the in-kernel data structures.
- */
- static int
- add_symbol_file_kallsyms(struct load_module *lm, struct gnu_request *req)
- {
- int len, buflen, done, nsections, retval;
- ulong vaddr, array_entry, attribute, owner, name, address;
- long name_type;
- char buf[BUFSIZE];
- char section_name[BUFSIZE];
- ulong section_vaddr;
- #if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1)
- return FALSE;
- #endif
- if (!(st->flags & (MODSECT_VMASK|MODSECT_UNKNOWN))) {
- STRUCT_SIZE_INIT(module_sect_attr, "module_sect_attr");
- MEMBER_OFFSET_INIT(module_sect_attrs,
- "module", "sect_attrs");
- MEMBER_OFFSET_INIT(module_sect_attrs_attrs,
- "module_sect_attrs", "attrs");
- MEMBER_OFFSET_INIT(module_sect_attrs_nsections,
- "module_sect_attrs", "nsections");
- MEMBER_OFFSET_INIT(module_sect_attr_mattr,
- "module_sect_attr", "mattr");
- MEMBER_OFFSET_INIT(module_sect_attr_name,
- "module_sect_attr", "name");
- MEMBER_OFFSET_INIT(module_sect_attr_address,
- "module_sect_attr", "address");
- MEMBER_OFFSET_INIT(module_attribute_attr,
- "module_attribute", "attr");
- MEMBER_OFFSET_INIT(module_sect_attr_attr,
- "module_sect_attr", "attr");
- MEMBER_OFFSET_INIT(module_sections_attrs,
- "module_sections", "attrs");
- MEMBER_OFFSET_INIT(attribute_owner,
- "attribute", "owner");
- if (VALID_MEMBER(module_sect_attrs_attrs) &&
- VALID_MEMBER(module_sect_attr_mattr) &&
- VALID_MEMBER(module_attribute_attr) &&
- VALID_MEMBER(module_sect_attrs_nsections))
- st->flags |= MODSECT_V3;
- else if (VALID_MEMBER(module_sect_attrs_attrs) &&
- VALID_MEMBER(module_sect_attr_mattr) &&
- VALID_MEMBER(module_attribute_attr))
- st->flags |= MODSECT_V2;
- else if (VALID_MEMBER(module_sect_attr_attr) &&
- VALID_MEMBER(module_sections_attrs))
- st->flags |= MODSECT_V1;
- else
- st->flags |= MODSECT_UNKNOWN;
- if ((st->flags & MODSECT_UNKNOWN) ||
- !VALID_STRUCT(module_sect_attr) ||
- (INVALID_MEMBER(attribute_owner) &&
- (st->flags & (MODSECT_V1|MODSECT_V2))) ||
- INVALID_MEMBER(module_sect_attrs) ||
- INVALID_MEMBER(module_sect_attr_name) ||
- INVALID_MEMBER(module_sect_attr_address)) {
- if (CRASHDEBUG(1))
- error(WARNING,
- "module section data structures "
- "unrecognized or changed\n");
- st->flags &= ~(MODSECT_VMASK);
- st->flags |= MODSECT_UNKNOWN;
- return FALSE;
- }
- } else if (st->flags & MODSECT_UNKNOWN)
- return FALSE;
- if (!readmem(lm->module_struct + OFFSET(module_sect_attrs),
- KVADDR, &vaddr, sizeof(void *), "module.sect_attrs",
- RETURN_ON_ERROR|QUIET))
- return FALSE;
- array_entry = attribute = 0;
- switch (st->flags & MODSECT_VMASK)
- {
- case MODSECT_V1:
- array_entry = vaddr + OFFSET(module_sections_attrs);
- nsections = UNUSED;
- break;
- case MODSECT_V2:
- array_entry = vaddr + OFFSET(module_sect_attrs_attrs);
- nsections = UNUSED;
- break;
- case MODSECT_V3:
- array_entry = vaddr + OFFSET(module_sect_attrs_attrs);
- if (!readmem(vaddr + OFFSET(module_sect_attrs_nsections),
- KVADDR, &nsections, sizeof(int),
- "module_sect_attrs.nsections", RETURN_ON_ERROR|QUIET))
- return FALSE;
- if (CRASHDEBUG(2))
- fprintf(fp, "nsections: %d\n", nsections);
- break;
- }
- if (CRASHDEBUG(2))
- fprintf(fp, "%s:\n", lm->mod_namelist);
- name_type = MEMBER_TYPE("module_sect_attr", "name");
- req->buf = GETBUF(buflen = 1024);
- retval = FALSE;
- for (done = FALSE; !done; array_entry += SIZE(module_sect_attr)) {
- switch (st->flags & MODSECT_VMASK)
- {
- case MODSECT_V1:
- attribute = array_entry + OFFSET(module_sect_attr_attr);
- break;
- case MODSECT_V2:
- case MODSECT_V3:
- attribute = array_entry + OFFSET(module_sect_attr_mattr)
- + OFFSET(module_attribute_attr);
- break;
- }
-
- if (st->flags & (MODSECT_V1|MODSECT_V2))
- owner = attribute + OFFSET(attribute_owner);
- else
- owner = UNUSED;
- address = array_entry + OFFSET(module_sect_attr_address);
- switch (name_type)
- {
- case TYPE_CODE_ARRAY:
- name = array_entry + OFFSET(module_sect_attr_name);
- break;
- case TYPE_CODE_PTR:
- if (!readmem(array_entry + OFFSET(module_sect_attr_name),
- KVADDR, &name, sizeof(void *),
- "module_sect_attr.name", RETURN_ON_ERROR|QUIET)) {
- done = TRUE;
- retval = FALSE;
- continue;
- }
- break;
- default:
- done = TRUE;
- retval = FALSE;
- }
- if (CRASHDEBUG(2)) {
- fprintf(fp, "attribute: %lx ", attribute);
- if (owner == UNUSED)
- fprintf(fp, " owner: (not used)");
- else
- fprintf(fp, " owner: %lx ", owner);
- fprintf(fp, " name: %lx ", name);
- fprintf(fp, " address: %lx\n", address);
- }
-
- if (nsections == UNUSED) {
- if (!readmem(owner, KVADDR, &vaddr, sizeof(void *),
- "attribute.owner", RETURN_ON_ERROR|QUIET)) {
- done = TRUE;
- continue;
- }
-
- if (lm->module_struct != vaddr) {
- done = TRUE;
- continue;
- }
- }
-
- BZERO(section_name, BUFSIZE);
- if (!read_string(name, section_name, 32)) {
- done = TRUE;
- retval = FALSE;
- continue;
- }
- if (!readmem(address, KVADDR, §ion_vaddr, sizeof(void *),
- "module_sect_attr.address", RETURN_ON_ERROR|QUIET)) {
- done = TRUE;
- retval = FALSE;
- continue;
- }
-
- if (CRASHDEBUG(1))
- fprintf(fp, "%lx %s\n", section_vaddr, section_name);
- len = strlen(req->buf);
- if (STREQ(section_name, ".text")) {
- sprintf(buf, "add-symbol-file %s 0x%lx %s",
- lm->mod_namelist, section_vaddr,
- pc->curcmd_flags & MOD_READNOW ? "-readnow" : "");
- while ((len + strlen(buf)) >= buflen) {
- RESIZEBUF(req->buf, buflen, buflen * 2);
- buflen *= 2;
- }
- shift_string_right(req->buf, strlen(buf));
- strncpy(req->buf, buf, strlen(buf));
- retval = TRUE;
- } else {
- sprintf(buf, " -s %s 0x%lx", section_name, section_vaddr);
- while ((len + strlen(buf)) >= buflen) {
- RESIZEBUF(req->buf, buflen, buflen * 2);
- buflen *= 2;
- }
- strcat(req->buf, buf);
- }
- if (nsections != UNUSED) {
- if (--nsections == 0)
- done = TRUE;
- }
- }
- if (retval == FALSE) {
- if (CRASHDEBUG(1))
- fprintf(fp, "%s: add_symbol_file_kallsyms failed\n",
- lm->mod_namelist);
- FREEBUF(req->buf);
- req->buf = NULL;
- return FALSE;
- }
- /*
- * Special case for per-cpu symbols
- */
- buflen = add_symbol_file_percpu(lm, req, buflen);
- lm->mod_flags |= MOD_NOPATCH;
- req->command = GNU_ADD_SYMBOL_FILE;
- req->addr = (ulong)lm;
- if (!CRASHDEBUG(1))
- req->fp = pc->nullfp;
- st->flags |= ADD_SYMBOL_FILE;
- gdb_interface(req);
- st->flags &= ~ADD_SYMBOL_FILE;
- FREEBUF(req->buf);
- sprintf(buf, "set complaints 0");
- gdb_pass_through(buf, NULL, GNU_RETURN_ON_ERROR);
- return(!(req->flags & GNU_COMMAND_FAILED));
- }
- /*
- * Given a syment structure of a valid symbol, determine which
- * load_module (if any) it belongs to.
- */
- static int
- load_module_index(struct syment *sp)
- {
- int i;
- ulong value;
- struct load_module *lm;
- value = sp->value;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (IN_MODULE(value, lm))
- return i;
- if (IN_MODULE_INIT(value, lm))
- return i;
- }
- return (error(FATAL, "cannot find %lx (%s) in module space\n",
- sp->value, sp->name));
- }
- /*
- * Return the syment of a kallsyms-generated module symbol.
- */
- static struct syment *
- kallsyms_module_symbol(struct load_module *lm, symbol_info *syminfo)
- {
- struct syment *sp, *spx;
- int cnt;
- if (!(lm->mod_flags & MOD_KALLSYMS))
- return NULL;
- sp = NULL;
- cnt = 0;
- for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) {
- if (!STREQ(spx->name, syminfo->name))
- continue;
- if (spx->cnt) {
- cnt++;
- continue;
- }
- spx->cnt++;
- sp = spx;
- break;
- }
- if (CRASHDEBUG(2)) {
- if (cnt)
- fprintf(fp, "kallsyms [%s] %s: multiply defined\n",
- lm->mod_name, syminfo->name);
- if (sp)
- fprintf(fp, "kallsyms [%s] %s: %lx\n",
- lm->mod_name, syminfo->name, sp->value);
- else
- fprintf(fp, "kallsyms [%s] %s: NOT FOUND\n",
- lm->mod_name, syminfo->name);
- }
- return sp;
- }
- /*
- * Replace the externally-defined module symbols found in store_load_modules()
- * with all the text and data symbols found in the load module object file.
- */
- static void
- store_load_module_symbols(bfd *bfd, int dynamic, void *minisyms,
- long symcount, unsigned int size, ulong base_addr, char *namelist)
- {
- int i;
- asymbol *store;
- asymbol *sym;
- bfd_byte *from, *fromend;
- symbol_info syminfo;
- struct syment *sp, *spx;
- struct load_module *lm;
- char name[BUFSIZE];
- char *nameptr, *secname;
- long index;
- long symalloc;
- int found;
- if ((store = bfd_make_empty_symbol(bfd)) == NULL)
- error(FATAL, "bfd_make_empty_symbol() failed\n");
- st->current = lm = NULL;
- /*
- * Find out whether this module has already been loaded. Coming
- * out of this for loop, lm->mod_load_symtable will either be set to
- * a reusable symbol table, or NULL if it needs to be re-malloc'd.
- */
- for (i = symalloc = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_base == base_addr) {
- symalloc = symcount + lm->mod_ext_symcnt;
- if (lm->mod_load_symtable &&
- (lm->mod_symalloc < symalloc)) {
- free(lm->mod_load_symtable);
- namespace_ctl(NAMESPACE_FREE,
- &lm->mod_load_namespace, NULL, NULL);
- lm->mod_load_symtable = NULL;
- }
- break;
- }
- }
- if (i == st->mods_installed)
- error(FATAL, "cannot find module at %lx\n", base_addr);
- if (!lm->mod_load_symtable) {
- if ((lm->mod_load_symtable = (struct syment *)
- calloc(symalloc, sizeof(struct syment))) == NULL)
- error(FATAL, "module syment space malloc: %s\n",
- strerror(errno));
- if (!namespace_ctl(NAMESPACE_INIT, &lm->mod_load_namespace,
- (void *)symalloc, NULL))
- error(FATAL, "module name space malloc: %s\n",
- strerror(errno));
- } else
- namespace_ctl(NAMESPACE_REUSE, &lm->mod_load_namespace,
- NULL, NULL);
- st->current = lm;
- lm->mod_symalloc = symalloc;
- BZERO(lm->mod_namelist, MAX_MOD_NAMELIST);
- if (strlen(namelist) < MAX_MOD_NAMELIST)
- strcpy(lm->mod_namelist, namelist);
- else
- strncpy(lm->mod_namelist, namelist, MAX_MOD_NAMELIST-1);
- lm->mod_text_start = lm->mod_data_start = 0;
- lm->mod_rodata_start = lm->mod_bss_start = 0;
- lm->mod_load_symcnt = 0;
- lm->mod_sections = 0;
- for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++)
- spx->cnt = 0;
- sp = lm->mod_load_symtable;
- if (!(lm->mod_section_data = (struct mod_section_data *)
- malloc(sizeof(struct mod_section_data) *
- (bfd->section_count+1))))
- error(FATAL, "module section data array malloc: %s\n",
- strerror(errno));
- bfd_map_over_sections(bfd, section_header_info, MODULE_SECTIONS);
- if (kt->flags & KMOD_V1)
- calculate_load_order_v1(lm, bfd);
- else
- calculate_load_order_v2(lm, bfd, dynamic, minisyms,
- symcount, size);
- from = (bfd_byte *) minisyms;
- fromend = from + symcount * size;
- for (; from < fromend; from += size)
- {
- if ((sym = bfd_minisymbol_to_symbol(bfd, dynamic, from, store))
- == NULL)
- error(FATAL, "bfd_minisymbol_to_symbol() failed\n");
- bfd_get_symbol_info(bfd, sym, &syminfo);
- secname = (char *)bfd_get_section_name(bfd, sym->section);
- found = 0;
- if (kt->flags & KMOD_V1) {
- switch (syminfo.type)
- {
- case 'b':
- case 'B':
- if (CRASHDEBUG(2))
- fprintf(fp, "%08lx (%c) [%s] %s\n",
- (ulong)syminfo.value,
- syminfo.type, secname, syminfo.name);
- if (!lm->mod_bss_start)
- break;
- syminfo.value += lm->mod_bss_start;
- found = 1;
- break;
- case 'd':
- case 'D':
- if (CRASHDEBUG(2))
- fprintf(fp, "%08lx (%c) [%s] %s\n",
- (ulong)syminfo.value,
- syminfo.type, secname, syminfo.name);
- if (STREQ(secname, ".rodata")) {
- if (!lm->mod_rodata_start)
- break;
- syminfo.value += lm->mod_rodata_start;
- } else {
- if (!lm->mod_data_start)
- break;
- syminfo.value += lm->mod_data_start;
- }
- found = 1;
- break;
- case 't':
- case 'T':
- if (CRASHDEBUG(2))
- fprintf(fp, "%08lx (%c) [%s] %s\n",
- (ulong)syminfo.value,
- syminfo.type, secname, syminfo.name);
- if (! lm->mod_text_start) {
- break;
- }
- if ((st->flags & INSMOD_BUILTIN) &&
- (STREQ(name, "init_module") ||
- STREQ(name, "cleanup_module")))
- break;
- syminfo.value += lm->mod_text_start;
- found = 1;
- break;
- default:
- break;
- }
- } else {
- /* Match the section it came in. */
- for (i = 0; i < lm->mod_sections; i++) {
- if (STREQ(lm->mod_section_data[i].name, secname)
- && (lm->mod_section_data[i].flags & SEC_FOUND)) {
- break;
- }
- }
- if (i < lm->mod_sections) {
- if (CRASHDEBUG(2))
- fprintf(fp, "%08lx (%c) [%s] %s\n",
- (ulong)syminfo.value,
- syminfo.type, secname, syminfo.name);
- if ((st->flags & INSMOD_BUILTIN) &&
- (STREQ(name, "init_module") ||
- STREQ(name, "cleanup_module")))
- found = FALSE;
- else if (syminfo.name[0] == '.')
- found = FALSE;
- else if ((spx = kallsyms_module_symbol(lm, &syminfo))) {
- syminfo.value = spx->value;
- found = TRUE;
- } else if (lm->mod_percpu &&
- (STREQ(secname, ".data.percpu") ||
- STREQ(secname, ".data..percpu"))) {
- syminfo.value += lm->mod_percpu;
- found = TRUE;
- } else {
- syminfo.value += lm->mod_section_data[i].offset + lm->mod_base;
- found = TRUE;
- }
- }
- }
- if (found) {
- strcpy(name, syminfo.name);
- strip_module_symbol_end(name);
- strip_symbol_end(name, NULL);
- if (machdep->verify_symbol(name, syminfo.value,
- syminfo.type)) {
- sp->value = syminfo.value;
- sp->type = syminfo.type;
- sp->flags |= MODULE_SYMBOL;
- namespace_ctl(NAMESPACE_INSTALL,
- &lm->mod_load_namespace, sp, name);
- if (CRASHDEBUG(2))
- fprintf(fp, "installing %c %08lx %s\n", syminfo.type, sp->value,
- name);
- sp++;
- lm->mod_load_symcnt++;
- }
- }
- }
- lm->mod_load_symend = &lm->mod_load_symtable[lm->mod_load_symcnt];
- /*
- * Merge in any externals that didn't show up in the four
- * syminfo data types accepted above, plus the two pseudo symbols.
- * Note that the new syment name pointers haven't been resolved yet.
- */
- for (spx = lm->mod_ext_symtable; spx <= lm->mod_ext_symend; spx++) {
- found = FALSE;
- for (sp = lm->mod_load_symtable;
- sp < lm->mod_load_symend; sp++) {
- index = (long)sp->name;
- nameptr = &lm->mod_load_namespace.address[index];
- if (STREQ(spx->name, nameptr)) {
- found = TRUE;
- if (spx->value == sp->value) {
- if (CRASHDEBUG(2))
- fprintf(fp,
- "%s: %s matches!\n",
- lm->mod_name,
- nameptr);
- } else {
- if (CRASHDEBUG(2))
- fprintf(fp,
- "[%s] %s: %lx != extern'd value: %lx\n",
- lm->mod_name,
- nameptr, sp->value,
- spx->value);
- }
- break;
- }
- }
- if (!found) {
- if (CRASHDEBUG(2))
- fprintf(fp, "append ext %s (%lx)\n",
- spx->name, spx->value);
- /* append it here... */
- namespace_ctl(NAMESPACE_INSTALL,
- &lm->mod_load_namespace,
- lm->mod_load_symend, spx->name);
- lm->mod_load_symend->value = spx->value;
- lm->mod_load_symend->type = spx->type;
- lm->mod_load_symend->flags |= MODULE_SYMBOL;
- lm->mod_load_symend++;
- lm->mod_load_symcnt++;
- }
- }
- /*
- * Append helpful pseudo symbols about found out sections.
- * Use 'S' as its type which is never seen in existing symbols.
- */
- for (i = 0; (pc->curcmd_flags & MOD_SECTIONS) &&
- (i < lm->mod_sections); i++) {
- if (!(lm->mod_section_data[i].flags & SEC_FOUND))
- continue;
- /* Section start */
- lm->mod_load_symend->value = lm->mod_base +
- lm->mod_section_data[i].offset;
- lm->mod_load_symend->type = 'S';
- lm->mod_load_symend->flags |= MODULE_SYMBOL;
- sprintf(name, "_MODULE_SECTION_START [%s]",
- lm->mod_section_data[i].name);
- namespace_ctl(NAMESPACE_INSTALL, &lm->mod_load_namespace,
- lm->mod_load_symend, name);
- lm->mod_load_symend++;
- lm->mod_load_symcnt++;
- /* Section end */
- lm->mod_load_symend->value = lm->mod_base +
- lm->mod_section_data[i].offset +
- lm->mod_section_data[i].size;
- lm->mod_load_symend->type = 'S';
- lm->mod_load_symend->flags |= MODULE_SYMBOL;
- sprintf(name, "_MODULE_SECTION_END [%s]",
- lm->mod_section_data[i].name);
- namespace_ctl(NAMESPACE_INSTALL, &lm->mod_load_namespace,
- lm->mod_load_symend, name);
- lm->mod_load_symend++;
- lm->mod_load_symcnt++;
- }
- namespace_ctl(NAMESPACE_COMPLETE, &lm->mod_load_namespace,
- lm->mod_load_symtable, lm->mod_load_symend);
- qsort(lm->mod_load_symtable, lm->mod_load_symcnt, sizeof(struct syment),
- compare_syms);
- lm->mod_load_symend--;
- if (!MODULE_END(lm->mod_load_symend) &&
- !IN_MODULE_PERCPU(lm->mod_load_symend->value, lm))
- error(INFO, "%s: last symbol: %s is not _MODULE_END_%s?\n",
- lm->mod_name, lm->mod_load_symend->name, lm->mod_name);
- lm->mod_symtable = lm->mod_load_symtable;
- lm->mod_symend = lm->mod_load_symend;
- lm->mod_flags &= ~MOD_EXT_SYMS;
- lm->mod_flags |= MOD_LOAD_SYMS;
- st->flags |= LOAD_MODULE_SYMS;
- }
- /*
- * Delete a load module's symbol table. If base_addr is NULL, delete the
- * complete list of modules.
- */
- void
- delete_load_module(ulong base_addr)
- {
- int i;
- struct load_module *lm;
- struct gnu_request request, *req;
- req = &request;
- BZERO(req, sizeof(struct gnu_request));
- req->command = GNU_DELETE_SYMBOL_FILE;
- if (base_addr == ALL_MODULES) {
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_flags & MOD_LOAD_SYMS) {
- req->name = lm->mod_namelist;
- gdb_interface(req);
- }
- if (lm->mod_load_symtable) {
- free(lm->mod_load_symtable);
- namespace_ctl(NAMESPACE_FREE,
- &lm->mod_load_namespace, NULL, NULL);
- }
- if (lm->mod_flags & MOD_REMOTE)
- unlink_module(lm);
- lm->mod_symtable = lm->mod_ext_symtable;
- lm->mod_symend = lm->mod_ext_symend;
- lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH);
- lm->mod_flags |= MOD_EXT_SYMS;
- lm->mod_load_symtable = NULL;
- lm->mod_load_symend = NULL;
- lm->mod_namelist[0] = NULLCHAR;
- lm->mod_load_symcnt = lm->mod_symalloc = 0;
- lm->mod_text_start = lm->mod_data_start = 0;
- lm->mod_bss_start = lm->mod_rodata_start = 0;
- lm->mod_sections = 0;
- lm->mod_percpu_size = 0;
- if (lm->mod_section_data)
- free(lm->mod_section_data);
- lm->mod_section_data = (struct mod_section_data *)0;
- }
- st->flags &= ~LOAD_MODULE_SYMS;
- return;
- }
- st->flags &= ~LOAD_MODULE_SYMS; /* restored below (if any found) */
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (lm->mod_base == base_addr) {
- if (lm->mod_flags & MOD_LOAD_SYMS) {
- req->name = lm->mod_namelist;
- gdb_interface(req);
- }
- if (lm->mod_load_symtable) {
- free(lm->mod_load_symtable);
- namespace_ctl(NAMESPACE_FREE,
- &lm->mod_load_namespace, NULL, NULL);
- }
- if (lm->mod_flags & MOD_REMOTE)
- unlink_module(lm);
- lm->mod_symtable = lm->mod_ext_symtable;
- lm->mod_symend = lm->mod_ext_symend;
- lm->mod_flags &= ~(MOD_LOAD_SYMS|MOD_REMOTE|MOD_NOPATCH);
- lm->mod_flags |= MOD_EXT_SYMS;
- lm->mod_load_symtable = NULL;
- lm->mod_load_symend = NULL;
- lm->mod_namelist[0] = NULLCHAR;
- lm->mod_load_symcnt = lm->mod_symalloc = 0;
- lm->mod_text_start = lm->mod_data_start = 0;
- lm->mod_bss_start = lm->mod_rodata_start = 0;
- lm->mod_percpu_size = 0;
- lm->mod_sections = 0;
- if (lm->mod_section_data)
- free(lm->mod_section_data);
- lm->mod_section_data = (struct mod_section_data *)0;
- } else if (lm->mod_flags & MOD_LOAD_SYMS)
- st->flags |= LOAD_MODULE_SYMS;
- }
- }
- /*
- * Check whether a string is the name of a module. If requested, return
- * the base address of the module.
- */
- int
- is_module_name(char *s, ulong *addr, struct load_module **lmp)
- {
- int i;
- struct load_module *lm;
- if (NO_MODULES())
- return FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (STREQ(s, lm->mod_name)) {
- if (addr)
- *addr = lm->mod_base;
- if (lmp)
- *lmp = lm;
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * Check whether an value is the base address of a module. If requested,
- * return the module name.
- */
- int
- is_module_address(ulong check_addr, char *module_name)
- {
- int i;
- struct load_module *lm;
- if (NO_MODULES())
- return FALSE;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (check_addr == lm->mod_base) {
- if (module_name)
- strcpy(module_name, lm->mod_name);
- return TRUE;
- }
- }
- return FALSE;
- }
- /*
- * In a MOD_EXT_SYMBOLS module, find a rough estimate as to where the
- * .rodata section starts. The value will be used by is_kernel_text()
- * when symbols are not loaded.
- */
- static void
- find_mod_etext(struct load_module *lm)
- {
- ulong start, end;
- char *modbuf;
- ulong maxchunk, alloc;
- long offset = 0;
- start = roundup(lm->mod_size_of_struct, sizeof(long)) + lm->mod_base;
- end = lm->mod_base + lm->mod_size;
- maxchunk = MIN(end-start, KILOBYTES(32));
- modbuf = GETBUF(maxchunk);
- while (start < end) {
- alloc = MIN(maxchunk, end-start);
- readmem(start, KVADDR, modbuf, alloc,
- "module rodata search chunk", FAULT_ON_ERROR);
- if ((offset = rodata_search((ulong *)modbuf, alloc)) >= 0)
- break;
- start += alloc;
- }
- FREEBUF(modbuf);
- if (offset >= 0)
- lm->mod_etext_guess = start + offset;
- else
- lm->mod_etext_guess = end;
-
- }
- #define ASCII_WORD_COUNT (16/sizeof(ulong))
- static long
- rodata_search(ulong *buf, ulong size)
- {
- int i, acnt, words;
- long offset;
- ulong *wordptr;
-
- words = size/sizeof(ulong);
- wordptr = buf;
- for (i = acnt = 0, offset = -1; i < words; i++, wordptr++) {
- if (ascii_long(*wordptr)) {
- if (acnt++ == 0)
- offset = i * sizeof(ulong);
- } else {
- acnt = 0;
- offset = -1;
- }
- if (acnt == ASCII_WORD_COUNT)
- break;
- }
- return offset;
- }
- static int
- ascii_long(ulong word)
- {
- int i, cnt;
- unsigned char c;
- for (i = cnt = 0; i < sizeof(ulong); i++) {
- c = (unsigned char)((word >> (i*BITS_PER_BYTE)) & 0xff);
- if ((c >= ' ') && (c < 0x7f))
- cnt++;
- }
- return (cnt == sizeof(ulong));
- }
- /*
- * Symbol sorting routines adapted from binutils/nm.c
- */
- /* nm.c -- Describe symbol table of a rel file.
- Copyright 1991, 92, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
- 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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- static bfd *gnu_sort_bfd;
- static asymbol *gnu_sort_x;
- static asymbol *gnu_sort_y;
- #define valueof(x) ((x)->section->vma + (x)->value)
- static int
- non_numeric_forward(const void *P_x, const void *P_y)
- {
- asymbol *x, *y;
- const char *xn, *yn;
- x = bfd_minisymbol_to_symbol(gnu_sort_bfd, FALSE, P_x, gnu_sort_x);
- y = bfd_minisymbol_to_symbol(gnu_sort_bfd, FALSE, P_y, gnu_sort_y);
- if (x == NULL || y == NULL)
- error(FATAL, "bfd_minisymbol_to_symbol failed\n");
- xn = bfd_asymbol_name(x);
- yn = bfd_asymbol_name(y);
- return ((xn == NULL) ? ((yn == NULL) ? 0 : -1) :
- ((yn == NULL) ? 1 : strcmp (xn, yn)));
- }
- static int
- numeric_forward(const void *P_x, const void *P_y)
- {
- asymbol *x, *y;
- asection *xs, *ys;
- x = bfd_minisymbol_to_symbol(gnu_sort_bfd, FALSE, P_x, gnu_sort_x);
- y = bfd_minisymbol_to_symbol(gnu_sort_bfd, FALSE, P_y, gnu_sort_y);
- if (x == NULL || y == NULL)
- error(FATAL, "bfd_minisymbol_to_symbol failed\n");
- if (st->_stext_vmlinux == UNINITIALIZED) {
- if (STREQ(x->name, "_stext"))
- st->_stext_vmlinux = valueof(x);
- else if (STREQ(y->name, "_stext"))
- st->_stext_vmlinux = valueof(y);
- }
- if (kt->flags2 & KASLR_CHECK) {
- if (STREQ(x->name, "randomize_modules") ||
- STREQ(y->name, "randomize_modules")) {
- kt->flags2 &= ~KASLR_CHECK;
- kt->flags2 |= (RELOC_AUTO|KASLR);
- }
- }
- xs = bfd_get_section(x);
- ys = bfd_get_section(y);
- if (bfd_is_und_section(xs)) {
- if (!bfd_is_und_section(ys))
- return -1;
- }
- else if (bfd_is_und_section (ys))
- return 1;
- else if (valueof (x) != valueof (y))
- return valueof (x) < valueof (y) ? -1 : 1;
- return non_numeric_forward(P_x, P_y);
- }
- static void
- gnu_qsort(bfd *bfd,
- void *minisyms,
- long symcount,
- unsigned int size,
- asymbol *x,
- asymbol *y)
- {
- gnu_sort_bfd = bfd;
- gnu_sort_x = x;
- gnu_sort_y = y;
-
- qsort(minisyms, symcount, size, numeric_forward);
- }
- /*
- * Keep a stash of commonly-accessed text locations checked by the
- * back_trace code. The saved values unsigned 32-bit values.
- * The same routine is used to store and query, based upon whether
- * the passed-in value and valptr args are non-zero.
- */
- #define TEXT_CACHE (50)
- #define MAX_TEXT_CACHE (TEXT_CACHE*4)
- struct text_cache_entry {
- ulong vaddr;
- uint32_t value;
- };
- static struct text_cache {
- int index;
- int entries;
- ulong hits;
- ulong refs;
- struct text_cache_entry *cache;
- } text_cache = { 0 };
- /*
- * Cache the contents of 32-bit text addresses. If "value" is set, the purpose
- * is to cache it. If "valptr" is set, a query is being made for the text
- * address.
- */
- int
- text_value_cache(ulong vaddr, uint32_t value, uint32_t *valptr)
- {
- int i;
- struct text_cache *tc;
- if (!is_kernel_text(vaddr))
- return FALSE;
- tc = &text_cache;
- if (!tc->cache) {
- if (!(tc->cache = (struct text_cache_entry *)
- malloc(sizeof(struct text_cache_entry) * TEXT_CACHE)))
- return FALSE;
- BZERO(tc->cache, sizeof(struct text_cache_entry) * TEXT_CACHE);
- tc->index = 0;
- tc->entries = TEXT_CACHE;
- }
- if (value) {
- for (i = 0; i < tc->entries; i++) {
- if (tc->cache[i].vaddr == vaddr)
- return TRUE;
- }
- i = tc->index;
- tc->cache[i].vaddr = vaddr;
- tc->cache[i].value = value;
- tc->index++;
- if (tc->index == MAX_TEXT_CACHE) {
- tc->index = 0;
- } else if (tc->index == tc->entries) {
- struct text_cache_entry *old_cache;
- old_cache = tc->cache;
- if ((tc->cache = (struct text_cache_entry *)
- realloc(old_cache, sizeof(struct text_cache_entry) *
- (TEXT_CACHE+tc->entries)))) {
- BZERO(&tc->cache[tc->index],
- sizeof(struct text_cache_entry) *
- TEXT_CACHE);
- tc->entries += TEXT_CACHE;
- } else {
- tc->cache = old_cache;
- tc->index = 0;
- }
- }
- return TRUE;
- }
- if (valptr) {
- tc->refs++;
- for (i = 0; i < tc->entries; i++) {
- if (!tc->cache[i].vaddr)
- return FALSE;
- if (tc->cache[i].vaddr == vaddr) {
- *valptr = tc->cache[i].value;
- tc->hits++;
- return TRUE;
- }
- }
- }
- return FALSE;
- }
- /*
- * The gdb disassembler reads text memory byte-by-byte, so this routine
- * acts as a front-end to the 32-bit (4-byte) text storage.
- */
- int
- text_value_cache_byte(ulong vaddr, unsigned char *valptr)
- {
- int i;
- int shift;
- struct text_cache *tc;
- ulong valtmp;
- if (!is_kernel_text(vaddr))
- return FALSE;
- tc = &text_cache;
- tc->refs++;
- for (i = 0; i < tc->entries; i++) {
- if (!tc->cache[i].vaddr)
- return FALSE;
- if ((vaddr >= tc->cache[i].vaddr) &&
- (vaddr < (tc->cache[i].vaddr+SIZEOF_32BIT))) {
- valtmp = tc->cache[i].value;
- shift = (vaddr - tc->cache[i].vaddr) * 8;
- valtmp >>= shift;
- *valptr = valtmp & 0xff;
- tc->hits++;
- return TRUE;
- }
- }
- return FALSE;
- }
- void
- dump_text_value_cache(int verbose)
- {
- int i;
- struct syment *sp;
- ulong offset;
- struct text_cache *tc;
- tc = &text_cache;
- if (!verbose) {
- if (!tc->refs || !tc->cache)
- return;
- fprintf(stderr, " text hit rate: %2ld%% (%ld of %ld)\n",
- (tc->hits * 100)/tc->refs,
- (ulong)tc->hits, (ulong)tc->refs);
- return;
- }
-
- for (i = 0; tc->cache && (i < tc->entries); i++) {
- if (!tc->cache[i].vaddr)
- break;
- fprintf(fp, "[%2d]: %lx %08x ", i, tc->cache[i].vaddr,
- tc->cache[i].value);
- if ((sp = value_search(tc->cache[i].vaddr, &offset))) {
- fprintf(fp, "(%s+", sp->name);
- switch (pc->output_radix)
- {
- case 10:
- fprintf(fp, "%ld)", offset);
- break;
- case 16:
- fprintf(fp, "%lx)", offset);
- break;
- }
- }
- fprintf(fp, "\n");
- }
- fprintf(fp,
- "text_cache entries: %d index: %d hit rate: %ld%% (%ld of %ld)\n",
- tc->entries, tc->index,
- (tc->hits * 100)/(tc->refs ? tc->refs : 1),
- tc->hits, tc->refs);
- }
- void
- clear_text_value_cache(void)
- {
- int i;
- struct text_cache *tc;
- tc = &text_cache;
- tc->index = 0;
- for (i = 0; tc->cache && (i < tc->entries); i++) {
- tc->cache[i].vaddr = 0;
- tc->cache[i].value = 0;
- }
- }
- /*
- * If a System.map file or a debug kernel was specified, the name hash
- * has been filled -- so sync up gdb's notion of symbol values with
- * the local values, taking dups into account. Given that gdb's
- * minimal_symbol dump is sorted by value, shortcut the get_syment_array()
- * call if the sp after the last one found is associated with the
- * new one.
- */
- #define last_sp addr2
- int
- patch_kernel_symbol(struct gnu_request *req)
- {
- int i, c;
- struct syment *sp_array[1000], *sp;
- if (req->name == PATCH_KERNEL_SYMBOLS_START) {
- if (kt->flags & RELOC_FORCE)
- error(WARNING,
- "\nkernel relocated [%ldMB]: patching %ld gdb minimal_symbol values\n",
- kt->relocate >> 20, st->symcnt);
- if (kt->flags2 & RELOC_AUTO)
- error(WARNING,
- "\nkernel relocated [%ldMB]: patching %ld gdb minimal_symbol values\n",
- (kt->relocate * -1) >> 20, st->symcnt);
- fprintf(fp, (pc->flags & SILENT) || !(pc->flags & TTY) ? "" :
- "\nplease wait... (patching %ld gdb minimal_symbol values) ",
- st->symcnt);
- fflush(fp);
- req->count = 0;
- req->length = 0;
- req->last_sp = 0;
- return TRUE;
- }
- if (req->name == PATCH_KERNEL_SYMBOLS_STOP) {
- fprintf(fp, (pc->flags & SILENT) || !(pc->flags & TTY) ? "" :
- "\r \r");
- st->flags |= GDB_SYMS_PATCHED;
- return TRUE;
- }
- if (!req->name || !req->addr)
- return FALSE;
- sp = (struct syment *)req->last_sp;
- sp += sp ? 1 : 0;
- if (sp && (sp->cnt == 1) && !(sp->flags & SYMBOL_NAME_USED) &&
- STREQ(sp->name, req->name)) {
- *((ulong *)req->addr) = sp->value;
- sp->flags |= SYMBOL_NAME_USED;
- req->last_sp = (ulong)sp;
- } else {
- switch (c = get_syment_array(req->name, sp_array, 1000))
- {
- case 0: req->last_sp = 0;
- return TRUE;
-
- case 1:
- *((ulong *)req->addr) = sp_array[0]->value;
- sp_array[0]->flags |= SYMBOL_NAME_USED;
- req->last_sp = (ulong)sp_array[0];
- break;
-
- default:
- for (i = 0; i < c; i++) {
- if (sp_array[i]->flags & SYMBOL_NAME_USED)
- continue;
- *((ulong *)req->addr) = sp_array[i]->value;
- sp_array[i]->flags |= SYMBOL_NAME_USED;
- req->last_sp = (ulong)sp_array[i];
- break;
- }
- break;
- }
- }
- return TRUE;
- }
- #undef last_sp
- /*
- * If the first offset/size is bogus, then use the second if it's OK.
- * But if both are bogus, then check whether we're debugging datatypes,
- * and act accordingly.
- */
- long
- OFFSET_option(long offset1, long offset2, char *func, char *file, int line,
- char *item1, char *item2)
- {
- char errmsg[BUFSIZE];
- if (offset1 >= 0)
- return offset1;
- if (offset2 >= 0)
- return offset2;
- if (pc->flags & DATADEBUG) {
- void *retaddr[NUMBER_STACKFRAMES] = { 0 };
- SAVE_RETURN_ADDRESS(retaddr);
- sprintf(errmsg,
- "invalid (optional) structure member offsets: %s or %s",
- item1, item2);
- datatype_error(retaddr, errmsg, func, file, line);
- }
- return -1;
- }
- long
- SIZE_option(long size1, long size2, char *func, char *file, int line,
- char *item1, char *item2)
- {
- char errmsg[BUFSIZE];
- if (size1 >= 0)
- return size1;
- if (size2 >= 0)
- return size2;
- if (pc->flags & DATADEBUG) {
- void *retaddr[NUMBER_STACKFRAMES] = { 0 };
- SAVE_RETURN_ADDRESS(retaddr);
- sprintf(errmsg, "invalid (optional) structure sizes: %s or %s",
- item1, item2);
- datatype_error(retaddr, errmsg, func, file, line);
- }
- return -1;
- }
- /*
- * Do the work of the former OFFSET() and SIZE() macros.
- *
- * For now verification that the offset is legitimate is only done
- * if the "--data_debug" command line option was used. There
- * could still be constructs like "OFFSET(x) >= 0" in the current
- * code, or in user extensions. Perhaps there should be an option
- * to turn it off instead?
- */
- long
- OFFSET_verify(long offset, char *func, char *file, int line, char *item)
- {
- char errmsg[BUFSIZE];
- if (!(pc->flags & DATADEBUG))
- return offset;
- if (offset < 0) {
- void *retaddr[NUMBER_STACKFRAMES] = { 0 };
- SAVE_RETURN_ADDRESS(retaddr);
- sprintf(errmsg, "invalid structure member offset: %s",
- item);
- datatype_error(retaddr, errmsg, func, file, line);
- }
- return offset;
- }
- long
- SIZE_verify(long size, char *func, char *file, int line, char *item)
- {
- char errmsg[BUFSIZE];
- if (!(pc->flags & DATADEBUG))
- return size;
- if (size < 0) {
- void *retaddr[NUMBER_STACKFRAMES] = { 0 };
- SAVE_RETURN_ADDRESS(retaddr);
- sprintf(errmsg, "invalid structure size: %s", item);
- datatype_error(retaddr, errmsg, func, file, line);
- }
- return size;
- }
- /*
- * Perform the common datatype error handling.
- */
- static void
- datatype_error(void **retaddr, char *errmsg, char *func, char *file, int line)
- {
- char buf[BUFSIZE];
- int fd;
- fprintf(stderr, "\n%s: %s\n", pc->curcmd, errmsg);
- fprintf(stderr, "%s FILE: %s LINE: %d FUNCTION: %s()\n\n",
- space(strlen(pc->curcmd)), file, line, func);
- fflush(stderr);
- dump_trace(retaddr);
- if (pc->flags & TTY) {
- if ((fd = open("/dev/tty", O_RDONLY)) >= 0) {
- tcsetattr(fd, TCSANOW, &pc->termios_orig);
- close(fd);
- }
- }
- if (pc->flags & DROP_CORE)
- drop_core("DROP_CORE flag set: forcing a segmentation fault\n");
-
- if (CRASHDEBUG(1))
- gdb_readnow_warning();
- if (pc->flags & RUNTIME) {
- sprintf(buf, "%s\n%s FILE: %s LINE: %d FUNCTION: %s()\n",
- errmsg, space(strlen(pc->curcmd)), file, line, func);
- error(FATAL, "%s\n", buf);
- }
- exit(1);
- }
- /*
- * Dump a trace leading to the improper datatype usage.
- */
- void
- dump_trace(void **retaddr)
- {
- int i, c;
- char *thisfile;
- char *arglist[MAXARGS];
- char buf[BUFSIZE];
- FILE *pipe;
- ulong vaddr, size, lookfor;
- ulong last_vaddr, last_size;
- char symbol[BUFSIZE];
- const char *nm_call;
- fflush(fp);
- fflush(stdout);
- fflush(pc->stdpipe);
- thisfile = get_thisfile();
- fprintf(stderr, "[%s] error trace: ", thisfile);
- for (i = (NUMBER_STACKFRAMES-1); i >= 0; i--) {
- if (retaddr[i])
- fprintf(stderr, "%s%lx%s",
- i == 3 ? "" : "=> ",
- (ulong)retaddr[i],
- i == 0 ? "\n" : " ");
- }
- fflush(stderr);
- if (!file_exists("/usr/bin/nm", NULL)) {
- fprintf(stderr, "crash: /usr/bin/nm: no such file\n");
- return;
- }
- if (is_binary_stripped(thisfile))
- nm_call = "/usr/bin/nm -DSBn %s";
- else
- nm_call = "/usr/bin/nm -BSn %s";
- last_size = 0;
- for (i = 0; i < NUMBER_STACKFRAMES; i++) {
- if (!(lookfor = (ulong)retaddr[i]))
- continue;
- sprintf(buf, nm_call, thisfile);
- if (!(pipe = popen(buf, "r"))) {
- perror("pipe");
- break;
- }
- last_vaddr = 0;
- BZERO(symbol, BUFSIZE);
- while (fgets(buf, BUFSIZE, pipe)) {
- c = parse_line(strip_linefeeds(buf), arglist);
- if (c != 4)
- continue;
- vaddr = htol(arglist[0], FAULT_ON_ERROR, NULL);
- size = htol(arglist[1], FAULT_ON_ERROR, NULL);
- if (vaddr > lookfor) {
- if ((lookfor - last_vaddr) > last_size)
- fprintf(stderr, "%s %lx: (undetermined)\n",
- i == 0 ? "\n" : "",
- lookfor);
- else
- fprintf(stderr, "%s %lx: %s+%ld\n",
- i == 0 ? "\n" : "",
- lookfor, symbol,
- lookfor-last_vaddr);
- break;
- }
- strcpy(symbol, arglist[3]);
- last_vaddr = vaddr;
- last_size = size;
- }
- pclose(pipe);
- }
- fprintf(stderr, "\n");
- }
- /*
- * Try best to determine which executable this is.
- */
- static char *
- get_thisfile(void)
- {
- char *buf1;
- char buf2[BUFSIZE];
- char *tok, *path;
- if (pc->program_path[0] == '.' ||
- pc->program_path[0] == '/')
- return pc->program_path;
- if ((path = getenv("PATH"))) {
- strcpy(buf2, path);
- } else
- return pc->program_path;
- buf1 = GETBUF(BUFSIZE);
- tok = strtok(buf2, ":");
- while (tok) {
- sprintf(buf1, "%s/%s", tok, pc->program_name);
- if (file_exists(buf1, NULL) && is_elf_file(buf1)) {
- return buf1;
- }
- tok = strtok(NULL, ":");
- }
- return pc->program_path;
- }
- /*
- * Check whether an address fits into any existing init_module() functions,
- * and if so, return the load_module.
- */
- struct load_module *
- init_module_function(ulong vaddr)
- {
- int i;
- struct load_module *lm;
- if (((kt->flags & (KMOD_V1|KMOD_V2)) == KMOD_V1) ||
- INVALID_MEMBER(module_init_text_size) ||
- INVALID_MEMBER(module_module_init))
- return NULL;
- for (i = 0; i < st->mods_installed; i++) {
- lm = &st->load_modules[i];
- if (!lm->mod_init_module_ptr || !lm->mod_init_text_size)
- continue;
- if ((vaddr >= lm->mod_init_module_ptr) &&
- (vaddr < (lm->mod_init_module_ptr+lm->mod_init_text_size))
- && accessible(vaddr))
- return lm;
- }
- return NULL;
- }
|