dbgrcomm.c 214 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757
  1. /*++
  2. Copyright (c) 2012 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. dbgrcomm.c
  5. Abstract:
  6. This module implements much of the debugger protocol communication for the
  7. debugger client.
  8. Author:
  9. Evan Green 3-Jul-2012
  10. Environment:
  11. Debugger client
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include "dbgrtl.h"
  17. #include <minoca/debug/spproto.h>
  18. #include <minoca/lib/im.h>
  19. #include <minoca/debug/dbgext.h>
  20. #include "disasm.h"
  21. #include "dbgapi.h"
  22. #include "dbgrprof.h"
  23. #include "console.h"
  24. #include "symbols.h"
  25. #include "dbgrcomm.h"
  26. #include "dbgsym.h"
  27. #include "extsp.h"
  28. #include "remsrv.h"
  29. #include <assert.h>
  30. #include <errno.h>
  31. #include <fcntl.h>
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/stat.h>
  36. #include <time.h>
  37. //
  38. // ---------------------------------------------------------------- Definitions
  39. //
  40. #define DEFAULT_DISASSEMBLED_INSTRUCTIONS 10
  41. #define DEFAULT_RECURSION_DEPTH 3
  42. #define BYTES_PER_INSTRUCTION 15
  43. #define DEFAULT_MEMORY_PRINT_ROWS 10
  44. #define DEFAULT_DUMP_POINTERS_ROWS 100
  45. //
  46. // ------------------------------------------------------ Data Type Definitions
  47. //
  48. //
  49. // ----------------------------------------------- Internal Function Prototypes
  50. //
  51. INT
  52. DbgrpSetBreakpointAtAddress (
  53. PDEBUGGER_CONTEXT Context,
  54. ULONGLONG Address,
  55. PULONG OriginalValue
  56. );
  57. INT
  58. DbgrpClearBreakpointAtAddress (
  59. PDEBUGGER_CONTEXT Context,
  60. ULONGLONG Address,
  61. ULONG OriginalValue
  62. );
  63. ULONG
  64. DbgrpHandleBreakpoints (
  65. PDEBUGGER_CONTEXT Context
  66. );
  67. INT
  68. DbgrpAdjustInstructionPointerForBreakpoint (
  69. PDEBUGGER_CONTEXT Context,
  70. ULONG OriginalValue
  71. );
  72. INT
  73. DbgrpProcessBreakNotification (
  74. PDEBUGGER_CONTEXT Context
  75. );
  76. INT
  77. DbgrpRangeStep (
  78. PDEBUGGER_CONTEXT Context,
  79. PRANGE_STEP RangeStep
  80. );
  81. INT
  82. DbgrpValidateLoadedModules (
  83. PDEBUGGER_CONTEXT Context,
  84. ULONG ModuleCount,
  85. ULONGLONG Signature,
  86. BOOL ForceReload
  87. );
  88. VOID
  89. DbgrpUnloadModule (
  90. PDEBUGGER_CONTEXT Context,
  91. PDEBUGGER_MODULE Module,
  92. BOOL Verbose
  93. );
  94. VOID
  95. DbgrpUnloadAllModules (
  96. PDEBUGGER_CONTEXT Context,
  97. BOOL Verbose
  98. );
  99. INT
  100. DbgrpPrintDisassembly (
  101. PDEBUGGER_CONTEXT Context,
  102. PBYTE InstructionStream,
  103. ULONGLONG InstructionPointer,
  104. ULONG InstructionCount,
  105. PULONG BytesDecoded
  106. );
  107. PDATA_SYMBOL
  108. DbgpGetLocal (
  109. PFUNCTION_SYMBOL Function,
  110. PSTR LocalName,
  111. ULONGLONG ExecutionAddress
  112. );
  113. PSTR
  114. DbgrpCreateFullPath (
  115. PSOURCE_FILE_SYMBOL Source
  116. );
  117. INT
  118. DbgrpPrintMemory (
  119. PDEBUGGER_CONTEXT Context,
  120. ULONGLONG Address,
  121. BOOL VirtualAddress,
  122. ULONG TypeSize,
  123. ULONG Columns,
  124. ULONG TotalValues,
  125. BOOL PrintCharacters
  126. );
  127. VOID
  128. DbgrpProcessShutdown (
  129. PDEBUGGER_CONTEXT Context
  130. );
  131. PDEBUGGER_MODULE
  132. DbgpLoadModule (
  133. PDEBUGGER_CONTEXT Context,
  134. PSTR BinaryName,
  135. PSTR FriendlyName,
  136. ULONGLONG BaseAddress,
  137. ULONGLONG Size,
  138. ULONGLONG LowestAddress,
  139. ULONGLONG Timestamp,
  140. ULONG Process
  141. );
  142. INT
  143. DbgrpResolveDumpType (
  144. PDEBUGGER_CONTEXT Context,
  145. PTYPE_SYMBOL *Type,
  146. PVOID *Data,
  147. PUINTN DataSize,
  148. PULONGLONG Address
  149. );
  150. INT
  151. DbgrpSetFrame (
  152. PDEBUGGER_CONTEXT Context,
  153. ULONG FrameNumber
  154. );
  155. INT
  156. DbgrpEnableBreakPoint (
  157. PDEBUGGER_CONTEXT Context,
  158. LONG BreakPointIndex,
  159. BOOL Enable
  160. );
  161. VOID
  162. DbgrpDestroySourcePath (
  163. PDEBUGGER_SOURCE_PATH SourcePath
  164. );
  165. INT
  166. DbgrpLoadFile (
  167. PSTR Path,
  168. PVOID *Contents,
  169. PULONGLONG Size
  170. );
  171. //
  172. // -------------------------------------------------------------------- Globals
  173. //
  174. //
  175. // Store a pointer to the global context, which is needed for requesting
  176. // break-ins.
  177. //
  178. extern PDEBUGGER_CONTEXT DbgConsoleContext;
  179. //
  180. // ------------------------------------------------------------------ Functions
  181. //
  182. INT
  183. DbgrInitialize (
  184. PDEBUGGER_CONTEXT Context,
  185. DEBUG_CONNECTION_TYPE ConnectionType
  186. )
  187. /*++
  188. Routine Description:
  189. This routine initializes data structures for common debugger functionality.
  190. Arguments:
  191. Context - Supplies a pointer to the application context.
  192. ConnectionType - Supplies the type of debug connection to set the debugger
  193. up in.
  194. Return Value:
  195. 0 on success.
  196. Returns an error number on failure.
  197. --*/
  198. {
  199. INT Status;
  200. Status = EINVAL;
  201. Context->Flags |= DEBUGGER_FLAG_SOURCE_LINE_STEPPING;
  202. //
  203. // Initialize the loaded modules list.
  204. //
  205. if (Context->ModuleList.ModuleCount == 0) {
  206. Context->ModuleList.Signature = 0;
  207. INITIALIZE_LIST_HEAD(&(Context->ModuleList.ModulesHead));
  208. }
  209. if (Context->BreakpointList.Next == NULL) {
  210. INITIALIZE_LIST_HEAD(&(Context->BreakpointList));
  211. }
  212. //
  213. // Initialize the profiler.
  214. //
  215. Status = DbgrProfilerInitialize(Context);
  216. if (Status != 0) {
  217. goto InitializeEnd;
  218. }
  219. Status = DbgInitialize(Context, ConnectionType);
  220. if (Status != 0) {
  221. goto InitializeEnd;
  222. }
  223. Status = 0;
  224. InitializeEnd:
  225. return Status;
  226. }
  227. VOID
  228. DbgrDestroy (
  229. PDEBUGGER_CONTEXT Context,
  230. DEBUG_CONNECTION_TYPE ConnectionType
  231. )
  232. /*++
  233. Routine Description:
  234. This routine destroys any data structures used for common debugger
  235. functionality.
  236. Arguments:
  237. Context - Supplies a pointer to the application context.
  238. ConnectionType - Supplies the type of debug connection the debugger was set
  239. up in.
  240. Return Value:
  241. None.
  242. --*/
  243. {
  244. //
  245. // Destroy the profiler structures.
  246. //
  247. DbgrProfilerDestroy(Context);
  248. DbgDestroy(Context, ConnectionType);
  249. return;
  250. }
  251. INT
  252. DbgrConnect (
  253. PDEBUGGER_CONTEXT Context
  254. )
  255. /*++
  256. Routine Description:
  257. This routine establishes a link with the target debuggee. It is assumed that
  258. the underlying communication layer has already been established (COM ports
  259. have been opened and initialized, etc).
  260. Arguments:
  261. Context - Supplies a pointer to the application context.
  262. Return Value:
  263. 0 on success.
  264. Returns an error code on failure.
  265. --*/
  266. {
  267. PSTR Architecture;
  268. PSTR BuildDebugString;
  269. PSTR BuildString;
  270. CHAR BuildTime[50];
  271. PCONNECTION_RESPONSE ConnectionResponse;
  272. BOOL InitialBreak;
  273. PSTR ProductName;
  274. INT Result;
  275. ULONG Size;
  276. time_t Time;
  277. struct tm *TimeStructure;
  278. InitialBreak = FALSE;
  279. if ((Context->Flags & DEBUGGER_FLAG_INITIAL_BREAK) != 0) {
  280. InitialBreak = TRUE;
  281. }
  282. //
  283. // Connect to the target.
  284. //
  285. DbgOut("Waiting to connect...\n");
  286. Result = DbgKdConnect(Context, InitialBreak, &ConnectionResponse, &Size);
  287. if (Result != 0) {
  288. DbgOut("Error: Unable to connect.\n");
  289. return Result;
  290. }
  291. //
  292. // A connection was successfully established. Print the banner and
  293. // return.
  294. //
  295. Context->MachineType = ConnectionResponse->Machine;
  296. switch (ConnectionResponse->Machine) {
  297. case MACHINE_TYPE_X86:
  298. Architecture = "x86";
  299. break;
  300. case MACHINE_TYPE_ARM:
  301. Architecture = "ARM";
  302. break;
  303. default:
  304. Architecture = "Unknown";
  305. break;
  306. }
  307. ProductName = "Unknown Target";
  308. if ((ConnectionResponse->ProductNameOffset != 0) &&
  309. (ConnectionResponse->ProductNameOffset < Size)) {
  310. ProductName = (PSTR)ConnectionResponse +
  311. ConnectionResponse->ProductNameOffset;
  312. }
  313. BuildString = "";
  314. if ((ConnectionResponse->BuildStringOffset != 0) &&
  315. (ConnectionResponse->BuildStringOffset < Size)) {
  316. BuildString = (PSTR)ConnectionResponse +
  317. ConnectionResponse->BuildStringOffset;
  318. }
  319. BuildDebugString = RtlGetBuildDebugLevelString(
  320. ConnectionResponse->SystemBuildDebugLevel);
  321. DbgOut("Connected to %s on %s\nSystem Version %d.%d.%d.%I64d %s %s %s\n",
  322. ProductName,
  323. Architecture,
  324. ConnectionResponse->SystemMajorVersion,
  325. ConnectionResponse->SystemMinorVersion,
  326. ConnectionResponse->SystemRevision,
  327. ConnectionResponse->SystemSerialVersion,
  328. RtlGetReleaseLevelString(ConnectionResponse->SystemReleaseLevel),
  329. BuildDebugString,
  330. BuildString);
  331. Time = ConnectionResponse->SystemBuildTime + SYSTEM_TIME_TO_EPOCH_DELTA;
  332. TimeStructure = localtime(&Time);
  333. strftime(BuildTime,
  334. sizeof(BuildTime),
  335. "%a %b %d, %Y %I:%M %p",
  336. TimeStructure);
  337. DbgOut("Built on %s.\n", BuildTime);
  338. free(ConnectionResponse);
  339. return 0;
  340. }
  341. INT
  342. DbgrQuit (
  343. PDEBUGGER_CONTEXT Context,
  344. PSTR *Arguments,
  345. ULONG ArgumentCount
  346. )
  347. /*++
  348. Routine Description:
  349. This routine exits the local debugger.
  350. Arguments:
  351. Context - Supplies a pointer to the application context.
  352. Arguments - Supplies an array of strings containing the arguments. The
  353. first argument is the command itself.
  354. ArgumentCount - Supplies the count of arguments. This is always at least
  355. one.
  356. Return Value:
  357. 0 on success.
  358. Returns an error code on failure.
  359. --*/
  360. {
  361. DbgOut("\n*** Exiting ***\n");
  362. Context->Flags |= DEBUGGER_FLAG_EXITING;
  363. return 0;
  364. }
  365. INT
  366. DbgrGo (
  367. PDEBUGGER_CONTEXT Context,
  368. PSTR *Arguments,
  369. ULONG ArgumentCount
  370. )
  371. /*++
  372. Routine Description:
  373. This routine interprets the "go" command from the user.
  374. Arguments:
  375. Context - Supplies a pointer to the application context.
  376. Arguments - Supplies an array of strings containing the arguments. The
  377. first argument is the command itself.
  378. ArgumentCount - Supplies the count of arguments. This is always at least
  379. one.
  380. Return Value:
  381. 0 on success.
  382. Returns an error code on failure.
  383. --*/
  384. {
  385. ULONGLONG Evaluation;
  386. PSTR GoUntilAddress;
  387. INT Result;
  388. GoUntilAddress = NULL;
  389. if (ArgumentCount > 1) {
  390. GoUntilAddress = Arguments[1];
  391. }
  392. //
  393. // If no argument was specified, send the unconditional go.
  394. //
  395. if (GoUntilAddress == NULL) {
  396. Result = DbgrContinue(Context, FALSE, 0);
  397. return Result;
  398. }
  399. //
  400. // Evaluate the argument. If it fails, print a message, and do not send the
  401. // command.
  402. //
  403. Result = DbgEvaluate(Context, GoUntilAddress, &Evaluation);
  404. if (Result != 0) {
  405. DbgOut("Error: Unable to evaluate \"%s\".\n", GoUntilAddress);
  406. return Result;
  407. }
  408. //
  409. // Send the command with a one-time breakpoint.
  410. //
  411. Result = DbgrContinue(Context, TRUE, Evaluation);
  412. return Result;
  413. }
  414. INT
  415. DbgrSingleStep (
  416. PDEBUGGER_CONTEXT Context
  417. )
  418. /*++
  419. Routine Description:
  420. This routine steps the target by a single instruction.
  421. Arguments:
  422. Context - Supplies a pointer to the application context.
  423. Return Value:
  424. 0 on success.
  425. Returns an error code on failure.
  426. --*/
  427. {
  428. INT Result;
  429. ULONG SignalToDeliver;
  430. SignalToDeliver = DbgGetSignalToDeliver(Context);
  431. Result = DbgSingleStep(Context, SignalToDeliver);
  432. return Result;
  433. }
  434. INT
  435. DbgrGetSetRegisters (
  436. PDEBUGGER_CONTEXT Context,
  437. PSTR *Arguments,
  438. ULONG ArgumentCount
  439. )
  440. /*++
  441. Routine Description:
  442. This routine prints or modifies the target machine's registers.
  443. Arguments:
  444. Context - Supplies a pointer to the application context.
  445. Arguments - Supplies an array of strings containing the arguments. The
  446. first argument is the command itself.
  447. ArgumentCount - Supplies the count of arguments. This is always at least
  448. one.
  449. Return Value:
  450. 0 on success.
  451. Returns an error code on failure.
  452. --*/
  453. {
  454. PARM_GENERAL_REGISTERS ArmRegisters;
  455. ULONG Eflags;
  456. ULONG Iopl;
  457. ULONGLONG NewValue;
  458. ULONG Psr;
  459. PULONG Register;
  460. PSTR RegisterString;
  461. INT Result;
  462. PUSHORT ShortRegister;
  463. PSTR ValueString;
  464. PX86_GENERAL_REGISTERS X86Registers;
  465. Register = NULL;
  466. RegisterString = NULL;
  467. Result = 0;
  468. ShortRegister = NULL;
  469. ValueString = NULL;
  470. if (ArgumentCount >= 2) {
  471. RegisterString = Arguments[1];
  472. if (ArgumentCount >= 3) {
  473. ValueString = Arguments[2];
  474. }
  475. }
  476. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  477. ArmRegisters = &(Context->CurrentEvent.BreakNotification.Registers.Arm);
  478. X86Registers = &(Context->CurrentEvent.BreakNotification.Registers.X86);
  479. if (Context->CurrentFrame != 0) {
  480. ArmRegisters = &(Context->FrameRegisters.Arm);
  481. X86Registers = &(Context->FrameRegisters.X86);
  482. }
  483. //
  484. // If the first parameter is not NULL, find the register the user is
  485. // talking about.
  486. //
  487. if (RegisterString != NULL) {
  488. switch (Context->MachineType) {
  489. //
  490. // Get x86 registers.
  491. //
  492. case MACHINE_TYPE_X86:
  493. if (strcasecmp(RegisterString, "eax") == 0) {
  494. Register = (PVOID)&(X86Registers->Eax);
  495. } else if (strcasecmp(RegisterString, "ebx") == 0) {
  496. Register = (PVOID)&(X86Registers->Ebx);
  497. } else if (strcasecmp(RegisterString, "ecx") == 0) {
  498. Register = (PVOID)&(X86Registers->Ecx);
  499. } else if (strcasecmp(RegisterString, "edx") == 0) {
  500. Register = (PVOID)&(X86Registers->Edx);
  501. } else if (strcasecmp(RegisterString, "esi") == 0) {
  502. Register = (PVOID)&(X86Registers->Esi);
  503. } else if (strcasecmp(RegisterString, "edi") == 0) {
  504. Register = (PVOID)&(X86Registers->Edi);
  505. } else if (strcasecmp(RegisterString, "esp") == 0) {
  506. Register = (PVOID)&(X86Registers->Esp);
  507. } else if (strcasecmp(RegisterString, "ebp") == 0) {
  508. Register = (PVOID)&(X86Registers->Ebp);
  509. } else if (strcasecmp(RegisterString, "eip") == 0) {
  510. Register = (PVOID)&(X86Registers->Eip);
  511. } else if (strcasecmp(RegisterString, "eflags") == 0) {
  512. Register = (PVOID)&(X86Registers->Eflags);
  513. } else if (strcasecmp(RegisterString, "cs") == 0) {
  514. ShortRegister = &(X86Registers->Cs);
  515. } else if (strcasecmp(RegisterString, "ds") == 0) {
  516. ShortRegister = &(X86Registers->Ds);
  517. } else if (strcasecmp(RegisterString, "es") == 0) {
  518. ShortRegister = &(X86Registers->Es);
  519. } else if (strcasecmp(RegisterString, "fs") == 0) {
  520. ShortRegister = &(X86Registers->Fs);
  521. } else if (strcasecmp(RegisterString, "gs") == 0) {
  522. ShortRegister = &(X86Registers->Gs);
  523. } else if (strcasecmp(RegisterString, "ss") == 0) {
  524. ShortRegister = &(X86Registers->Ss);
  525. } else {
  526. DbgOut("Error: Invalid register \"%s\".\n", RegisterString);
  527. goto GetSetRegistersEnd;
  528. }
  529. break;
  530. //
  531. // Get ARM registers.
  532. //
  533. case MACHINE_TYPE_ARM:
  534. if (strcasecmp(RegisterString, "r0") == 0) {
  535. Register = &(ArmRegisters->R0);
  536. } else if (strcasecmp(RegisterString, "r1") == 0) {
  537. Register = &(ArmRegisters->R1);
  538. } else if (strcasecmp(RegisterString, "r2") == 0) {
  539. Register = &(ArmRegisters->R2);
  540. } else if (strcasecmp(RegisterString, "r3") == 0) {
  541. Register = &(ArmRegisters->R3);
  542. } else if (strcasecmp(RegisterString, "r4") == 0) {
  543. Register = &(ArmRegisters->R4);
  544. } else if (strcasecmp(RegisterString, "r5") == 0) {
  545. Register = &(ArmRegisters->R5);
  546. } else if (strcasecmp(RegisterString, "r6") == 0) {
  547. Register = &(ArmRegisters->R6);
  548. } else if (strcasecmp(RegisterString, "r7") == 0) {
  549. Register = &(ArmRegisters->R7);
  550. } else if (strcasecmp(RegisterString, "r8") == 0) {
  551. Register = &(ArmRegisters->R8);
  552. } else if (strcasecmp(RegisterString, "r9") == 0) {
  553. Register = &(ArmRegisters->R9);
  554. } else if ((strcasecmp(RegisterString, "r10") == 0) ||
  555. (strcasecmp(RegisterString, "sl") == 0)) {
  556. Register = &(ArmRegisters->R10);
  557. } else if ((strcasecmp(RegisterString, "r11") == 0) ||
  558. (strcasecmp(RegisterString, "fp") == 0)) {
  559. Register = &(ArmRegisters->R11Fp);
  560. } else if ((strcasecmp(RegisterString, "r12") == 0) ||
  561. (strcasecmp(RegisterString, "ip") == 0)) {
  562. Register = &(ArmRegisters->R12Ip);
  563. } else if ((strcasecmp(RegisterString, "r13") == 0) ||
  564. (strcasecmp(RegisterString, "sp") == 0)) {
  565. Register = &(ArmRegisters->R13Sp);
  566. } else if ((strcasecmp(RegisterString, "r14") == 0) ||
  567. (strcasecmp(RegisterString, "lr") == 0)) {
  568. Register = &(ArmRegisters->R14Lr);
  569. } else if ((strcasecmp(RegisterString, "r15") == 0) ||
  570. (strcasecmp(RegisterString, "pc") == 0)) {
  571. Register = &(ArmRegisters->R15Pc);
  572. } else if (strcasecmp(RegisterString, "cpsr") == 0) {
  573. Register = &(ArmRegisters->Cpsr);
  574. } else {
  575. DbgOut("Error: Invalid register \"%s\".\n", RegisterString);
  576. goto GetSetRegistersEnd;
  577. }
  578. break;
  579. //
  580. // Unknown machine type.
  581. //
  582. default:
  583. DbgOut("Error: Unknown machine type %d.\n", Context->MachineType);
  584. goto GetSetRegistersEnd;
  585. }
  586. //
  587. // If no other parameter was specified, print out the value of the
  588. // specified register.
  589. //
  590. if (ValueString == NULL) {
  591. DbgOut("%08x\n", *Register);
  592. goto GetSetRegistersEnd;
  593. //
  594. // A value to write into the register was supplied. Attempt to evaluate
  595. // and write the register.
  596. //
  597. } else {
  598. if (Context->CurrentFrame != 0) {
  599. DbgOut("Error: Registers can only be set in frame 0.\n");
  600. goto GetSetRegistersEnd;
  601. }
  602. Result = DbgEvaluate(Context, ValueString, &NewValue);
  603. if (Result != 0) {
  604. DbgOut("Error: Unable to evaluate \"%s\".\n", ValueString);
  605. goto GetSetRegistersEnd;
  606. }
  607. if (Register != NULL) {
  608. *Register = (ULONG)NewValue;
  609. } else {
  610. assert(ShortRegister != NULL);
  611. *ShortRegister = (USHORT)NewValue;
  612. }
  613. Result = DbgSetRegisters(
  614. Context,
  615. &(Context->CurrentEvent.BreakNotification.Registers));
  616. goto GetSetRegistersEnd;
  617. }
  618. //
  619. // No parameters were specified, just dump all the register contents.
  620. //
  621. } else {
  622. if (Context->CurrentFrame != 0) {
  623. DbgOut("Frame %d Registers:\n", Context->CurrentFrame);
  624. }
  625. switch (Context->MachineType) {
  626. //
  627. // Dump x86 registers.
  628. //
  629. case MACHINE_TYPE_X86:
  630. DbgOut("eax=%08I64x ebx=%08I64x ecx=%08I64x edx=%08I64x "
  631. "eip=%08I64x\n"
  632. "esi=%08I64x edi=%08I64x ebp=%08I64x esp=%08I64x "
  633. "eflags=%08I64x\n",
  634. X86Registers->Eax,
  635. X86Registers->Ebx,
  636. X86Registers->Ecx,
  637. X86Registers->Edx,
  638. X86Registers->Eip,
  639. X86Registers->Esi,
  640. X86Registers->Edi,
  641. X86Registers->Ebp,
  642. X86Registers->Esp,
  643. X86Registers->Eflags);
  644. DbgOut("cs=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\n",
  645. X86Registers->Cs,
  646. X86Registers->Ds,
  647. X86Registers->Es,
  648. X86Registers->Fs,
  649. X86Registers->Gs,
  650. X86Registers->Ss);
  651. Eflags = (ULONG)X86Registers->Eflags;
  652. Iopl = (Eflags & IA32_EFLAG_IOPL_MASK) >> IA32_EFLAG_IOPL_SHIFT;
  653. DbgOut("Iopl: %d Flags: ", Iopl);
  654. if (((Eflags & IA32_EFLAG_ALWAYS_0) != 0) ||
  655. ((Eflags & IA32_EFLAG_ALWAYS_1) != IA32_EFLAG_ALWAYS_1)) {
  656. DbgOut("*** WARNING: Invalid Flags!! ***");
  657. }
  658. if ((Eflags & IA32_EFLAG_CF) != 0) {
  659. DbgOut("cf ");
  660. }
  661. if ((Eflags & IA32_EFLAG_PF) != 0) {
  662. DbgOut("pf ");
  663. }
  664. if ((Eflags & IA32_EFLAG_AF) != 0) {
  665. DbgOut("af ");
  666. }
  667. if ((Eflags & IA32_EFLAG_ZF) != 0) {
  668. DbgOut("zf ");
  669. }
  670. if ((Eflags & IA32_EFLAG_SF) != 0) {
  671. DbgOut("sf ");
  672. }
  673. if ((Eflags & IA32_EFLAG_TF) != 0) {
  674. DbgOut("tf ");
  675. }
  676. if ((Eflags & IA32_EFLAG_IF) != 0) {
  677. DbgOut("if ");
  678. }
  679. if ((Eflags & IA32_EFLAG_DF) != 0) {
  680. DbgOut("df ");
  681. }
  682. if ((Eflags & IA32_EFLAG_OF) != 0) {
  683. DbgOut("of ");
  684. }
  685. if ((Eflags & IA32_EFLAG_NT) != 0) {
  686. DbgOut("nt ");
  687. }
  688. if ((Eflags & IA32_EFLAG_RF) != 0) {
  689. DbgOut("rf ");
  690. }
  691. if ((Eflags & IA32_EFLAG_VM) != 0) {
  692. DbgOut("vm ");
  693. }
  694. if ((Eflags & IA32_EFLAG_AC) != 0) {
  695. DbgOut("ac ");
  696. }
  697. if ((Eflags & IA32_EFLAG_VIF) != 0) {
  698. DbgOut("vif ");
  699. }
  700. if ((Eflags & IA32_EFLAG_VIP) != 0) {
  701. DbgOut("vip ");
  702. }
  703. if ((Eflags & IA32_EFLAG_ID) != 0) {
  704. DbgOut("id ");
  705. }
  706. DbgOut("\n");
  707. break;
  708. //
  709. // Dump ARM registers.
  710. //
  711. case MACHINE_TYPE_ARM:
  712. DbgOut("r0=%08x r1=%08x r2=%08x r3=%08x r4=%08x r5=%08x\n"
  713. "r6=%08x r7=%08x r8=%08x r9=%08x r10=%08x fp=%08x\n"
  714. "ip=%08x sp=%08x lr=%08x pc=%08x cpsr=%08x\n",
  715. ArmRegisters->R0,
  716. ArmRegisters->R1,
  717. ArmRegisters->R2,
  718. ArmRegisters->R3,
  719. ArmRegisters->R4,
  720. ArmRegisters->R5,
  721. ArmRegisters->R6,
  722. ArmRegisters->R7,
  723. ArmRegisters->R8,
  724. ArmRegisters->R9,
  725. ArmRegisters->R10,
  726. ArmRegisters->R11Fp,
  727. ArmRegisters->R12Ip,
  728. ArmRegisters->R13Sp,
  729. ArmRegisters->R14Lr,
  730. ArmRegisters->R15Pc,
  731. ArmRegisters->Cpsr);
  732. DbgOut("Mode: ");
  733. Psr = ArmRegisters->Cpsr;
  734. switch (Psr & ARM_MODE_MASK) {
  735. case ARM_MODE_ABORT:
  736. DbgOut("Abort");
  737. break;
  738. case ARM_MODE_FIQ:
  739. DbgOut("FIQ");
  740. break;
  741. case ARM_MODE_IRQ:
  742. DbgOut("IRQ");
  743. break;
  744. case ARM_MODE_SVC:
  745. DbgOut("SVC");
  746. break;
  747. case ARM_MODE_SYSTEM:
  748. DbgOut("System");
  749. break;
  750. case ARM_MODE_UNDEF:
  751. DbgOut("Undefined Instruction");
  752. break;
  753. case ARM_MODE_USER:
  754. DbgOut("User");
  755. break;
  756. default:
  757. DbgOut("*** Unknown ***");
  758. break;
  759. }
  760. if ((Psr & PSR_FLAG_NEGATIVE) != 0) {
  761. DbgOut(" N");
  762. }
  763. if ((Psr & PSR_FLAG_ZERO) != 0) {
  764. DbgOut(" Z");
  765. }
  766. if ((Psr & PSR_FLAG_CARRY) != 0) {
  767. DbgOut(" C");
  768. }
  769. if ((Psr & PSR_FLAG_OVERFLOW) != 0) {
  770. DbgOut(" V");
  771. }
  772. if ((Psr & PSR_FLAG_SATURATION) != 0) {
  773. DbgOut(" Q");
  774. }
  775. if ((Psr & PSR_FLAG_JAZELLE) != 0) {
  776. DbgOut(" Jazelle");
  777. }
  778. if ((Psr & PSR_FLAG_THUMB) != 0) {
  779. DbgOut(" Thumb");
  780. }
  781. if ((Psr & PSR_FLAG_FIQ) != 0) {
  782. DbgOut(" FIQ");
  783. }
  784. if ((Psr & PSR_FLAG_IRQ) != 0) {
  785. DbgOut(" IRQ");
  786. }
  787. DbgOut("\n");
  788. break;
  789. default:
  790. DbgOut("Error: Unknown machine type %d.\n", Context->MachineType);
  791. goto GetSetRegistersEnd;
  792. }
  793. }
  794. GetSetRegistersEnd:
  795. return Result;
  796. }
  797. INT
  798. DbgrGetSetSpecialRegisters (
  799. PDEBUGGER_CONTEXT Context,
  800. PSTR *Arguments,
  801. ULONG ArgumentCount
  802. )
  803. /*++
  804. Routine Description:
  805. This routine prints or modifies the target machine's special registers.
  806. Arguments:
  807. Context - Supplies a pointer to the application context.
  808. Arguments - Supplies an array of strings containing the arguments. The
  809. first argument is the command itself.
  810. ArgumentCount - Supplies the count of arguments. This is always at least
  811. one.
  812. Return Value:
  813. 0 on success.
  814. Returns an error code on failure.
  815. --*/
  816. {
  817. PSPECIAL_REGISTERS_UNION Original;
  818. PVOID Register;
  819. PULONG Register2;
  820. ULONG RegisterSize;
  821. PSTR RegisterString;
  822. INT Result;
  823. SET_SPECIAL_REGISTERS SetCommand;
  824. ULONGLONG Value;
  825. ULONGLONG Value2;
  826. PSTR ValueCopy;
  827. PSTR ValueString;
  828. PSTR ValueString2;
  829. Register = NULL;
  830. RegisterString = NULL;
  831. Register2 = NULL;
  832. ValueCopy = NULL;
  833. ValueString = NULL;
  834. if (ArgumentCount >= 2) {
  835. RegisterString = Arguments[1];
  836. if (ArgumentCount >= 3) {
  837. ValueString = Arguments[2];
  838. }
  839. }
  840. //
  841. // Fill in the new registers as if they were the originals so they can be
  842. // modified in place.
  843. //
  844. Original = &(SetCommand.New);
  845. Result = DbgGetSpecialRegisters(Context, Original);
  846. if (Result != 0) {
  847. goto GetSetSpecialRegistersEnd;
  848. }
  849. //
  850. // A specific register is being read or written to.
  851. //
  852. if (RegisterString != NULL) {
  853. switch (Context->MachineType) {
  854. case MACHINE_TYPE_X86:
  855. RegisterSize = 8;
  856. if (strcasecmp(RegisterString, "cr0") == 0) {
  857. Register = &(Original->Ia.Cr0);
  858. } else if (strcasecmp(RegisterString, "cr2") == 0) {
  859. Register = &(Original->Ia.Cr2);
  860. } else if (strcasecmp(RegisterString, "cr3") == 0) {
  861. Register = &(Original->Ia.Cr3);
  862. } else if (strcasecmp(RegisterString, "cr4") == 0) {
  863. Register = &(Original->Ia.Cr4);
  864. } else if (strcasecmp(RegisterString, "dr0") == 0) {
  865. Register = &(Original->Ia.Dr0);
  866. } else if (strcasecmp(RegisterString, "dr1") == 0) {
  867. Register = &(Original->Ia.Dr1);
  868. } else if (strcasecmp(RegisterString, "dr2") == 0) {
  869. Register = &(Original->Ia.Dr2);
  870. } else if (strcasecmp(RegisterString, "dr3") == 0) {
  871. Register = &(Original->Ia.Dr3);
  872. } else if (strcasecmp(RegisterString, "dr6") == 0) {
  873. Register = &(Original->Ia.Dr6);
  874. } else if (strcasecmp(RegisterString, "dr7") == 0) {
  875. Register = &(Original->Ia.Dr7);
  876. } else if (strcasecmp(RegisterString, "idtr") == 0) {
  877. RegisterSize = 4;
  878. Register = &(Original->Ia.Idtr.Base);
  879. Register2 = &(Original->Ia.Idtr.Limit);
  880. } else if (strcasecmp(RegisterString, "gdtr") == 0) {
  881. RegisterSize = 4;
  882. Register = &(Original->Ia.Gdtr.Base);
  883. Register2 = &(Original->Ia.Gdtr.Limit);
  884. } else if (strcasecmp(RegisterString, "tr") == 0) {
  885. RegisterSize = 2;
  886. Register = &(Original->Ia.Tr);
  887. } else {
  888. DbgOut("Error: Unknown register '%s'.\n", RegisterString);
  889. Result = EINVAL;
  890. goto GetSetSpecialRegistersEnd;
  891. }
  892. break;
  893. case MACHINE_TYPE_ARM:
  894. RegisterSize = 4;
  895. if (strcasecmp(RegisterString, "sctlr") == 0) {
  896. Register = &(Original->Arm.Sctlr);
  897. } else if (strcasecmp(RegisterString, "actlr") == 0) {
  898. Register = &(Original->Arm.Actlr);
  899. } else if (strcasecmp(RegisterString, "ttbr0") == 0) {
  900. Register = &(Original->Arm.Ttbr0);
  901. } else if (strcasecmp(RegisterString, "ttbr1") == 0) {
  902. Register = &(Original->Arm.Ttbr1);
  903. } else if (strcasecmp(RegisterString, "dfsr") == 0) {
  904. Register = &(Original->Arm.Dfsr);
  905. } else if (strcasecmp(RegisterString, "ifsr") == 0) {
  906. Register = &(Original->Arm.Ifsr);
  907. } else if (strcasecmp(RegisterString, "dfar") == 0) {
  908. Register = &(Original->Arm.Dfar);
  909. } else if (strcasecmp(RegisterString, "ifar") == 0) {
  910. Register = &(Original->Arm.Ifar);
  911. } else if (strcasecmp(RegisterString, "prrr") == 0) {
  912. Register = &(Original->Arm.Prrr);
  913. } else if (strcasecmp(RegisterString, "nmrr") == 0) {
  914. Register = &(Original->Arm.Nmrr);
  915. } else if (strcasecmp(RegisterString, "vbar") == 0) {
  916. Register = &(Original->Arm.Vbar);
  917. } else if (strcasecmp(RegisterString, "par") == 0) {
  918. Register = &(Original->Arm.Par);
  919. } else if (strcasecmp(RegisterString, "ats1cpr") == 0) {
  920. Register = &(Original->Arm.Ats1Cpr);
  921. } else if (strcasecmp(RegisterString, "ats1cpw") == 0) {
  922. Register = &(Original->Arm.Ats1Cpw);
  923. } else if (strcasecmp(RegisterString, "ats1cur") == 0) {
  924. Register = &(Original->Arm.Ats1Cur);
  925. } else if (strcasecmp(RegisterString, "ats1cuw") == 0) {
  926. Register = &(Original->Arm.Ats1Cuw);
  927. } else if (strcasecmp(RegisterString, "tpidrprw") == 0) {
  928. Register = &(Original->Arm.Tpidrprw);
  929. } else {
  930. DbgOut("Error: Unknown register '%s'.\n", RegisterString);
  931. Result = EINVAL;
  932. goto GetSetSpecialRegistersEnd;
  933. }
  934. break;
  935. default:
  936. DbgOut("GetSetSpecialRegisters: Unknown architecture.\n");
  937. Result = EINVAL;
  938. goto GetSetSpecialRegistersEnd;
  939. }
  940. //
  941. // Set a register.
  942. //
  943. if (ValueString != NULL) {
  944. ValueCopy = strdup(ValueString);
  945. if (ValueCopy == NULL) {
  946. Result = ENOMEM;
  947. goto GetSetSpecialRegistersEnd;
  948. }
  949. ValueString2 = strchr(ValueCopy, ',');
  950. if (ValueString2 != NULL) {
  951. *ValueString2 = '\0';
  952. ValueString2 += 1;
  953. }
  954. Result = DbgEvaluate(Context, ValueCopy, &Value);
  955. if (Result != 0) {
  956. DbgOut("Failed to evaluate '%s'.\n", ValueCopy);
  957. goto GetSetSpecialRegistersEnd;
  958. }
  959. if (ValueString2 != NULL) {
  960. Result = DbgEvaluate(Context, ValueString2, &Value2);
  961. if (Result != 0) {
  962. DbgOut("Failed to evaluate '%s'.\n", ValueCopy);
  963. goto GetSetSpecialRegistersEnd;
  964. }
  965. }
  966. if ((ValueString2 != NULL) && (Register2 == NULL)) {
  967. DbgOut("Error: %s takes only one argument.\n", RegisterString);
  968. Result = EINVAL;
  969. goto GetSetSpecialRegistersEnd;
  970. } else if ((ValueString2 == NULL) && (Register2 != NULL)) {
  971. DbgOut("Error: %s takes two arguments (in the form "
  972. "'base,limit').\n",
  973. RegisterString);
  974. Result = EINVAL;
  975. goto GetSetSpecialRegistersEnd;
  976. }
  977. //
  978. // Set the register. Copy the originals to the originals position
  979. // first.
  980. //
  981. memcpy(&(SetCommand.Original),
  982. &(SetCommand.New),
  983. sizeof(SPECIAL_REGISTERS_UNION));
  984. memcpy(Register, &Value, RegisterSize);
  985. if (Register2 != NULL) {
  986. memcpy(Register2, &Value2, sizeof(ULONG));
  987. }
  988. Result = DbgSetSpecialRegisters(Context, &SetCommand);
  989. if (Result != 0) {
  990. goto GetSetSpecialRegistersEnd;
  991. }
  992. } else {
  993. Value = 0;
  994. memcpy(&Value, Register, RegisterSize);
  995. if (Register2 != NULL) {
  996. DbgOut("%I64x,%x\n", Value, *Register2);
  997. } else {
  998. DbgOut("%I64x\n", Value);
  999. }
  1000. }
  1001. //
  1002. // Just print all the registers.
  1003. //
  1004. } else {
  1005. switch (Context->MachineType) {
  1006. case MACHINE_TYPE_X86:
  1007. DbgOut("cr0=%08I64x cr2=%08I64x cr3=%08I64x cr4=%08I64x tr=%04x\n"
  1008. "dr0=%08I64x dr1=%08I64x dr2=%08I64x dr3=%08I64x\n"
  1009. "dr6=%08I64x dr7=%08I64x\n"
  1010. "idtr=%08x,%04x gdtr=%08x,%04x\n",
  1011. Original->Ia.Cr0,
  1012. Original->Ia.Cr2,
  1013. Original->Ia.Cr3,
  1014. Original->Ia.Cr4,
  1015. Original->Ia.Tr,
  1016. Original->Ia.Dr0,
  1017. Original->Ia.Dr1,
  1018. Original->Ia.Dr2,
  1019. Original->Ia.Dr3,
  1020. Original->Ia.Dr6,
  1021. Original->Ia.Dr7,
  1022. Original->Ia.Idtr.Base,
  1023. Original->Ia.Idtr.Limit,
  1024. Original->Ia.Gdtr.Base,
  1025. Original->Ia.Gdtr.Limit);
  1026. break;
  1027. case MACHINE_TYPE_ARM:
  1028. DbgOut("Not shown: ats1cpr, ats1cpw, ats1cur, ats1cuw\n"
  1029. "sctlr=%08x actlr=%08x ttbr0=%08I64x ttbr1=%08I64x\n"
  1030. " dfsr=%08x dfar=%08I64x ifsr=%08x ifar=%08I64x\n"
  1031. " prrr=%08x nmrr=%08x vbar=%08x par=%08I64x\n"
  1032. "tpidrprw=%08I64x\n",
  1033. Original->Arm.Sctlr,
  1034. Original->Arm.Actlr,
  1035. Original->Arm.Ttbr0,
  1036. Original->Arm.Ttbr1,
  1037. Original->Arm.Dfsr,
  1038. Original->Arm.Dfar,
  1039. Original->Arm.Ifsr,
  1040. Original->Arm.Ifar,
  1041. Original->Arm.Prrr,
  1042. Original->Arm.Nmrr,
  1043. Original->Arm.Vbar,
  1044. Original->Arm.Par,
  1045. Original->Arm.Tpidrprw);
  1046. break;
  1047. default:
  1048. DbgOut("GetSetSpecialRegisters: Unknown architecture.\n");
  1049. Result = EINVAL;
  1050. goto GetSetSpecialRegistersEnd;
  1051. }
  1052. }
  1053. Result = 0;
  1054. GetSetSpecialRegistersEnd:
  1055. if (ValueCopy != NULL) {
  1056. free(ValueCopy);
  1057. }
  1058. return Result;
  1059. }
  1060. INT
  1061. DbgrPrintCallStack (
  1062. PDEBUGGER_CONTEXT Context,
  1063. PSTR *Arguments,
  1064. ULONG ArgumentCount
  1065. )
  1066. /*++
  1067. Routine Description:
  1068. This routine prints the current call stack.
  1069. Arguments:
  1070. Context - Supplies a pointer to the application context.
  1071. Arguments - Supplies an array of strings containing the arguments. The
  1072. first argument is the command itself.
  1073. ArgumentCount - Supplies the count of arguments. This is always at least
  1074. one.
  1075. Return Value:
  1076. 0 on success.
  1077. Returns an error code on failure.
  1078. --*/
  1079. {
  1080. ULONGLONG BasePointer;
  1081. ULONGLONG InstructionPointer;
  1082. REGISTERS_UNION LocalRegisters;
  1083. BOOL PrintFrameNumbers;
  1084. PREGISTERS_UNION Registers;
  1085. INT Result;
  1086. ULONGLONG StackPointer;
  1087. Registers = NULL;
  1088. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  1089. if ((ArgumentCount != 1) && (ArgumentCount != 4)) {
  1090. DbgOut("Usage: k [<InstructionPointer> <StackPointer> "
  1091. "<BasePointer>]\n");
  1092. return EINVAL;
  1093. }
  1094. PrintFrameNumbers = FALSE;
  1095. if (strcasecmp(Arguments[0], "kn") == 0) {
  1096. PrintFrameNumbers = TRUE;
  1097. } else {
  1098. assert(strcasecmp(Arguments[0], "k") == 0);
  1099. }
  1100. if (ArgumentCount == 4) {
  1101. RtlCopyMemory(&LocalRegisters,
  1102. &(Context->CurrentEvent.BreakNotification.Registers),
  1103. sizeof(REGISTERS_UNION));
  1104. Registers = &LocalRegisters;
  1105. Result = DbgEvaluate(Context, Arguments[1], &InstructionPointer);
  1106. if (Result != 0) {
  1107. DbgOut("Failed to evaluate \"%s\".\n", Arguments[1]);
  1108. goto PrintCallStackEnd;
  1109. }
  1110. Result = DbgEvaluate(Context, Arguments[2], &StackPointer);
  1111. if (Result != 0) {
  1112. DbgOut("Failed to evaluate \"%s\".\n", Arguments[2]);
  1113. goto PrintCallStackEnd;
  1114. }
  1115. Result = DbgEvaluate(Context, Arguments[3], &BasePointer);
  1116. if (Result != 0) {
  1117. DbgOut("Failed to evaluate \"%s\".\n", Arguments[3]);
  1118. goto PrintCallStackEnd;
  1119. }
  1120. switch (Context->MachineType) {
  1121. case MACHINE_TYPE_X86:
  1122. LocalRegisters.X86.Eip = InstructionPointer;
  1123. LocalRegisters.X86.Esp = StackPointer;
  1124. LocalRegisters.X86.Ebp = BasePointer;
  1125. break;
  1126. case MACHINE_TYPE_ARM:
  1127. LocalRegisters.Arm.R15Pc = InstructionPointer;
  1128. LocalRegisters.Arm.R13Sp = StackPointer;
  1129. if ((LocalRegisters.Arm.Cpsr & PSR_FLAG_THUMB) != 0) {
  1130. LocalRegisters.Arm.R7 = BasePointer;
  1131. } else {
  1132. LocalRegisters.Arm.R11Fp = BasePointer;
  1133. }
  1134. break;
  1135. }
  1136. }
  1137. Result = DbgPrintCallStack(Context, Registers, PrintFrameNumbers);
  1138. if (Result != 0) {
  1139. goto PrintCallStackEnd;
  1140. }
  1141. Result = 0;
  1142. PrintCallStackEnd:
  1143. return Result;
  1144. }
  1145. INT
  1146. DbgrSetFrame (
  1147. PDEBUGGER_CONTEXT Context,
  1148. PSTR *Arguments,
  1149. ULONG ArgumentCount
  1150. )
  1151. /*++
  1152. Routine Description:
  1153. This routine changes the current stack frame, so that local variables may
  1154. come from a different function in the call stack.
  1155. Arguments:
  1156. Context - Supplies a pointer to the application context.
  1157. Arguments - Supplies an array of strings containing the arguments. The
  1158. first argument is the command itself.
  1159. ArgumentCount - Supplies the count of arguments. This is always at least
  1160. one.
  1161. Return Value:
  1162. 0 on success.
  1163. Returns an error code on failure.
  1164. --*/
  1165. {
  1166. PSTR AfterScan;
  1167. ULONG FrameNumber;
  1168. PSTR FrameNumberString;
  1169. INT Status;
  1170. if (ArgumentCount < 2) {
  1171. DbgOut("Usage: frame <N>\nSets the current call stack frame, where "
  1172. "N is a number between 0 and the number of stack frames (use "
  1173. "kn to dump numbered frames).\n");
  1174. Status = EINVAL;
  1175. goto SetFrameEnd;
  1176. }
  1177. FrameNumberString = Arguments[1];
  1178. FrameNumber = strtoul(FrameNumberString, &AfterScan, 0);
  1179. if (FrameNumberString == AfterScan) {
  1180. DbgOut("Failed to convert '%s' to a number.\n", FrameNumberString);
  1181. Status = EINVAL;
  1182. goto SetFrameEnd;
  1183. }
  1184. Status = DbgrpSetFrame(Context, FrameNumber);
  1185. SetFrameEnd:
  1186. return Status;
  1187. }
  1188. INT
  1189. DbgrDisassemble (
  1190. PDEBUGGER_CONTEXT Context,
  1191. PSTR *Arguments,
  1192. ULONG ArgumentCount
  1193. )
  1194. /*++
  1195. Routine Description:
  1196. This routine disassembles instructions from the target.
  1197. Arguments:
  1198. Context - Supplies a pointer to the application context.
  1199. Arguments - Supplies an array of strings containing the arguments. The
  1200. first argument is the command itself.
  1201. ArgumentCount - Supplies the count of arguments. This is always at least
  1202. one.
  1203. Return Value:
  1204. 0 on success.
  1205. Returns an error code on failure.
  1206. --*/
  1207. {
  1208. ULONGLONG ActualAddress;
  1209. ULONG BufferSize;
  1210. ULONG BytesConsumed;
  1211. ULONG BytesRead;
  1212. ULONG InstructionCount;
  1213. PBYTE InstructionStream;
  1214. ULONGLONG NewAddress;
  1215. BOOL Result;
  1216. InstructionCount = DEFAULT_DISASSEMBLED_INSTRUCTIONS;
  1217. BufferSize = InstructionCount * BYTES_PER_INSTRUCTION;
  1218. InstructionStream = NULL;
  1219. //
  1220. // If an address string was supplied, parse that. Otherwise, print from
  1221. // where disassembly left off.
  1222. //
  1223. if (ArgumentCount >= 2) {
  1224. Result = DbgEvaluate(Context, Arguments[1], &NewAddress);
  1225. if (Result != 0) {
  1226. DbgOut("Error: Unable to parse address '%s'.\n", Arguments[1]);
  1227. goto DisassembleEnd;
  1228. } else {
  1229. Context->DisassemblyAddress = NewAddress;
  1230. }
  1231. }
  1232. //
  1233. // Allocate memory to hold the binary instructions.
  1234. //
  1235. InstructionStream = malloc(BufferSize);
  1236. if (InstructionStream == NULL) {
  1237. Result = ENOMEM;
  1238. goto DisassembleEnd;
  1239. }
  1240. memset(InstructionStream, 0, BufferSize);
  1241. //
  1242. // Read the memory from the target.
  1243. //
  1244. ActualAddress = Context->DisassemblyAddress;
  1245. if (Context->MachineType == MACHINE_TYPE_ARM) {
  1246. ActualAddress &= ~ARM_THUMB_BIT;
  1247. }
  1248. Result = DbgReadMemory(Context,
  1249. TRUE,
  1250. ActualAddress,
  1251. BufferSize,
  1252. InstructionStream,
  1253. &BytesRead);
  1254. if (Result != 0) {
  1255. goto DisassembleEnd;
  1256. }
  1257. if (BytesRead < BufferSize) {
  1258. BufferSize = BytesRead;
  1259. }
  1260. //
  1261. // Print out the disassembly and advance the disassembly address.
  1262. //
  1263. Result = DbgrpPrintDisassembly(Context,
  1264. InstructionStream,
  1265. Context->DisassemblyAddress,
  1266. BufferSize / BYTES_PER_INSTRUCTION,
  1267. &BytesConsumed);
  1268. if (Result != 0) {
  1269. goto DisassembleEnd;
  1270. }
  1271. Result = 0;
  1272. Context->DisassemblyAddress += BytesConsumed;
  1273. DisassembleEnd:
  1274. if (InstructionStream != NULL) {
  1275. free(InstructionStream);
  1276. }
  1277. return Result;
  1278. }
  1279. INT
  1280. DbgrWaitForEvent (
  1281. PDEBUGGER_CONTEXT Context
  1282. )
  1283. /*++
  1284. Routine Description:
  1285. This routine gets an event from the target, such as a break event or other
  1286. exception.
  1287. Arguments:
  1288. Context - Supplies a pointer to the debugger context.
  1289. Return Value:
  1290. 0 on success,
  1291. Returns an error code on failure.
  1292. --*/
  1293. {
  1294. INT Result;
  1295. while ((Context->TargetFlags & DEBUGGER_TARGET_RUNNING) != 0) {
  1296. Result = DbgWaitForEvent(Context);
  1297. if (Result != 0) {
  1298. DbgOut("Error: Failed to get next debugging event.\n");
  1299. return Result;
  1300. }
  1301. switch (Context->CurrentEvent.Type) {
  1302. case DebuggerEventBreak:
  1303. Result = DbgrpProcessBreakNotification(Context);
  1304. if (Result != 0) {
  1305. goto WaitForEventEnd;
  1306. }
  1307. break;
  1308. case DebuggerEventShutdown:
  1309. DbgrpProcessShutdown(Context);
  1310. break;
  1311. case DebuggerEventProfiler:
  1312. DbgrProcessProfilerNotification(Context);
  1313. break;
  1314. default:
  1315. //
  1316. // The target sent an unknown command.
  1317. //
  1318. DbgOut("Unknown event received: 0x%x\n",
  1319. Context->CurrentEvent.Type);
  1320. break;
  1321. }
  1322. }
  1323. Result = 0;
  1324. WaitForEventEnd:
  1325. return Result;
  1326. }
  1327. INT
  1328. DbgrSearchSymbols (
  1329. PDEBUGGER_CONTEXT Context,
  1330. PSTR *Arguments,
  1331. ULONG ArgumentCount
  1332. )
  1333. /*++
  1334. Routine Description:
  1335. This routine searches for symbols. Wildcards are accepted. If the search
  1336. string is preceded by "modulename!" then only that module will be searched.
  1337. Arguments:
  1338. Context - Supplies a pointer to the application context.
  1339. Arguments - Supplies an array of strings containing the arguments. The
  1340. first argument is the command itself.
  1341. ArgumentCount - Supplies the count of arguments. This is always at least
  1342. one.
  1343. Return Value:
  1344. 0 on success.
  1345. Returns an error code on failure.
  1346. --*/
  1347. {
  1348. ULONGLONG Address;
  1349. PDEBUGGER_MODULE CurrentModule;
  1350. PLIST_ENTRY CurrentModuleEntry;
  1351. PSTR ModuleEnd;
  1352. ULONG ModuleLength;
  1353. ULONGLONG Pc;
  1354. INT Result;
  1355. PSYMBOL_SEARCH_RESULT ResultValid;
  1356. SYMBOL_SEARCH_RESULT SearchResult;
  1357. PSTR SearchString;
  1358. PDEBUGGER_MODULE UserModule;
  1359. UserModule = NULL;
  1360. if (ArgumentCount != 2) {
  1361. DbgOut("Usage: x <query>\nThe x command searches for a symbol with "
  1362. "the given name. Wildcards are accepted.");
  1363. Result = EINVAL;
  1364. goto SearchSymbolsEnd;
  1365. }
  1366. SearchString = Arguments[1];
  1367. //
  1368. // If an exclamation point exists, then the module was specified. Find that
  1369. // module.
  1370. //
  1371. ModuleEnd = strchr(SearchString, '!');
  1372. if (ModuleEnd != NULL) {
  1373. ModuleLength = (UINTN)ModuleEnd - (UINTN)SearchString;
  1374. UserModule = DbgpGetModule(Context, SearchString, ModuleLength);
  1375. if (UserModule == NULL) {
  1376. DbgOut("Module %s not found.\n", SearchString);
  1377. Result = ENOENT;
  1378. goto SearchSymbolsEnd;
  1379. }
  1380. //
  1381. // Move the search string and initialize the list entry.
  1382. //
  1383. SearchString = ModuleEnd + 1;
  1384. CurrentModuleEntry = &(UserModule->ListEntry);
  1385. //
  1386. // If a module was not specified, simply start with the first one.
  1387. //
  1388. } else {
  1389. CurrentModuleEntry = Context->ModuleList.ModulesHead.Next;
  1390. }
  1391. //
  1392. // Loop over all modules.
  1393. //
  1394. while (CurrentModuleEntry != &(Context->ModuleList.ModulesHead)) {
  1395. CurrentModule = LIST_VALUE(CurrentModuleEntry,
  1396. DEBUGGER_MODULE,
  1397. ListEntry);
  1398. CurrentModuleEntry = CurrentModuleEntry->Next;
  1399. if (!IS_MODULE_IN_CURRENT_PROCESS(Context, CurrentModule)) {
  1400. if (UserModule != NULL) {
  1401. break;
  1402. }
  1403. continue;
  1404. }
  1405. //
  1406. // Loop over all symbol search results.
  1407. //
  1408. SearchResult.Variety = SymbolResultInvalid;
  1409. while (TRUE) {
  1410. //
  1411. // Perform the search. If it fails, break out of this loop.
  1412. //
  1413. ResultValid = DbgpFindSymbolInModule(CurrentModule->Symbols,
  1414. SearchString,
  1415. &SearchResult);
  1416. if (ResultValid == NULL) {
  1417. break;
  1418. }
  1419. //
  1420. // Print out the result.
  1421. //
  1422. Result = TRUE;
  1423. switch (SearchResult.Variety) {
  1424. case SymbolResultFunction:
  1425. Address = SearchResult.U.FunctionResult->StartAddress +
  1426. CurrentModule->BaseDifference;
  1427. DbgPrintFunctionPrototype(SearchResult.U.FunctionResult,
  1428. CurrentModule->ModuleName,
  1429. Address);
  1430. DbgOut("\n");
  1431. break;
  1432. case SymbolResultData:
  1433. Pc = DbgGetPc(Context, &(Context->FrameRegisters)) -
  1434. CurrentModule->BaseDifference;
  1435. Result = DbgGetDataSymbolAddress(Context,
  1436. CurrentModule->Symbols,
  1437. SearchResult.U.DataResult,
  1438. Pc,
  1439. &Address);
  1440. if (Result == 0) {
  1441. DbgOut("%s!%s @ 0x%08x\n",
  1442. CurrentModule->ModuleName,
  1443. SearchResult.U.DataResult->Name,
  1444. Address + CurrentModule->BaseDifference);
  1445. }
  1446. Result = TRUE;
  1447. break;
  1448. case SymbolResultType:
  1449. DbgOut("%s!%s\n",
  1450. CurrentModule->ModuleName,
  1451. SearchResult.U.TypeResult->Name);
  1452. break;
  1453. default:
  1454. DbgOut("ERROR: Unknown search result type %d returned!",
  1455. SearchResult.U.TypeResult);
  1456. Result = EINVAL;
  1457. goto SearchSymbolsEnd;
  1458. }
  1459. if (Result == FALSE) {
  1460. Result = ENOENT;
  1461. goto SearchSymbolsEnd;
  1462. }
  1463. }
  1464. //
  1465. // If a specific user module was specified, do not loop over more
  1466. // modules.
  1467. //
  1468. if (UserModule != NULL) {
  1469. break;
  1470. }
  1471. }
  1472. Result = 0;
  1473. SearchSymbolsEnd:
  1474. return Result;
  1475. }
  1476. INT
  1477. DbgrDumpTypeCommand (
  1478. PDEBUGGER_CONTEXT Context,
  1479. PSTR *Arguments,
  1480. ULONG ArgumentCount
  1481. )
  1482. /*++
  1483. Routine Description:
  1484. This routine prints information about a type description or value. If only
  1485. a type is specified, the type format will be printed. If an address is
  1486. passed as a second parameter, then the values will be dumped. If a global
  1487. or local variable is passed as the first parameter, the values will also be
  1488. dumped.
  1489. Arguments:
  1490. Context - Supplies a pointer to the application context.
  1491. Arguments - Supplies an array of strings containing the arguments. The
  1492. first argument is the command itself.
  1493. ArgumentCount - Supplies the count of arguments. This is always at least
  1494. one.
  1495. Return Value:
  1496. 0 on success.
  1497. Returns an error code on failure.
  1498. --*/
  1499. {
  1500. INT Result;
  1501. if (ArgumentCount < 2) {
  1502. DbgOut("Usage: dt <type name> [<address...> | <variable name>]\n");
  1503. Result = EINVAL;
  1504. goto DumpTypeCommandEnd;
  1505. }
  1506. Result = DbgrDumpType(Context, Arguments + 1, ArgumentCount - 1, NULL, 0);
  1507. if (Result != 0) {
  1508. goto DumpTypeCommandEnd;
  1509. }
  1510. DbgOut("\n");
  1511. Result = 0;
  1512. DumpTypeCommandEnd:
  1513. return Result;
  1514. }
  1515. INT
  1516. DbgrDumpMemory (
  1517. PDEBUGGER_CONTEXT Context,
  1518. PSTR *Arguments,
  1519. ULONG ArgumentCount
  1520. )
  1521. /*++
  1522. Routine Description:
  1523. This routine prints the contents of debuggee memory to the screen.
  1524. Arguments:
  1525. Context - Supplies a pointer to the application context.
  1526. Arguments - Supplies an array of strings containing the arguments. The
  1527. first argument is the command itself.
  1528. ArgumentCount - Supplies the count of arguments. This is always at least
  1529. one.
  1530. Return Value:
  1531. 0 on success.
  1532. Returns an error code on failure.
  1533. --*/
  1534. {
  1535. ULONGLONG Address;
  1536. PSTR Argument;
  1537. ULONG ArgumentIndex;
  1538. ULONGLONG Columns;
  1539. PSTR MemoryType;
  1540. BOOL PrintCharacters;
  1541. INT Status;
  1542. ULONGLONG TotalValues;
  1543. ULONG TypeSize;
  1544. BOOL VirtualAddress;
  1545. Columns = 0;
  1546. PrintCharacters = TRUE;
  1547. TotalValues = 0;
  1548. VirtualAddress = TRUE;
  1549. MemoryType = Arguments[0];
  1550. //
  1551. // Get the type size.
  1552. //
  1553. if (strcasecmp(MemoryType, "db") == 0) {
  1554. TypeSize = 1;
  1555. } else if (strcasecmp(MemoryType, "dc") == 0) {
  1556. TypeSize = 1;
  1557. } else if (strcasecmp(MemoryType, "dw") == 0) {
  1558. TypeSize = 2;
  1559. } else if (strcasecmp(MemoryType, "dd") == 0) {
  1560. TypeSize = 4;
  1561. } else if (strcasecmp(MemoryType, "dq") == 0) {
  1562. TypeSize = 8;
  1563. } else {
  1564. DbgOut("Error: unrecognized command. Valid dump commands are db (byte),"
  1565. " dc (char), dw (word), dd (double-word), dq (quad-word), and "
  1566. "dt (type).\n");
  1567. Status = EINVAL;
  1568. goto DebuggerDumpMemoryEnd;
  1569. }
  1570. //
  1571. // Go through the arguments.
  1572. //
  1573. for (ArgumentIndex = 1; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  1574. Argument = Arguments[ArgumentIndex];
  1575. assert(Argument != NULL);
  1576. if (Argument[0] == '-') {
  1577. Argument += 1;
  1578. //
  1579. // 'c' specifies the number of columns.
  1580. //
  1581. if (Argument[0] == 'c') {
  1582. Status = DbgEvaluate(Context, Argument + 1, &Columns);
  1583. if (Status != 0) {
  1584. DbgOut("Error: Invalid column argument \"%s\". The correct "
  1585. "form looks something like \"c4\".\n",
  1586. Argument);
  1587. goto DebuggerDumpMemoryEnd;
  1588. }
  1589. }
  1590. //
  1591. // 'l' specifies the number of values to print.
  1592. //
  1593. if (Argument[0] == 'l') {
  1594. Status = DbgEvaluate(Context, Argument + 1, &TotalValues);
  1595. if (Status != 0) {
  1596. DbgOut("Error: Invalid total values argument \"%s\". The "
  1597. "correct form looks something like \"l8\".\n",
  1598. Argument);
  1599. goto DebuggerDumpMemoryEnd;
  1600. }
  1601. }
  1602. //
  1603. // 'p' specifies physical addressing.
  1604. //
  1605. if (Argument[0] == 'p') {
  1606. VirtualAddress = FALSE;
  1607. }
  1608. }
  1609. //
  1610. // The last argument is the address to dump.
  1611. //
  1612. if (ArgumentIndex == ArgumentCount - 1) {
  1613. Status = DbgEvaluate(Context, Argument, &Address);
  1614. if (Status != 0) {
  1615. DbgOut("Error: unable to parse address \"%s\".\n", Argument);
  1616. goto DebuggerDumpMemoryEnd;
  1617. }
  1618. }
  1619. }
  1620. //
  1621. // If the argument count is 0, continue from the previous dump or print the
  1622. // default dump.
  1623. //
  1624. if (ArgumentCount <= 1) {
  1625. Address = Context->LastMemoryDump.NextAddress;
  1626. VirtualAddress = Context->LastMemoryDump.Virtual;
  1627. Columns = Context->LastMemoryDump.Columns;
  1628. TotalValues = Context->LastMemoryDump.TotalValues;
  1629. PrintCharacters = Context->LastMemoryDump.PrintCharacters;
  1630. //
  1631. // Save the current dump parameters.
  1632. //
  1633. } else {
  1634. Context->LastMemoryDump.NextAddress = Address +
  1635. (TypeSize * TotalValues);
  1636. Context->LastMemoryDump.Virtual = VirtualAddress;
  1637. Context->LastMemoryDump.Columns = Columns;
  1638. Context->LastMemoryDump.TotalValues = TotalValues;
  1639. Context->LastMemoryDump.PrintCharacters = PrintCharacters;
  1640. }
  1641. //
  1642. // Update the last dump address.
  1643. //
  1644. if (TotalValues == 0) {
  1645. Context->LastMemoryDump.NextAddress += 16 * DEFAULT_MEMORY_PRINT_ROWS;
  1646. } else {
  1647. Context->LastMemoryDump.NextAddress += TotalValues * TypeSize;
  1648. }
  1649. //
  1650. // All the information has been collected. Attempt to print the memory.
  1651. //
  1652. Status = DbgrpPrintMemory(Context,
  1653. Address,
  1654. VirtualAddress,
  1655. TypeSize,
  1656. Columns,
  1657. TotalValues,
  1658. PrintCharacters);
  1659. if (Status != 0) {
  1660. goto DebuggerDumpMemoryEnd;
  1661. }
  1662. Status = 0;
  1663. DebuggerDumpMemoryEnd:
  1664. return Status;
  1665. }
  1666. INT
  1667. DbgrDumpList (
  1668. PDEBUGGER_CONTEXT Context,
  1669. PSTR *Arguments,
  1670. ULONG ArgumentCount
  1671. )
  1672. /*++
  1673. Routine Description:
  1674. This routine interates over a linked list and prints out the structure
  1675. information for each entry. It also performs basic validation on the list,
  1676. checking for bad previous pointers.
  1677. Arguments:
  1678. Context - Supplies a pointer to the application context.
  1679. Arguments - Supplies an array of strings containing the arguments. The
  1680. first argument is the command itself.
  1681. ArgumentCount - Supplies the count of arguments. This is always at least
  1682. one.
  1683. Return Value:
  1684. 0 on success.
  1685. Returns an error code on failure.
  1686. --*/
  1687. {
  1688. ULONG BytesRead;
  1689. ULONG Count;
  1690. ULONGLONG CurrentAddress;
  1691. ULONG FieldOffset;
  1692. ULONG FieldSize;
  1693. ULONGLONG ListEntry[2];
  1694. PSTR ListEntryName;
  1695. ULONG ListEntrySize;
  1696. ULONGLONG ListHeadAddress;
  1697. PSTR ListHeadAddressString;
  1698. ULONG PointerSize;
  1699. ULONGLONG PreviousAddress;
  1700. PTYPE_SYMBOL ResolvedType;
  1701. BOOL Result;
  1702. SYMBOL_SEARCH_RESULT SearchResult;
  1703. INT Status;
  1704. ULONGLONG StructureAddress;
  1705. PVOID StructureBuffer;
  1706. PDATA_TYPE_STRUCTURE StructureData;
  1707. ULONG StructureSize;
  1708. PSTR TypeNameString;
  1709. Status = EINVAL;
  1710. //
  1711. // Argument validation.
  1712. //
  1713. if (ArgumentCount < 3) {
  1714. DbgOut("Usage: dl <list head address> <type name> "
  1715. "[<list entry name>]\n");
  1716. goto DumpListEnd;
  1717. }
  1718. ListHeadAddressString = Arguments[1];
  1719. TypeNameString = Arguments[2];
  1720. //
  1721. // Evaluate the first argument, converting it to the list head address.
  1722. //
  1723. Status = DbgEvaluate(Context, ListHeadAddressString, &ListHeadAddress);
  1724. if (Status != 0) {
  1725. DbgOut("Error: Could not evaluate address from string %s\n",
  1726. Arguments[0]);
  1727. goto DumpListEnd;
  1728. }
  1729. //
  1730. // Serach through all modules to find the supplied symbol.
  1731. //
  1732. SearchResult.Variety = SymbolResultType;
  1733. Result = DbgpFindSymbol(Context, TypeNameString, &SearchResult);
  1734. if (Result == FALSE) {
  1735. DbgOut("Error: Unknown type name %s\n", TypeNameString);
  1736. goto DumpListEnd;
  1737. }
  1738. //
  1739. // Validate that the given symbol is a structure. It must at least be a
  1740. // type.
  1741. //
  1742. if (SearchResult.Variety != SymbolResultType) {
  1743. DbgOut("Error: %s is not a structure.\n", TypeNameString);
  1744. goto DumpListEnd;
  1745. }
  1746. //
  1747. // If the symbol is a relation type, then test to see if it resolves to a
  1748. // structure type.
  1749. //
  1750. if (SearchResult.U.TypeResult->Type == DataTypeRelation) {
  1751. ResolvedType = DbgSkipTypedefs(SearchResult.U.TypeResult);
  1752. if ((ResolvedType == NULL) ||
  1753. (ResolvedType->Type != DataTypeStructure)) {
  1754. DbgOut("Error: %s could not be resolved as a structure.\n",
  1755. TypeNameString);
  1756. goto DumpListEnd;
  1757. }
  1758. //
  1759. // If the symbol is not a structure type, then this is an error.
  1760. //
  1761. } else if (SearchResult.U.TypeResult->Type != DataTypeStructure) {
  1762. DbgOut("Error: %s is not a structure.\n", TypeNameString);
  1763. goto DumpListEnd;
  1764. } else {
  1765. ResolvedType = SearchResult.U.TypeResult;
  1766. }
  1767. //
  1768. // If the list entry name is not supplied, assume the field is called
  1769. // "ListEntry".
  1770. //
  1771. ListEntryName = "ListEntry";
  1772. if (ArgumentCount > 3) {
  1773. ListEntryName = Arguments[3];
  1774. }
  1775. //
  1776. // Get the offset and size of the list entry field.
  1777. //
  1778. Status = DbgGetMemberOffset(ResolvedType,
  1779. ListEntryName,
  1780. &FieldOffset,
  1781. &FieldSize);
  1782. if (Status != 0) {
  1783. DbgOut("Error: Unknown structure member %s\n", ListEntryName);
  1784. goto DumpListEnd;
  1785. }
  1786. if ((FieldOffset % BITS_PER_BYTE) != 0) {
  1787. DbgOut("Error: Structure member %s is not byte align\n", ListEntryName);
  1788. goto DumpListEnd;
  1789. }
  1790. //
  1791. // Read the Next and Previous pointers from the list head.
  1792. //
  1793. PointerSize = DbgGetTargetPointerSize(Context);
  1794. ListEntrySize = PointerSize * 2;
  1795. Status = DbgReadMemory(Context,
  1796. TRUE,
  1797. ListHeadAddress,
  1798. ListEntrySize,
  1799. ListEntry,
  1800. &BytesRead);
  1801. if ((Status != 0) || (BytesRead != ListEntrySize)) {
  1802. if (Status == 0) {
  1803. Status = EINVAL;
  1804. }
  1805. DbgOut("Error: Unable to read data at address 0x%I64x\n",
  1806. ListHeadAddress);
  1807. goto DumpListEnd;
  1808. }
  1809. //
  1810. // If the target's pointer size is 32-bits modify the ListEntry array to
  1811. // hold a list pointer in each index.
  1812. //
  1813. if (PointerSize == sizeof(ULONG)) {
  1814. ListEntry[1] = ListEntry[0] >> (sizeof(ULONG) * BITS_PER_BYTE);
  1815. ListEntry[0] &= MAX_ULONG;
  1816. }
  1817. //
  1818. // If the list is empty validate the Previous pointer and exit.
  1819. //
  1820. if (ListEntry[0] == ListHeadAddress) {
  1821. DbgOut("Empty List\n");
  1822. if (ListEntry[1] != ListHeadAddress) {
  1823. DbgOut("Error: Corrupted empty list head Previous.\n"
  1824. "\tExpected Value: 0x%I64x\n"
  1825. "\tActual Value: 0x%I64x\n",
  1826. ListHeadAddress,
  1827. ListEntry[1]);
  1828. }
  1829. goto DumpListEnd;
  1830. }
  1831. //
  1832. // Get the given data structure's size and allocate a buffer for reading
  1833. // each structure entry in the list.
  1834. //
  1835. StructureData = &(ResolvedType->U.Structure);
  1836. StructureSize = StructureData->SizeInBytes;
  1837. StructureBuffer = malloc(StructureSize);
  1838. if (StructureBuffer == NULL) {
  1839. DbgOut("Error: Failed to allocate %d bytes\n", StructureSize);
  1840. goto DumpListEnd;
  1841. }
  1842. //
  1843. // Loop through the list, printing each element.
  1844. //
  1845. Count = 0;
  1846. CurrentAddress = ListEntry[0];
  1847. PreviousAddress = ListHeadAddress;
  1848. while (CurrentAddress != ListHeadAddress) {
  1849. if (CurrentAddress == (ULONG)NULL) {
  1850. DbgOut("Error: Found NULL list entry Next pointer\n");
  1851. break;
  1852. }
  1853. //
  1854. // Calculate the structure's base pointer and read it from memory.
  1855. //
  1856. StructureAddress = CurrentAddress - (FieldOffset / BITS_PER_BYTE);
  1857. Status = DbgReadMemory(Context,
  1858. TRUE,
  1859. StructureAddress,
  1860. StructureSize,
  1861. StructureBuffer,
  1862. &BytesRead);
  1863. if ((Status != 0) || (BytesRead != StructureSize)) {
  1864. if (Status == 0) {
  1865. Status = EINVAL;
  1866. }
  1867. DbgOut("Error: Unable to read %d bytes at address 0x%I64x\n",
  1868. StructureSize,
  1869. StructureAddress);
  1870. goto DumpListEnd;
  1871. }
  1872. //
  1873. // Print the structure's contents.
  1874. //
  1875. DbgOut("----------------------------------------\n");
  1876. DbgOut("List Entry %d at address 0x%I64x\n", Count, StructureAddress);
  1877. DbgOut("----------------------------------------\n");
  1878. DbgPrintType(Context,
  1879. ResolvedType,
  1880. StructureBuffer,
  1881. StructureSize,
  1882. 1,
  1883. DEFAULT_RECURSION_DEPTH);
  1884. DbgOut("\n");
  1885. //
  1886. // Read the current structure's list entry data.
  1887. //
  1888. Status = DbgReadMemory(Context,
  1889. TRUE,
  1890. CurrentAddress,
  1891. ListEntrySize,
  1892. ListEntry,
  1893. &BytesRead);
  1894. if ((Status != 0) || (BytesRead != ListEntrySize)) {
  1895. if (Status == 0) {
  1896. Status = EINVAL;
  1897. }
  1898. Status = Status;
  1899. DbgOut("Error: Unable to read data at address 0x%I64x\n",
  1900. CurrentAddress);
  1901. goto DumpListEnd;
  1902. }
  1903. //
  1904. // Perform the same pointer magic as we did above for the head.
  1905. //
  1906. if (PointerSize == sizeof(ULONG)) {
  1907. ListEntry[1] = ListEntry[0] >> (sizeof(ULONG) * BITS_PER_BYTE);
  1908. ListEntry[0] &= MAX_ULONG;
  1909. }
  1910. //
  1911. // Validate that the current list entry's Previous field points to the
  1912. // previous element in the list.
  1913. //
  1914. if (PreviousAddress != ListEntry[1]) {
  1915. DbgOut("Error: Corrupted previous pointer:\n"
  1916. "\tExpected Value: 0x%I64x\n"
  1917. "\tActual Value: 0x%I64x\n",
  1918. PreviousAddress,
  1919. ListEntry[1]);
  1920. goto DumpListEnd;
  1921. }
  1922. PreviousAddress = CurrentAddress;
  1923. CurrentAddress = ListEntry[0];
  1924. Count += 1;
  1925. }
  1926. Status = 0;
  1927. DumpListEnd:
  1928. return Status;
  1929. }
  1930. INT
  1931. DbgrEditMemory (
  1932. PDEBUGGER_CONTEXT Context,
  1933. PSTR *Arguments,
  1934. ULONG ArgumentCount
  1935. )
  1936. /*++
  1937. Routine Description:
  1938. This routine writes to the target memory space.
  1939. Arguments:
  1940. Context - Supplies a pointer to the application context.
  1941. Arguments - Supplies an array of strings containing the arguments. The
  1942. first argument is the command itself.
  1943. ArgumentCount - Supplies the count of arguments. This is always at least
  1944. one.
  1945. Return Value:
  1946. 0 on success.
  1947. Returns an error code on failure.
  1948. --*/
  1949. {
  1950. ULONGLONG Address;
  1951. PSTR Argument;
  1952. ULONG ArgumentIndex;
  1953. ULONG BufferSize;
  1954. ULONG BytesWritten;
  1955. PVOID CurrentValue;
  1956. PVOID DataBuffer;
  1957. PSTR MemoryType;
  1958. INT Status;
  1959. ULONG TypeSize;
  1960. ULONGLONG Value;
  1961. BOOL VirtualAddress;
  1962. Address = 0;
  1963. DataBuffer = NULL;
  1964. MemoryType = Arguments[0];
  1965. VirtualAddress = TRUE;
  1966. //
  1967. // Get the type size.
  1968. //
  1969. if (strcasecmp(MemoryType, "eb") == 0) {
  1970. TypeSize = 1;
  1971. } else if (strcasecmp(MemoryType, "ew") == 0) {
  1972. TypeSize = 2;
  1973. } else if (strcasecmp(MemoryType, "ed") == 0) {
  1974. TypeSize = 4;
  1975. } else if (strcasecmp(MemoryType, "eq") == 0) {
  1976. TypeSize = 8;
  1977. } else {
  1978. DbgOut("Error: unrecognized command. Valid edit commands are eb "
  1979. "(byte), ew (word), ed (double-word), and eq (quad-word).\n");
  1980. Status = EINVAL;
  1981. goto DebuggerEditMemoryEnd;
  1982. }
  1983. //
  1984. // Go through the argument options.
  1985. //
  1986. for (ArgumentIndex = 1; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  1987. Argument = Arguments[ArgumentIndex];
  1988. assert(Argument != NULL);
  1989. //
  1990. // 'p' specifies physical addressing.
  1991. //
  1992. if ((Argument[0] == 'p') && (Argument[1] == '\0')) {
  1993. VirtualAddress = FALSE;
  1994. continue;
  1995. }
  1996. break;
  1997. }
  1998. //
  1999. // The next argument is the address to edit.
  2000. //
  2001. if (ArgumentIndex == ArgumentCount) {
  2002. DbgOut("Error: Not enough arguments.\n");
  2003. Status = EINVAL;
  2004. goto DebuggerEditMemoryEnd;
  2005. }
  2006. Status = DbgEvaluate(Context, Arguments[ArgumentIndex], &Address);
  2007. if (Status != 0) {
  2008. DbgOut("Error: unable to parse address \"%s\".\n",
  2009. Arguments[ArgumentIndex]);
  2010. goto DebuggerEditMemoryEnd;
  2011. }
  2012. ArgumentIndex += 1;
  2013. if (ArgumentIndex == ArgumentCount) {
  2014. DbgOut("Error: Not enough arguments!\n");
  2015. Status = EINVAL;
  2016. goto DebuggerEditMemoryEnd;
  2017. }
  2018. //
  2019. // All other arguments are values to write, sequentially. Start by
  2020. // allocating space for the data to be written.
  2021. //
  2022. BufferSize = (ArgumentCount - ArgumentIndex) * TypeSize;
  2023. DataBuffer = malloc(BufferSize);
  2024. if (DataBuffer == NULL) {
  2025. DbgOut("Error: Unable to allocate %d bytes.\n", BufferSize);
  2026. Status = ENOMEM;
  2027. goto DebuggerEditMemoryEnd;
  2028. }
  2029. CurrentValue = DataBuffer;
  2030. for (NOTHING; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  2031. Status = DbgEvaluate(Context, Arguments[ArgumentIndex], &Value);
  2032. if (Status != 0) {
  2033. DbgOut("Error: Unable to parse value \"%s\".\n",
  2034. Arguments[ArgumentIndex]);
  2035. goto DebuggerEditMemoryEnd;
  2036. }
  2037. memcpy(CurrentValue, &Value, TypeSize);
  2038. CurrentValue += TypeSize;
  2039. }
  2040. //
  2041. // Attempt to write the values to memory.
  2042. //
  2043. Status = DbgWriteMemory(Context,
  2044. VirtualAddress,
  2045. Address,
  2046. BufferSize,
  2047. DataBuffer,
  2048. &BytesWritten);
  2049. if (Status != 0) {
  2050. goto DebuggerEditMemoryEnd;
  2051. }
  2052. if (BytesWritten != BufferSize) {
  2053. DbgOut("Only %d of %d bytes written.\n", BytesWritten, BufferSize);
  2054. }
  2055. Context->LastMemoryDump.NextAddress = Address;
  2056. Context->LastMemoryDump.Virtual = VirtualAddress;
  2057. Status = 0;
  2058. DebuggerEditMemoryEnd:
  2059. if (DataBuffer != NULL) {
  2060. free(DataBuffer);
  2061. }
  2062. return Status;
  2063. }
  2064. INT
  2065. DbgrEvaluate (
  2066. PDEBUGGER_CONTEXT Context,
  2067. PSTR *Arguments,
  2068. ULONG ArgumentCount
  2069. )
  2070. /*++
  2071. Routine Description:
  2072. This routine evaluates a numerical expression and prints it out in both
  2073. decimal and hexadecimal.
  2074. Arguments:
  2075. Context - Supplies a pointer to the application context.
  2076. Arguments - Supplies an array of strings containing the arguments. The
  2077. first argument is the command itself.
  2078. ArgumentCount - Supplies the count of arguments. This is always at least
  2079. one.
  2080. Return Value:
  2081. 0 on success.
  2082. Returns an error code on failure.
  2083. --*/
  2084. {
  2085. ULONGLONG Result;
  2086. BOOL Status;
  2087. if (ArgumentCount < 2) {
  2088. DbgOut("Usage: %s <expr>.\nExpressions can be numeric (3+4) or \n"
  2089. "symbolic (DbgSymbolTable+(0x10*4)).\n",
  2090. Arguments[0]);
  2091. return EINVAL;
  2092. }
  2093. Status = DbgEvaluate(Context, Arguments[1], &Result);
  2094. if (Status != 0) {
  2095. DbgOut("Syntax error in expression.\n");
  2096. goto EvaluateEnd;
  2097. }
  2098. DbgOut(" 0x%I64x = %I64d\n", Result, Result);
  2099. Status = 0;
  2100. EvaluateEnd:
  2101. return Status;
  2102. }
  2103. INT
  2104. DbgrPrintLocals (
  2105. PDEBUGGER_CONTEXT Context,
  2106. PSTR *Arguments,
  2107. ULONG ArgumentCount
  2108. )
  2109. /*++
  2110. Routine Description:
  2111. This routine prints the values of the local variables inside the currently
  2112. selected stack frame.
  2113. Arguments:
  2114. Context - Supplies a pointer to the application context.
  2115. Arguments - Supplies an array of strings containing the arguments. The
  2116. first argument is the command itself.
  2117. ArgumentCount - Supplies the count of arguments. This is always at least
  2118. one.
  2119. Return Value:
  2120. 0 on success.
  2121. Returns an error code on failure.
  2122. --*/
  2123. {
  2124. PDATA_SYMBOL BestLocal;
  2125. PDATA_SYMBOL CurrentLocal;
  2126. PLIST_ENTRY CurrentLocalEntry;
  2127. PFUNCTION_SYMBOL Function;
  2128. ULONGLONG InstructionPointer;
  2129. PDEBUGGER_MODULE Module;
  2130. BOOL ParameterPrinted;
  2131. PSYMBOL_SEARCH_RESULT ResultValid;
  2132. SYMBOL_SEARCH_RESULT SearchResult;
  2133. INT Status;
  2134. //
  2135. // Attempt to get the module this address is in. If one cannot be found,
  2136. // then there is no useful information to print, so exit.
  2137. //
  2138. InstructionPointer = DbgGetPc(Context, &(Context->FrameRegisters));
  2139. Module = DbgpFindModuleFromAddress(Context,
  2140. InstructionPointer,
  2141. &InstructionPointer);
  2142. if (Module == NULL) {
  2143. DbgOut("Error: Execution is not in any module!\n");
  2144. Status = ENOENT;
  2145. goto PrintLocalsEnd;
  2146. }
  2147. //
  2148. // Attempt to find the current function symbol in the module.
  2149. //
  2150. SearchResult.Variety = SymbolResultInvalid;
  2151. ResultValid = NULL;
  2152. if (Module->Symbols != NULL) {
  2153. ResultValid = DbgFindFunctionSymbol(Module->Symbols,
  2154. NULL,
  2155. InstructionPointer,
  2156. &SearchResult);
  2157. } else {
  2158. DbgOut("Error: Module %s has no symbols loaded for it!\n",
  2159. Module->ModuleName);
  2160. Status = ESRCH;
  2161. goto PrintLocalsEnd;
  2162. }
  2163. //
  2164. // If a function could not be found, bail.
  2165. //
  2166. if ((ResultValid == NULL) ||
  2167. (SearchResult.Variety != SymbolResultFunction)) {
  2168. DbgOut("Error: Function symbol could not be found in module %s!\n",
  2169. Module->ModuleName);
  2170. Status = ENOENT;
  2171. goto PrintLocalsEnd;
  2172. }
  2173. Function = SearchResult.U.FunctionResult;
  2174. //
  2175. // Print all function parameters.
  2176. //
  2177. ParameterPrinted = FALSE;
  2178. CurrentLocalEntry = Function->ParametersHead.Next;
  2179. while (CurrentLocalEntry != &(Function->ParametersHead)) {
  2180. CurrentLocal = LIST_VALUE(CurrentLocalEntry, DATA_SYMBOL, ListEntry);
  2181. CurrentLocalEntry = CurrentLocalEntry->Next;
  2182. Status = DbgPrintDataSymbol(Context,
  2183. Module->Symbols,
  2184. CurrentLocal,
  2185. InstructionPointer,
  2186. 4,
  2187. DEFAULT_RECURSION_DEPTH);
  2188. if (Status != ENOENT) {
  2189. if (Status == 0) {
  2190. ParameterPrinted = TRUE;
  2191. }
  2192. DbgOut("\n");
  2193. }
  2194. }
  2195. if (ParameterPrinted != FALSE) {
  2196. DbgOut("\n");
  2197. }
  2198. //
  2199. // Loop through every local in the function.
  2200. //
  2201. CurrentLocalEntry = Function->LocalsHead.Next;
  2202. while (CurrentLocalEntry != &(Function->LocalsHead)) {
  2203. CurrentLocal = LIST_VALUE(CurrentLocalEntry, DATA_SYMBOL, ListEntry);
  2204. CurrentLocalEntry = CurrentLocalEntry->Next;
  2205. if (CurrentLocal->MinimumValidExecutionAddress != 0) {
  2206. //
  2207. // Skip this local if it's not yet valid.
  2208. //
  2209. if (InstructionPointer <
  2210. CurrentLocal->MinimumValidExecutionAddress) {
  2211. continue;
  2212. }
  2213. //
  2214. // Attempt to find the most updated version of this local. Skip
  2215. // this one if a different local is determined to be the most up to
  2216. // date.
  2217. //
  2218. BestLocal = DbgpGetLocal(Function,
  2219. CurrentLocal->Name,
  2220. InstructionPointer);
  2221. //
  2222. // The function should definitely not fail to find any local, since
  2223. // this function found it.
  2224. //
  2225. assert(BestLocal != NULL);
  2226. if (BestLocal != CurrentLocal) {
  2227. continue;
  2228. }
  2229. }
  2230. //
  2231. // Print out this local.
  2232. //
  2233. Status = DbgPrintDataSymbol(Context,
  2234. Module->Symbols,
  2235. CurrentLocal,
  2236. InstructionPointer,
  2237. 4,
  2238. DEFAULT_RECURSION_DEPTH);
  2239. if (Status != ENOENT) {
  2240. DbgOut("\n");
  2241. }
  2242. }
  2243. Status = 0;
  2244. PrintLocalsEnd:
  2245. return Status;
  2246. }
  2247. INT
  2248. DbgrShowSourceAtAddressCommand (
  2249. PDEBUGGER_CONTEXT Context,
  2250. PSTR *Arguments,
  2251. ULONG ArgumentCount
  2252. )
  2253. /*++
  2254. Routine Description:
  2255. This routine shows the source file for the provided address and highlights
  2256. the specific line associated with the address.
  2257. Arguments:
  2258. Context - Supplies a pointer to the application context.
  2259. Arguments - Supplies an array of strings containing the arguments. The
  2260. first argument is the command itself.
  2261. ArgumentCount - Supplies the count of arguments. This is always at least
  2262. one.
  2263. Return Value:
  2264. 0 on success.
  2265. Returns an error code on failure.
  2266. --*/
  2267. {
  2268. ULONGLONG Address;
  2269. PSTR AddressString;
  2270. INT Result;
  2271. if (ArgumentCount != 2) {
  2272. DbgOut("Usage: so <address>.\nThis command displays the current "
  2273. "source file and line for the given address.\n");
  2274. return EINVAL;
  2275. }
  2276. AddressString = Arguments[1];
  2277. Result = DbgEvaluate(Context, AddressString, &Address);
  2278. if (Result != 0) {
  2279. DbgOut("Error: Unable to parse address %s.\n", Address);
  2280. goto ShowSourceAtAddressEnd;
  2281. }
  2282. DbgrShowSourceAtAddress(Context, Address);
  2283. Result = 0;
  2284. ShowSourceAtAddressEnd:
  2285. return Result;
  2286. }
  2287. VOID
  2288. DbgrUnhighlightCurrentLine (
  2289. PDEBUGGER_CONTEXT Context
  2290. )
  2291. /*++
  2292. Routine Description:
  2293. This routine restores the currently executing line to the normal background
  2294. color in the source window.
  2295. Arguments:
  2296. Context - Supplies a pointer to the application context.
  2297. Return Value:
  2298. None.
  2299. --*/
  2300. {
  2301. //
  2302. // Remove the highlight on the previous line.
  2303. //
  2304. DbgrpHighlightExecutingLine(Context, 0);
  2305. return;
  2306. }
  2307. INT
  2308. DbgrListBreakPoints (
  2309. PDEBUGGER_CONTEXT Context,
  2310. PSTR *Arguments,
  2311. ULONG ArgumentCount
  2312. )
  2313. /*++
  2314. Routine Description:
  2315. This routine lists all valid breakpoints in the target.
  2316. Arguments:
  2317. Context - Supplies a pointer to the application context.
  2318. Arguments - Supplies an array of strings containing the arguments. The
  2319. first argument is the command itself.
  2320. ArgumentCount - Supplies the count of arguments. This is always at least
  2321. one.
  2322. Return Value:
  2323. 0 on success.
  2324. Returns an error code on failure.
  2325. --*/
  2326. {
  2327. PDEBUGGER_BREAK_POINT Breakpoint;
  2328. PLIST_ENTRY CurrentEntry;
  2329. INT Status;
  2330. DbgOut("Breakpoints: \n");
  2331. if (LIST_EMPTY(&(Context->BreakpointList)) != FALSE) {
  2332. DbgOut("(None)\n");
  2333. return 0;
  2334. }
  2335. //
  2336. // Loop and print every breakpoint.
  2337. //
  2338. CurrentEntry = Context->BreakpointList.Next;
  2339. while (CurrentEntry != &(Context->BreakpointList)) {
  2340. Breakpoint = LIST_VALUE(CurrentEntry, DEBUGGER_BREAK_POINT, ListEntry);
  2341. //
  2342. // Check that this is a valid entry.
  2343. //
  2344. if (Breakpoint->Type == BreakpointTypeInvalid) {
  2345. DbgOut("Error: Invalid breakpoint type!\n");
  2346. Status = EINVAL;
  2347. goto ListBreakPointsEnd;
  2348. }
  2349. //
  2350. // Print the breakpoint index and whether or not the breakpoint is
  2351. // disabled.
  2352. //
  2353. DbgOut("%d: ", Breakpoint->Index);
  2354. if (Breakpoint->Enabled == FALSE) {
  2355. DbgOut("(Disabled) ");
  2356. }
  2357. //
  2358. // Print the breakpoint address, with symbol information if possible.
  2359. //
  2360. DbgOut("%08I64x ", Breakpoint->Address);
  2361. Status = DbgPrintAddressSymbol(Context, Breakpoint->Address);
  2362. if (Status == 0) {
  2363. DbgOut(" ");
  2364. }
  2365. //
  2366. // If it's a break on access, print out the access type and size.
  2367. //
  2368. if (Breakpoint->Type == BreakpointTypeRead) {
  2369. DbgOut("Read ");
  2370. } else if (Breakpoint->Type == BreakpointTypeWrite) {
  2371. DbgOut("Write ");
  2372. } else if (Breakpoint->Type == BreakpointTypeReadWrite) {
  2373. DbgOut("Read/Write ");
  2374. }
  2375. if ((Breakpoint->Type == BreakpointTypeRead) ||
  2376. (Breakpoint->Type == BreakpointTypeWrite) ||
  2377. (Breakpoint->Type == BreakpointTypeReadWrite)) {
  2378. DbgOut("%d Bytes", Breakpoint->AccessSize);
  2379. }
  2380. //
  2381. // Advance to the next breakpoint.
  2382. //
  2383. DbgOut("\n");
  2384. CurrentEntry = CurrentEntry->Next;
  2385. }
  2386. Status = 0;
  2387. ListBreakPointsEnd:
  2388. return Status;
  2389. }
  2390. INT
  2391. DbgrEnableBreakPoint (
  2392. PDEBUGGER_CONTEXT Context,
  2393. PSTR *Arguments,
  2394. ULONG ArgumentCount
  2395. )
  2396. /*++
  2397. Routine Description:
  2398. This routine lists all valid breakpoints in the target.
  2399. Arguments:
  2400. Context - Supplies a pointer to the application context.
  2401. Arguments - Supplies an array of strings containing the arguments. The
  2402. first argument is the command itself.
  2403. ArgumentCount - Supplies the count of arguments. This is always at least
  2404. one.
  2405. Return Value:
  2406. 0 on success.
  2407. Returns an error code on failure.
  2408. --*/
  2409. {
  2410. PSTR AfterScan;
  2411. BOOL Enable;
  2412. LONG Number;
  2413. PSTR NumberString;
  2414. INT Status;
  2415. if (ArgumentCount < 2) {
  2416. DbgOut("Usage: %s <N>\nEnable or disable the break point with the "
  2417. "given number N. Use bl to list all breakpoints.\n",
  2418. Arguments[0]);
  2419. Status = EINVAL;
  2420. goto EnableBreakPointEnd;
  2421. }
  2422. Enable = FALSE;
  2423. if (strcasecmp(Arguments[0], "be") == 0) {
  2424. Enable = TRUE;
  2425. } else {
  2426. assert(strcasecmp(Arguments[0], "bd") == 0);
  2427. }
  2428. NumberString = Arguments[1];
  2429. //
  2430. // A star specifies all breakpoints.
  2431. //
  2432. if (strcmp(NumberString, "*") == 0) {
  2433. Number = -1;
  2434. } else {
  2435. Number = strtol(NumberString, &AfterScan, 0);
  2436. if (AfterScan == NumberString) {
  2437. DbgOut("Failed to convert '%s' into a number.\n", NumberString);
  2438. Status = EINVAL;
  2439. goto EnableBreakPointEnd;
  2440. }
  2441. }
  2442. Status = DbgrpEnableBreakPoint(Context, Number, Enable);
  2443. if (Status != 0) {
  2444. goto EnableBreakPointEnd;
  2445. }
  2446. EnableBreakPointEnd:
  2447. return Status;
  2448. }
  2449. INT
  2450. DbgrDeleteBreakPoint (
  2451. PDEBUGGER_CONTEXT Context,
  2452. PSTR *Arguments,
  2453. ULONG ArgumentCount
  2454. )
  2455. /*++
  2456. Routine Description:
  2457. This routine deletes a breakpoint from the target.
  2458. Arguments:
  2459. Context - Supplies a pointer to the application context.
  2460. Arguments - Supplies an array of strings containing the arguments. The
  2461. first argument is the command itself.
  2462. ArgumentCount - Supplies the count of arguments. This is always at least
  2463. one.
  2464. Return Value:
  2465. 0 on success.
  2466. Returns an error code on failure.
  2467. --*/
  2468. {
  2469. PSTR AfterScan;
  2470. PDEBUGGER_BREAK_POINT Breakpoint;
  2471. PLIST_ENTRY CurrentEntry;
  2472. BOOL Found;
  2473. LONG Number;
  2474. PSTR NumberString;
  2475. INT Status;
  2476. if (ArgumentCount < 2) {
  2477. DbgOut("Usage: %s <N>\nDelete a breakpoint with the given number N. "
  2478. "Use * for all breakpoints. Use bl to list all breakpoints.",
  2479. Arguments[0]);
  2480. Status = EINVAL;
  2481. goto DeleteBreakPointEnd;
  2482. }
  2483. NumberString = Arguments[1];
  2484. //
  2485. // A star specifies all breakpoints.
  2486. //
  2487. if (strcmp(NumberString, "*") == 0) {
  2488. Number = -1;
  2489. } else {
  2490. Number = strtol(NumberString, &AfterScan, 0);
  2491. if (AfterScan == NumberString) {
  2492. DbgOut("Failed to convert '%s' into a number.\n", NumberString);
  2493. Status = EINVAL;
  2494. goto DeleteBreakPointEnd;
  2495. }
  2496. }
  2497. //
  2498. // Loop through looking for the breakpoint in the list.
  2499. //
  2500. Found = FALSE;
  2501. CurrentEntry = Context->BreakpointList.Next;
  2502. while (CurrentEntry != &(Context->BreakpointList)) {
  2503. Breakpoint = LIST_VALUE(CurrentEntry, DEBUGGER_BREAK_POINT, ListEntry);
  2504. CurrentEntry = CurrentEntry->Next;
  2505. if ((Breakpoint->Index == Number) || (Number == -1)) {
  2506. Found = TRUE;
  2507. if (Context->BreakpointToRestore == Breakpoint) {
  2508. Context->BreakpointToRestore = NULL;
  2509. }
  2510. if (Breakpoint->Enabled != FALSE) {
  2511. DbgrpClearBreakpointAtAddress(Context,
  2512. Breakpoint->Address,
  2513. Breakpoint->OriginalValue);
  2514. }
  2515. LIST_REMOVE(&(Breakpoint->ListEntry));
  2516. free(Breakpoint);
  2517. if (Number != -1) {
  2518. break;
  2519. }
  2520. }
  2521. }
  2522. if (Found == FALSE) {
  2523. DbgOut("Breakpoint %d not found.\n", Number);
  2524. Status = ESRCH;
  2525. goto DeleteBreakPointEnd;
  2526. }
  2527. Status = 0;
  2528. DeleteBreakPointEnd:
  2529. return Status;
  2530. }
  2531. INT
  2532. DbgrCreateBreakPoint (
  2533. PDEBUGGER_CONTEXT Context,
  2534. PSTR *Arguments,
  2535. ULONG ArgumentCount
  2536. )
  2537. /*++
  2538. Routine Description:
  2539. This routine creates a new breakpoint in the debuggee.
  2540. Arguments:
  2541. Context - Supplies a pointer to the application context.
  2542. Arguments - Supplies an array of strings containing the arguments. The
  2543. first argument is the command itself.
  2544. ArgumentCount - Supplies the count of arguments. This is always at least
  2545. one.
  2546. Return Value:
  2547. 0 on success.
  2548. Returns an error code on failure.
  2549. --*/
  2550. {
  2551. PSTR AccessType;
  2552. PDEBUGGER_BREAK_POINT Breakpoint;
  2553. PSTR BreakPointAddress;
  2554. PDEBUGGER_BREAK_POINT BreakpointAfter;
  2555. PDEBUGGER_BREAK_POINT CurrentBreakpoint;
  2556. PLIST_ENTRY CurrentEntry;
  2557. LONG Index;
  2558. INT Status;
  2559. AccessType = NULL;
  2560. Breakpoint = NULL;
  2561. if ((ArgumentCount <= 1) || (ArgumentCount > 3)) {
  2562. DbgOut("Usage: bp [<access>] <address>.\n"
  2563. "Set a new breakpoint. The access takes the form "
  2564. "<type><width>, where type is 'r' for read, 'w' for write, or "
  2565. "'x' for execute, and width is 1, 2, 4, or 8. The address is "
  2566. "where to set the breakpoint.\n"
  2567. "Example: \"bp w2 0x1004\" -- Breaks in when a two-byte write "
  2568. "occurs to address 0x1004. If no access type is specified, a "
  2569. "regular software execution breakpoint is created.\n");
  2570. Status = EINVAL;
  2571. goto CreateBreakPointEnd;
  2572. }
  2573. if (ArgumentCount > 2) {
  2574. AccessType = Arguments[1];
  2575. BreakPointAddress = Arguments[2];
  2576. } else {
  2577. assert(ArgumentCount == 2);
  2578. BreakPointAddress = Arguments[1];
  2579. }
  2580. Breakpoint = malloc(sizeof(DEBUGGER_BREAK_POINT));
  2581. if (Breakpoint == NULL) {
  2582. DbgOut("Error: Failed to allocate space for a breakpoint.\n");
  2583. Status = ENOMEM;
  2584. goto CreateBreakPointEnd;
  2585. }
  2586. RtlZeroMemory(Breakpoint, sizeof(DEBUGGER_BREAK_POINT));
  2587. //
  2588. // Parse the access type.
  2589. //
  2590. if (AccessType != NULL) {
  2591. //
  2592. // It's a break on read or break on read/write.
  2593. //
  2594. if (*AccessType == 'r') {
  2595. AccessType += 1;
  2596. if (*AccessType == 'w') {
  2597. AccessType += 1;
  2598. Breakpoint->Type = BreakpointTypeReadWrite;
  2599. } else {
  2600. Breakpoint->Type = BreakpointTypeRead;
  2601. }
  2602. //
  2603. // It's a break on write.
  2604. //
  2605. } else if (*AccessType == 'w') {
  2606. AccessType += 1;
  2607. Breakpoint->Type = BreakpointTypeWrite;
  2608. //
  2609. // It's an invalid specification.
  2610. //
  2611. } else {
  2612. DbgOut("Error: Invalid access type specified. Valid values are "
  2613. "r, w, and rw, but not %c.\n",
  2614. *AccessType);
  2615. Status = EINVAL;
  2616. goto CreateBreakPointEnd;
  2617. }
  2618. //
  2619. // Get the access size.
  2620. //
  2621. Breakpoint->AccessSize = strtoul(AccessType, NULL, 10);
  2622. //
  2623. // Check the validity of the result.
  2624. //
  2625. if ((Breakpoint->AccessSize != 1) &&
  2626. (Breakpoint->AccessSize != 2) &&
  2627. (Breakpoint->AccessSize != 4) &&
  2628. (Breakpoint->AccessSize != 8) &&
  2629. (Breakpoint->AccessSize != 16)) {
  2630. DbgOut("Error: Invalid access size specified. Valid values are "
  2631. "1, 2, 4, 8, and 16.\n");
  2632. Status = EINVAL;
  2633. goto CreateBreakPointEnd;
  2634. }
  2635. //
  2636. // The access type parameter was NULL, so this must be a standard execution
  2637. // breakpoint.
  2638. //
  2639. } else {
  2640. Breakpoint->Type = BreakpointTypeExecution;
  2641. }
  2642. //
  2643. // Parse the address parameter.
  2644. //
  2645. Status = DbgEvaluate(Context, BreakPointAddress, &(Breakpoint->Address));
  2646. if (Status != 0) {
  2647. DbgOut("Error: Unable to parse breakpoint address.\n");
  2648. goto CreateBreakPointEnd;
  2649. }
  2650. //
  2651. // TODO: Enable hardware breakpoints.
  2652. //
  2653. if (Breakpoint->Type != BreakpointTypeExecution) {
  2654. DbgOut("Error: Break on access is currently not implemented.\n");
  2655. Status = ENOSYS;
  2656. goto CreateBreakPointEnd;
  2657. }
  2658. //
  2659. // Loop through once and ensure there's not the same breakpoint already in
  2660. // there (for software breakpoints only).
  2661. //
  2662. if (Breakpoint->Type == BreakpointTypeExecution) {
  2663. CurrentEntry = Context->BreakpointList.Next;
  2664. Index = 0;
  2665. while (CurrentEntry != &(Context->BreakpointList)) {
  2666. CurrentBreakpoint = LIST_VALUE(CurrentEntry,
  2667. DEBUGGER_BREAK_POINT,
  2668. ListEntry);
  2669. CurrentEntry = CurrentEntry->Next;
  2670. if ((CurrentBreakpoint->Type == Breakpoint->Type) &&
  2671. (CurrentBreakpoint->Address == Breakpoint->Address)) {
  2672. //
  2673. // If the existing breakpoint is currently disabled, enable it.
  2674. //
  2675. if (CurrentBreakpoint->Enabled == FALSE) {
  2676. Status = DbgrpEnableBreakPoint(Context,
  2677. CurrentBreakpoint->Index,
  2678. TRUE);
  2679. if (Status != 0) {
  2680. DbgOut("Error: Failed to re-enable existing breakpoint "
  2681. "%d at %I64x.\n",
  2682. CurrentBreakpoint->Index,
  2683. CurrentBreakpoint->Address);
  2684. goto CreateBreakPointEnd;
  2685. }
  2686. }
  2687. Status = 0;
  2688. goto CreateBreakPointEnd;
  2689. }
  2690. }
  2691. }
  2692. //
  2693. // Find an index and location in the list for this breakpoint. The list is
  2694. // always in sorted order by index.
  2695. //
  2696. BreakpointAfter = NULL;
  2697. CurrentEntry = Context->BreakpointList.Next;
  2698. Index = 0;
  2699. while (CurrentEntry != &(Context->BreakpointList)) {
  2700. BreakpointAfter = LIST_VALUE(CurrentEntry,
  2701. DEBUGGER_BREAK_POINT,
  2702. ListEntry);
  2703. //
  2704. // If the entry here is bigger than the index, then a free slot was
  2705. // found.
  2706. //
  2707. if (BreakpointAfter->Index > Index) {
  2708. break;
  2709. }
  2710. //
  2711. // The index must be equal to this entrie's index. Move up to the next
  2712. // slot.
  2713. //
  2714. Index += 1;
  2715. CurrentEntry = CurrentEntry->Next;
  2716. }
  2717. //
  2718. // If the list is empty or entirely in order, then just put this one at
  2719. // the back of the list.
  2720. //
  2721. Breakpoint->Index = Index;
  2722. if (CurrentEntry == &(Context->BreakpointList)) {
  2723. INSERT_BEFORE(&(Breakpoint->ListEntry), &(Context->BreakpointList));
  2724. } else {
  2725. INSERT_BEFORE(&(Breakpoint->ListEntry), &(BreakpointAfter->ListEntry));
  2726. }
  2727. Breakpoint->Enabled = FALSE;
  2728. DbgrpEnableBreakPoint(Context, Breakpoint->Index, TRUE);
  2729. Breakpoint = NULL;
  2730. Status = 0;
  2731. CreateBreakPointEnd:
  2732. if (Breakpoint != NULL) {
  2733. free(Breakpoint);
  2734. }
  2735. return Status;
  2736. }
  2737. INT
  2738. DbgrStep (
  2739. PDEBUGGER_CONTEXT Context,
  2740. PSTR *Arguments,
  2741. ULONG ArgumentCount
  2742. )
  2743. /*++
  2744. Routine Description:
  2745. This routine performs a source or assembly line step in the debugger.
  2746. Arguments:
  2747. Context - Supplies a pointer to the application context.
  2748. Arguments - Supplies an array of strings containing the arguments. The
  2749. first argument is the command itself.
  2750. ArgumentCount - Supplies the count of arguments. This is always at least
  2751. one.
  2752. Return Value:
  2753. 0 on success.
  2754. Returns an error code on failure.
  2755. --*/
  2756. {
  2757. ULONGLONG BaseDifference;
  2758. PFUNCTION_SYMBOL CurrentFunction;
  2759. PDEBUGGER_MODULE CurrentModule;
  2760. PSOURCE_FILE_SYMBOL CurrentSource;
  2761. ULONGLONG DebasedInstructionPointer;
  2762. ULONGLONG FunctionEndAddress;
  2763. SYMBOL_SEARCH_RESULT FunctionSearch;
  2764. ULONGLONG InstructionPointer;
  2765. ULONGLONG LineEndAddress;
  2766. RANGE_STEP RangeStep;
  2767. INT Result;
  2768. PSYMBOL_SEARCH_RESULT ResultValid;
  2769. PSOURCE_LINE_SYMBOL SourceLine;
  2770. BOOL StepInto;
  2771. BaseDifference = 0;
  2772. CurrentFunction = NULL;
  2773. CurrentSource = NULL;
  2774. FunctionEndAddress = 0;
  2775. InstructionPointer =
  2776. Context->CurrentEvent.BreakNotification.InstructionPointer;
  2777. DebasedInstructionPointer = InstructionPointer;
  2778. SourceLine = NULL;
  2779. StepInto = FALSE;
  2780. if (strcasecmp(Arguments[0], "t") == 0) {
  2781. StepInto = TRUE;
  2782. } else {
  2783. assert(strcasecmp(Arguments[0], "p") == 0);
  2784. }
  2785. //
  2786. // Attempt to get the currently executing source line and function.
  2787. //
  2788. CurrentModule = DbgpFindModuleFromAddress(Context,
  2789. InstructionPointer,
  2790. &DebasedInstructionPointer);
  2791. if (CurrentModule != NULL) {
  2792. BaseDifference = CurrentModule->BaseDifference;
  2793. SourceLine = DbgLookupSourceLine(CurrentModule->Symbols,
  2794. DebasedInstructionPointer);
  2795. if (SourceLine != NULL) {
  2796. CurrentSource = SourceLine->ParentSource;
  2797. }
  2798. FunctionSearch.Variety = SymbolResultInvalid;
  2799. ResultValid = DbgFindFunctionSymbol(CurrentModule->Symbols,
  2800. NULL,
  2801. DebasedInstructionPointer,
  2802. &FunctionSearch);
  2803. if (ResultValid != NULL) {
  2804. assert(FunctionSearch.Variety == SymbolResultFunction);
  2805. CurrentFunction = FunctionSearch.U.FunctionResult;
  2806. }
  2807. }
  2808. //
  2809. // If the source line or current function could not be found, or source
  2810. // stepping is disabled, fall back to stepping over the current instruction.
  2811. //
  2812. if ((SourceLine == NULL) ||
  2813. ((Context->Flags & DEBUGGER_FLAG_SOURCE_LINE_STEPPING) == 0)) {
  2814. //
  2815. // If stepping into, just execute a single step.
  2816. //
  2817. if (StepInto != FALSE) {
  2818. Result = DbgrSingleStep(Context);
  2819. //
  2820. // Attempt to step over one instruction. Symbols will be helpful here.
  2821. // Without them, this basically does a single step.
  2822. //
  2823. } else {
  2824. //
  2825. // Start with a default value that basically represents a single
  2826. // step.
  2827. //
  2828. RangeStep.BreakRangeMinimum = 0;
  2829. RangeStep.BreakRangeMaximum = MAX_ULONGLONG;
  2830. //
  2831. // If there is a current function symbol, then set the range to
  2832. // break anywhere in this function, unless this is the last
  2833. // instruction in the function.
  2834. //
  2835. if (CurrentFunction != NULL) {
  2836. if ((DebasedInstructionPointer +
  2837. Context->BreakInstructionLength) <
  2838. CurrentFunction->EndAddress) {
  2839. RangeStep.BreakRangeMinimum =
  2840. CurrentFunction->StartAddress + BaseDifference;
  2841. RangeStep.BreakRangeMaximum =
  2842. CurrentFunction->EndAddress + BaseDifference;
  2843. }
  2844. //
  2845. // There's not a function symbol, so check to see if there's at
  2846. // least a source symbol. If there is, set the range to break
  2847. // anywhere in this file.
  2848. //
  2849. } else if (CurrentSource != NULL) {
  2850. if ((DebasedInstructionPointer +
  2851. Context->BreakInstructionLength) <
  2852. CurrentSource->EndAddress) {
  2853. RangeStep.BreakRangeMinimum =
  2854. CurrentSource->StartAddress + BaseDifference;
  2855. RangeStep.BreakRangeMaximum =
  2856. CurrentSource->EndAddress + BaseDifference;
  2857. }
  2858. }
  2859. RangeStep.RangeHoleMinimum = InstructionPointer;
  2860. RangeStep.RangeHoleMaximum = InstructionPointer + 1;
  2861. Result = DbgrpRangeStep(Context, &RangeStep);
  2862. }
  2863. goto StepEnd;
  2864. }
  2865. //
  2866. // Set a "range" breakpoint, which essentially puts the debuggee into single
  2867. // step mode. The debuggee will break when it is inside the break range (ie
  2868. // the current function), but not inside the range hole (ie the current
  2869. // source line). Start by getting the addresses of the beginning and end of
  2870. // the source line.
  2871. //
  2872. if ((CurrentFunction == NULL) || (SourceLine == NULL)) {
  2873. LineEndAddress = 0;
  2874. RangeStep.RangeHoleMinimum = 0;
  2875. RangeStep.RangeHoleMaximum = 0;
  2876. } else {
  2877. LineEndAddress = SourceLine->End + BaseDifference;
  2878. RangeStep.RangeHoleMinimum = SourceLine->Start + BaseDifference;
  2879. RangeStep.RangeHoleMaximum = LineEndAddress;
  2880. }
  2881. //
  2882. // If stepping into the source line or this is the last line of the
  2883. // function (ie it's about to return), just set the break range to be the
  2884. // entire address space.
  2885. //
  2886. if (CurrentFunction != NULL) {
  2887. FunctionEndAddress = CurrentFunction->EndAddress + BaseDifference;
  2888. }
  2889. if ((StepInto != FALSE) ||
  2890. (CurrentFunction == NULL) ||
  2891. (LineEndAddress == FunctionEndAddress)) {
  2892. RangeStep.BreakRangeMinimum = 0;
  2893. RangeStep.BreakRangeMaximum = MAX_ULONGLONG;
  2894. //
  2895. // The command was step over and it's not the last line of the function, so
  2896. // only break anywhere in the function.
  2897. //
  2898. } else {
  2899. RangeStep.BreakRangeMinimum =
  2900. CurrentFunction->StartAddress + BaseDifference;
  2901. RangeStep.BreakRangeMaximum = FunctionEndAddress;
  2902. }
  2903. Result = DbgrpRangeStep(Context, &RangeStep);
  2904. StepEnd:
  2905. return Result;
  2906. }
  2907. INT
  2908. DbgrSetSourceStepping (
  2909. PDEBUGGER_CONTEXT Context,
  2910. PSTR *Arguments,
  2911. ULONG ArgumentCount
  2912. )
  2913. /*++
  2914. Routine Description:
  2915. This routine turns source line stepping on or off.
  2916. Arguments:
  2917. Context - Supplies a pointer to the application context.
  2918. Arguments - Supplies an array of strings containing the arguments. The
  2919. first argument is the command itself.
  2920. ArgumentCount - Supplies the count of arguments. This is always at least
  2921. one.
  2922. Return Value:
  2923. 0 on success.
  2924. Returns an error code on failure.
  2925. --*/
  2926. {
  2927. PSTR Argument;
  2928. if (ArgumentCount != 2) {
  2929. DbgOut("Error: Use \"ss on\" or \"ss off\" to enable or disable source "
  2930. "line stepping.\n");
  2931. return EINVAL;
  2932. }
  2933. Argument = Arguments[1];
  2934. if ((strcasecmp(Argument, "on") == 0) ||
  2935. (strcasecmp(Argument, "yes") == 0) ||
  2936. (strcasecmp(Argument, "1") == 0)) {
  2937. Context->Flags |= DEBUGGER_FLAG_SOURCE_LINE_STEPPING;
  2938. }
  2939. if ((strcasecmp(Argument, "off") == 0) ||
  2940. (strcasecmp(Argument, "no") == 0) ||
  2941. (strcasecmp(Argument, "0") == 0)) {
  2942. Context->Flags &= ~DEBUGGER_FLAG_SOURCE_LINE_STEPPING;
  2943. }
  2944. if ((Context->Flags & DEBUGGER_FLAG_SOURCE_LINE_STEPPING) != 0) {
  2945. DbgOut("Stepping by source line is now enabled.\n");
  2946. } else {
  2947. DbgOut("Stepping by source line is now disabled.\n");
  2948. }
  2949. return 0;
  2950. }
  2951. INT
  2952. DbgrSetSourceLinePrinting (
  2953. PDEBUGGER_CONTEXT Context,
  2954. PSTR *Arguments,
  2955. ULONG ArgumentCount
  2956. )
  2957. /*++
  2958. Routine Description:
  2959. This routine turns on or off the option to print the source file and line
  2960. next to every text address.
  2961. Arguments:
  2962. Context - Supplies a pointer to the application context.
  2963. Arguments - Supplies an array of strings containing the arguments. The
  2964. first argument is the command itself.
  2965. ArgumentCount - Supplies the count of arguments. This is always at least
  2966. one.
  2967. Return Value:
  2968. 0 on success.
  2969. Returns an error code on failure.
  2970. --*/
  2971. {
  2972. PSTR Argument;
  2973. if (ArgumentCount != 2) {
  2974. DbgOut("Error: Use \"sl on\" or \"sl off\" to enable or disable source "
  2975. "line printing.\n");
  2976. return EINVAL;
  2977. }
  2978. Argument = Arguments[1];
  2979. if ((strcasecmp(Argument, "on") == 0) ||
  2980. (strcasecmp(Argument, "yes") == 0) ||
  2981. (strcasecmp(Argument, "1") == 0)) {
  2982. Context->Flags |= DEBUGGER_FLAG_PRINT_LINE_NUMBERS;
  2983. }
  2984. if ((strcasecmp(Argument, "off") == 0) ||
  2985. (strcasecmp(Argument, "no") == 0) ||
  2986. (strcasecmp(Argument, "0") == 0)) {
  2987. Context->Flags &= ~DEBUGGER_FLAG_PRINT_LINE_NUMBERS;
  2988. }
  2989. if ((Context->Flags & DEBUGGER_FLAG_PRINT_LINE_NUMBERS) != 0) {
  2990. DbgOut("Printing of source line numbers is now enabled.\n");
  2991. } else {
  2992. DbgOut("Printing of source line numbers is now disabled.\n");
  2993. }
  2994. return 0;
  2995. }
  2996. INT
  2997. DbgrReturnToCaller (
  2998. PDEBUGGER_CONTEXT Context,
  2999. PSTR *Arguments,
  3000. ULONG ArgumentCount
  3001. )
  3002. /*++
  3003. Routine Description:
  3004. This routine interprets the "go" command from the user.
  3005. Arguments:
  3006. Context - Supplies a pointer to the application context.
  3007. Arguments - Supplies an array of strings containing the arguments. The
  3008. first argument is the command itself.
  3009. ArgumentCount - Supplies the count of arguments. This is always at least
  3010. one.
  3011. Return Value:
  3012. 0 on success.
  3013. Returns an error code on failure.
  3014. --*/
  3015. {
  3016. ULONG BytesRead;
  3017. ULONG FirstInstruction;
  3018. ULONG FirstInstructionAddress;
  3019. STACK_FRAME Frame;
  3020. ULONG FrameCount;
  3021. ULONGLONG InstructionPointer;
  3022. INT Result;
  3023. ULONGLONG ReturnAddress;
  3024. ReturnAddress = 0;
  3025. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  3026. InstructionPointer =
  3027. Context->CurrentEvent.BreakNotification.InstructionPointer;
  3028. //
  3029. // For ARM machines, the compiler doesn't generate a stack frame for
  3030. // leaf functions (functions that call no other functions). If this is the
  3031. // case the link register is actually the return value, not the frame.
  3032. // Detect this case by reading the first instruction of the function. If
  3033. // it's not "mov ip, sp", then this is a leaf function.
  3034. //
  3035. if (Context->MachineType == MACHINE_TYPE_ARM) {
  3036. FirstInstructionAddress =
  3037. DbgpGetFunctionStartAddress(Context, InstructionPointer);
  3038. if (FirstInstructionAddress != 0) {
  3039. Result = DbgReadMemory(Context,
  3040. TRUE,
  3041. FirstInstructionAddress,
  3042. ARM_INSTRUCTION_LENGTH,
  3043. &FirstInstruction,
  3044. &BytesRead);
  3045. if ((Result == 0) && (BytesRead == ARM_INSTRUCTION_LENGTH) &&
  3046. ((FirstInstruction != ARM_FUNCTION_PROLOGUE) ||
  3047. (InstructionPointer == FirstInstructionAddress))) {
  3048. ReturnAddress =
  3049. Context->CurrentEvent.BreakNotification.Registers.Arm.R14Lr;
  3050. Result = 0;
  3051. goto ReturnToCallerEnd;
  3052. }
  3053. }
  3054. }
  3055. FrameCount = 1;
  3056. Result = DbgGetCallStack(Context, NULL, &Frame, &FrameCount);
  3057. if ((Result != 0) || (FrameCount == 0)) {
  3058. DbgOut("Error: Unable to get call stack.\n");
  3059. Result = EINVAL;
  3060. goto ReturnToCallerEnd;
  3061. }
  3062. ReturnAddress = Frame.ReturnAddress;
  3063. Result = 0;
  3064. ReturnToCallerEnd:
  3065. //
  3066. // If the return address was successfully retrieved, then send the go
  3067. // command.
  3068. //
  3069. if (Result == 0) {
  3070. Result = DbgrContinue(Context, TRUE, ReturnAddress);
  3071. }
  3072. return Result;
  3073. }
  3074. INT
  3075. DbgrSetSymbolPathCommand (
  3076. PDEBUGGER_CONTEXT Context,
  3077. PSTR *Arguments,
  3078. ULONG ArgumentCount
  3079. )
  3080. /*++
  3081. Routine Description:
  3082. This routine sets or updates the symbol search path.
  3083. Arguments:
  3084. Context - Supplies a pointer to the application context.
  3085. Arguments - Supplies an array of strings containing the arguments. The
  3086. first argument is the command itself.
  3087. ArgumentCount - Supplies the count of arguments. This is always at least
  3088. one.
  3089. Return Value:
  3090. 0 on success.
  3091. Returns an error code on failure.
  3092. --*/
  3093. {
  3094. BOOL Append;
  3095. ULONG ArgumentIndex;
  3096. ULONG PathIndex;
  3097. INT Status;
  3098. INT TotalStatus;
  3099. //
  3100. // The sympath+ command augments the current symbol path.
  3101. //
  3102. if (strcasecmp(Arguments[0], "sympath+") == 0) {
  3103. Append = TRUE;
  3104. //
  3105. // The sympath command command either prints the current symbol path with
  3106. // no arguments or sets a new one.
  3107. //
  3108. } else {
  3109. assert(strcasecmp(Arguments[0], "sympath") == 0);
  3110. Append = FALSE;
  3111. if (ArgumentCount == 1) {
  3112. for (PathIndex = 0;
  3113. PathIndex < Context->SymbolPathCount;
  3114. PathIndex += 1) {
  3115. DbgOut("%s\n", Context->SymbolPath[PathIndex]);
  3116. }
  3117. return 0;
  3118. }
  3119. }
  3120. //
  3121. // Loop adding or replacing the symbol path.
  3122. //
  3123. TotalStatus = 0;
  3124. for (ArgumentIndex = 1; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  3125. Status = DbgrSetSymbolPath(Context, Arguments[ArgumentIndex], Append);
  3126. if (Status != 0) {
  3127. TotalStatus = Status;
  3128. }
  3129. //
  3130. // Assume that even if the user didn't specify sympath+ but did add
  3131. // multiple arguments, they want all the arguments in the search path.
  3132. //
  3133. Append = TRUE;
  3134. }
  3135. Status = TotalStatus;
  3136. return Status;
  3137. }
  3138. INT
  3139. DbgrSetSourcePathCommand (
  3140. PDEBUGGER_CONTEXT Context,
  3141. PSTR *Arguments,
  3142. ULONG ArgumentCount
  3143. )
  3144. /*++
  3145. Routine Description:
  3146. This routine sets or updates the source search path.
  3147. Arguments:
  3148. Context - Supplies a pointer to the application context.
  3149. Arguments - Supplies an array of strings containing the arguments. The
  3150. first argument is the command itself.
  3151. ArgumentCount - Supplies the count of arguments. This is always at least
  3152. one.
  3153. Return Value:
  3154. 0 on success.
  3155. Returns an error code on failure.
  3156. --*/
  3157. {
  3158. ULONG ArgumentIndex;
  3159. PLIST_ENTRY CurrentEntry;
  3160. PDEBUGGER_SOURCE_PATH Entry;
  3161. INT FinalResult;
  3162. INT Result;
  3163. if (strcasecmp(Arguments[0], "srcpath+") != 0) {
  3164. //
  3165. // If it's just srcpath by itself, print the current source path.
  3166. //
  3167. if (ArgumentCount == 1) {
  3168. CurrentEntry = Context->SourcePathList.Next;
  3169. while (CurrentEntry != &(Context->SourcePathList)) {
  3170. Entry = LIST_VALUE(CurrentEntry,
  3171. DEBUGGER_SOURCE_PATH,
  3172. ListEntry);
  3173. CurrentEntry = CurrentEntry->Next;
  3174. if (Entry->PrefixLength != 0) {
  3175. DbgOut("%s -> %s\n", Entry->Prefix, Entry->Path);
  3176. } else {
  3177. DbgOut("%s\n", Entry->Path);
  3178. }
  3179. }
  3180. } else {
  3181. DbgrpDestroyAllSourcePaths(Context);
  3182. }
  3183. }
  3184. //
  3185. // Add all source paths in the arguments.
  3186. //
  3187. FinalResult = 0;
  3188. for (ArgumentIndex = 1; ArgumentIndex < ArgumentCount; ArgumentIndex += 1) {
  3189. Result = DbgrpAddSourcePath(Context, Arguments[ArgumentIndex]);
  3190. if (Result != 0) {
  3191. DbgOut("Failed to add source path %s: Error %s.\n",
  3192. Arguments[ArgumentIndex],
  3193. strerror(Result));
  3194. FinalResult = Result;
  3195. }
  3196. }
  3197. return FinalResult;
  3198. }
  3199. INT
  3200. DbgrReloadSymbols (
  3201. PDEBUGGER_CONTEXT Context,
  3202. PSTR *Arguments,
  3203. ULONG ArgumentCount
  3204. )
  3205. /*++
  3206. Routine Description:
  3207. This routine unloads and reloads all symbols from the search path.
  3208. Arguments:
  3209. Context - Supplies a pointer to the application context.
  3210. Arguments - Supplies an array of strings containing the arguments. The
  3211. first argument is the command itself.
  3212. ArgumentCount - Supplies the count of arguments. This is always at least
  3213. one.
  3214. Return Value:
  3215. 0 on success.
  3216. Returns an error code on failure.
  3217. --*/
  3218. {
  3219. INT Result;
  3220. DbgrpUnloadAllModules(Context, FALSE);
  3221. Result = DbgrpValidateLoadedModules(
  3222. Context,
  3223. Context->CurrentEvent.BreakNotification.LoadedModuleCount,
  3224. Context->CurrentEvent.BreakNotification.LoadedModuleSignature,
  3225. TRUE);
  3226. return Result;
  3227. }
  3228. INT
  3229. DbgrSetSymbolPath (
  3230. PDEBUGGER_CONTEXT Context,
  3231. PSTR Path,
  3232. BOOL Append
  3233. )
  3234. /*++
  3235. Routine Description:
  3236. This routine sets or updates the symbol search path.
  3237. Arguments:
  3238. Context - Supplies a pointer to the application context.
  3239. Path - Supplies a pointer to the new symbol path. This could contain
  3240. multiple symbol paths if separated by semicolons.
  3241. Append - Supplies a boolean indicating whether the new path should replace
  3242. or append the existing path.
  3243. Return Value:
  3244. 0 on success.
  3245. Returns an error code on failure.
  3246. --*/
  3247. {
  3248. PSTR CurrentString;
  3249. PSTR *NewArray;
  3250. PSTR NewPath;
  3251. ULONG NewPathCount;
  3252. PSTR Next;
  3253. ULONG Offset;
  3254. ULONG PathCount;
  3255. ULONG PathIndex;
  3256. ULONG PathLength;
  3257. INT Status;
  3258. NewArray = NULL;
  3259. //
  3260. // Loop once to count the number of semicolons.
  3261. //
  3262. NewPathCount = 1;
  3263. CurrentString = Path;
  3264. while (TRUE) {
  3265. CurrentString = strchr(CurrentString, ';');
  3266. if (CurrentString == NULL) {
  3267. break;
  3268. }
  3269. NewPathCount += 1;
  3270. CurrentString += 1;
  3271. }
  3272. //
  3273. // Allocate the new array.
  3274. //
  3275. PathCount = NewPathCount;
  3276. if (Append != FALSE) {
  3277. PathCount += Context->SymbolPathCount;
  3278. }
  3279. NewArray = malloc(sizeof(PSTR) * PathCount);
  3280. if (NewArray == NULL) {
  3281. Status = ENOMEM;
  3282. goto SetSymbolPathEnd;
  3283. }
  3284. memset(NewArray, 0, sizeof(PSTR) * PathCount);
  3285. //
  3286. // If copying, move the existing entries over now.
  3287. //
  3288. Offset = 0;
  3289. if (Append != FALSE) {
  3290. for (Offset = 0; Offset < Context->SymbolPathCount; Offset += 1) {
  3291. NewArray[Offset] = Context->SymbolPath[Offset];
  3292. }
  3293. //
  3294. // If not copying, free up the existing entries.
  3295. //
  3296. } else {
  3297. for (PathIndex = 0;
  3298. PathIndex < Context->SymbolPathCount;
  3299. PathIndex += 1) {
  3300. free(Context->SymbolPath[PathIndex]);
  3301. }
  3302. }
  3303. if (Context->SymbolPath != NULL) {
  3304. free(Context->SymbolPath);
  3305. }
  3306. //
  3307. // Now create the new array entries based on the parameter.
  3308. //
  3309. CurrentString = Path;
  3310. for (PathIndex = 0; PathIndex < NewPathCount; PathIndex += 1) {
  3311. Next = strchr(CurrentString, ';');
  3312. if (Next != NULL) {
  3313. PathLength = (UINTN)Next - (UINTN)CurrentString;
  3314. } else {
  3315. PathLength = strlen(CurrentString);
  3316. }
  3317. NewPath = malloc(PathLength + 1);
  3318. if (NewPath == NULL) {
  3319. Status = ENOMEM;
  3320. goto SetSymbolPathEnd;
  3321. }
  3322. memcpy(NewPath, CurrentString, PathLength);
  3323. NewPath[PathLength] = '\0';
  3324. NewArray[PathIndex + Offset] = NewPath;
  3325. CurrentString = Next + 1;
  3326. }
  3327. Context->SymbolPath = NewArray;
  3328. Context->SymbolPathCount = PathCount;
  3329. Status = 0;
  3330. SetSymbolPathEnd:
  3331. if (Status != 0) {
  3332. if (NewArray != NULL) {
  3333. for (PathIndex = 0; PathIndex < NewPathCount; PathIndex += 1) {
  3334. if (NewArray[PathIndex] != NULL) {
  3335. free(NewArray[PathIndex]);
  3336. }
  3337. }
  3338. free(NewArray);
  3339. }
  3340. }
  3341. return Status;
  3342. }
  3343. INT
  3344. DbgrLoadExtension (
  3345. PDEBUGGER_CONTEXT Context,
  3346. PSTR *Arguments,
  3347. ULONG ArgumentCount
  3348. )
  3349. /*++
  3350. Routine Description:
  3351. This routine loads or unloads a debugger extension.
  3352. Arguments:
  3353. Context - Supplies a pointer to the application context.
  3354. Arguments - Supplies an array of strings containing the arguments. The
  3355. first argument is the command itself.
  3356. ArgumentCount - Supplies the count of arguments. This is always at least
  3357. one.
  3358. Return Value:
  3359. 0 on success.
  3360. Returns an error code on failure.
  3361. --*/
  3362. {
  3363. ULONG ArgumentIndex;
  3364. PSTR Name;
  3365. INT Status;
  3366. INT TotalStatus;
  3367. //
  3368. // The load command fires up an extension.
  3369. //
  3370. if (strcasecmp(Arguments[0], "load") == 0) {
  3371. if (ArgumentCount < 2) {
  3372. DbgOut("Usage: load <path>\nLoads a debugger extension at the "
  3373. "given path.\n");
  3374. Status = EINVAL;
  3375. goto LoadExtensionEnd;
  3376. }
  3377. TotalStatus = 0;
  3378. for (ArgumentIndex = 1;
  3379. ArgumentIndex < ArgumentCount;
  3380. ArgumentIndex += 1) {
  3381. Name = Arguments[ArgumentIndex];
  3382. Status = DbgLoadExtension(Context, Name);
  3383. if (Status != 0) {
  3384. DbgOut("Failed to load extension '%s'.\n", Name);
  3385. TotalStatus = Status;
  3386. }
  3387. }
  3388. Status = TotalStatus;
  3389. //
  3390. // Unload an extension, or * for all extensions.
  3391. //
  3392. } else {
  3393. assert(strcasecmp(Arguments[0], "unload") == 0);
  3394. if (ArgumentCount < 2) {
  3395. DbgOut("Usage: unload <path>\nUnloads a debugger extension at the "
  3396. "given path. Use 'unload *' to unload all extensions.\n");
  3397. Status = EINVAL;
  3398. goto LoadExtensionEnd;
  3399. }
  3400. TotalStatus = 0;
  3401. for (ArgumentIndex = 1;
  3402. ArgumentIndex < ArgumentCount;
  3403. ArgumentIndex += 1) {
  3404. Name = Arguments[ArgumentIndex];
  3405. if (strcmp(Name, "*") == 0) {
  3406. DbgOut("Unloading all extensions.\n");
  3407. DbgUnloadAllExtensions(Context);
  3408. Status = 0;
  3409. break;
  3410. } else {
  3411. DbgUnloadExtension(Context, Name);
  3412. }
  3413. }
  3414. Status = TotalStatus;
  3415. }
  3416. LoadExtensionEnd:
  3417. return Status;
  3418. }
  3419. INT
  3420. DbgrSwitchProcessor (
  3421. PDEBUGGER_CONTEXT Context,
  3422. PSTR *Arguments,
  3423. ULONG ArgumentCount
  3424. )
  3425. /*++
  3426. Routine Description:
  3427. This routine switches the debugger to another processor in kernel mode or
  3428. thread in user mode.
  3429. Arguments:
  3430. Context - Supplies a pointer to the application context.
  3431. Arguments - Supplies an array of strings containing the arguments. The
  3432. first argument is the command itself.
  3433. ArgumentCount - Supplies the count of arguments. This is always at least
  3434. one.
  3435. Return Value:
  3436. 0 on success.
  3437. Returns an error code on failure.
  3438. --*/
  3439. {
  3440. PSTR AfterScan;
  3441. ULONG Count;
  3442. PULONG Ids;
  3443. ULONG ProcessorNumber;
  3444. PSTR ProcessorNumberString;
  3445. INT Result;
  3446. ULONG ThreadIndex;
  3447. Ids = NULL;
  3448. assert(Arguments[0][0] == '~');
  3449. if (Arguments[0][1] == '\0') {
  3450. ProcessorNumber = -1;
  3451. } else {
  3452. ProcessorNumberString = Arguments[0] + 1;
  3453. ProcessorNumber = strtoul(ProcessorNumberString, &AfterScan, 0);
  3454. if (AfterScan == ProcessorNumberString) {
  3455. DbgOut("Failed to convert '%s' to a number.\n",
  3456. ProcessorNumberString);
  3457. Result = EINVAL;
  3458. goto SwitchProcessorsEnd;
  3459. }
  3460. }
  3461. //
  3462. // If no processor number was supplied, list the processors.
  3463. //
  3464. if (ProcessorNumber == -1) {
  3465. Result = DbgGetThreadList(Context, &Count, &Ids);
  3466. if (Result != 0) {
  3467. DbgOut("Error: Failed to get processor/thread list.\n");
  3468. goto SwitchProcessorsEnd;
  3469. }
  3470. if (Context->ConnectionType == DebugConnectionKernel) {
  3471. if (Count == 1) {
  3472. DbgOut("There is 1 processor in the system.\n");
  3473. } else {
  3474. DbgOut("There are %d processors in the system.\n", Count);
  3475. }
  3476. Result = 0;
  3477. } else if (Context->ConnectionType == DebugConnectionUser) {
  3478. if (Count == 1) {
  3479. DbgOut("There is 1 thread in the process.\n");
  3480. } else {
  3481. DbgOut("There are %d threads in the process:\n", Count);
  3482. for (ThreadIndex = 0; ThreadIndex < Count; ThreadIndex += 1) {
  3483. DbgOut("%x\n", Ids[ThreadIndex]);
  3484. }
  3485. }
  3486. } else {
  3487. DbgOut("Error: Unknown connection type %d.\n",
  3488. Context->ConnectionType);
  3489. Result = EINVAL;
  3490. }
  3491. goto SwitchProcessorsEnd;
  3492. }
  3493. //
  3494. // The user cannot switch to the same processor.
  3495. //
  3496. if (ProcessorNumber ==
  3497. Context->CurrentEvent.BreakNotification.ProcessorOrThreadNumber) {
  3498. Result = 0;
  3499. goto SwitchProcessorsEnd;
  3500. }
  3501. //
  3502. // The user cannot switch to a processor that's out of range.
  3503. //
  3504. Count = Context->CurrentEvent.BreakNotification.ProcessorOrThreadCount;
  3505. if ((Context->ConnectionType == DebugConnectionKernel) &&
  3506. (ProcessorNumber >= Count)) {
  3507. if (Count == 1) {
  3508. DbgOut("Error: There is only one processor in the system.\n");
  3509. } else {
  3510. DbgOut("Error: There are only %d processors in the system!\n",
  3511. Count);
  3512. }
  3513. Result = 0;
  3514. goto SwitchProcessorsEnd;
  3515. }
  3516. //
  3517. // Send the switch command.
  3518. //
  3519. Result = DbgSwitchProcessors(Context, ProcessorNumber);
  3520. if (Result != 0) {
  3521. DbgOut("Error: Failed to switch processors.\n");
  3522. goto SwitchProcessorsEnd;
  3523. }
  3524. //
  3525. // Reset the frame as well.
  3526. //
  3527. DbgrpSetFrame(Context, 0);
  3528. Context->LastMemoryDump.NextAddress =
  3529. Context->CurrentEvent.BreakNotification.InstructionPointer;
  3530. Context->LastMemoryDump.Virtual = TRUE;
  3531. Context->DisassemblyAddress = Context->LastMemoryDump.NextAddress;
  3532. Result = 0;
  3533. SwitchProcessorsEnd:
  3534. if (Ids != NULL) {
  3535. free(Ids);
  3536. }
  3537. return Result;
  3538. }
  3539. INT
  3540. DbgrPrintProcessorBlock (
  3541. PDEBUGGER_CONTEXT Context,
  3542. PSTR *Arguments,
  3543. ULONG ArgumentCount
  3544. )
  3545. /*++
  3546. Routine Description:
  3547. This routine prints the contents of the current processor block.
  3548. Arguments:
  3549. Context - Supplies a pointer to the application context.
  3550. Arguments - Supplies an array of strings containing the arguments. The
  3551. first argument is the command itself.
  3552. ArgumentCount - Supplies the count of arguments. This is always at least
  3553. one.
  3554. Return Value:
  3555. 0 on success.
  3556. Returns an error code on failure.
  3557. --*/
  3558. {
  3559. ULONGLONG Address;
  3560. UINTN Size;
  3561. INT Status;
  3562. PSTR TypeString;
  3563. if (ArgumentCount > 1) {
  3564. Size = strlen(Arguments[1]) + strlen("PROCESSOR_BLOCK") + 2;
  3565. TypeString = malloc(Size);
  3566. if (TypeString == NULL) {
  3567. return ENOMEM;
  3568. }
  3569. snprintf(TypeString, Size, "%s.%s", "PROCESSOR_BLOCK", Arguments[1]);
  3570. } else {
  3571. TypeString = "PROCESSOR_BLOCK";
  3572. }
  3573. Address = Context->CurrentEvent.BreakNotification.ProcessorBlock;
  3574. Status = EFAULT;
  3575. if (Address != 0) {
  3576. Status = DbgPrintTypeByName(Context,
  3577. Address,
  3578. TypeString,
  3579. 0,
  3580. DEFAULT_RECURSION_DEPTH);
  3581. DbgOut("\n");
  3582. }
  3583. if (ArgumentCount > 1) {
  3584. free(TypeString);
  3585. }
  3586. return Status;
  3587. }
  3588. VOID
  3589. DbgrRequestBreakIn (
  3590. VOID
  3591. )
  3592. /*++
  3593. Routine Description:
  3594. This routine sends a break-in request to the target.
  3595. Arguments:
  3596. None.
  3597. Return Value:
  3598. None.
  3599. --*/
  3600. {
  3601. if (DbgConsoleContext->ConnectionType == DebugConnectionRemote) {
  3602. DbgrpClientRequestBreakIn(DbgConsoleContext);
  3603. } else {
  3604. DbgRequestBreakIn(DbgConsoleContext);
  3605. }
  3606. return;
  3607. }
  3608. INT
  3609. DbgrDumpPointerSymbols (
  3610. PDEBUGGER_CONTEXT Context,
  3611. PSTR *Arguments,
  3612. ULONG ArgumentCount
  3613. )
  3614. /*++
  3615. Routine Description:
  3616. This routine dumps memory at the provided address and attempts to match
  3617. symbols at the dumped memory addresses.
  3618. Arguments:
  3619. Context - Supplies a pointer to the application context.
  3620. Arguments - Supplies an array of strings containing the arguments. The
  3621. first argument is the command itself.
  3622. ArgumentCount - Supplies the count of arguments. This is always at least
  3623. one.
  3624. Return Value:
  3625. 0 on success.
  3626. Returns an error code on failure.
  3627. --*/
  3628. {
  3629. ULONGLONG Address;
  3630. PSTR AddressString;
  3631. PULONG Buffer;
  3632. ULONG BufferSize;
  3633. ULONG BytesRead;
  3634. INT Index;
  3635. INT Result;
  3636. Buffer = NULL;
  3637. AddressString = NULL;
  3638. if (ArgumentCount >= 2) {
  3639. AddressString = Arguments[1];
  3640. Result = DbgEvaluate(Context, AddressString, &Address);
  3641. if (Result != 0) {
  3642. DbgOut("Failed to evaluate address '%s'.\n", AddressString);
  3643. goto DumpPointerSymbolsEnd;
  3644. }
  3645. } else {
  3646. Address = Context->LastMemoryDump.NextAddress;
  3647. }
  3648. BufferSize = sizeof(ULONG) * DEFAULT_DUMP_POINTERS_ROWS;
  3649. Buffer = malloc(BufferSize);
  3650. if (Buffer == NULL) {
  3651. Result = ENOMEM;
  3652. goto DumpPointerSymbolsEnd;
  3653. }
  3654. Result = DbgReadMemory(Context,
  3655. TRUE,
  3656. Address,
  3657. BufferSize,
  3658. Buffer,
  3659. &BytesRead);
  3660. if (Result != 0) {
  3661. goto DumpPointerSymbolsEnd;
  3662. }
  3663. for (Index = 0; Index < DEFAULT_DUMP_POINTERS_ROWS; Index += 1) {
  3664. DbgOut("%08I64x ", Address);
  3665. Address += sizeof(ULONG);
  3666. if (((Index + 1) * sizeof(ULONG)) <= BytesRead) {
  3667. DbgOut("%08x ", Buffer[Index]);
  3668. DbgPrintAddressSymbol(Context, Buffer[Index]);
  3669. } else {
  3670. DbgOut("????????");
  3671. }
  3672. DbgOut("\n");
  3673. }
  3674. Context->LastMemoryDump.NextAddress = Address;
  3675. Context->LastMemoryDump.Virtual = TRUE;
  3676. Result = 0;
  3677. DumpPointerSymbolsEnd:
  3678. if (Buffer != NULL) {
  3679. free(Buffer);
  3680. }
  3681. return Result;
  3682. }
  3683. INT
  3684. DbgrProfileCommand (
  3685. PDEBUGGER_CONTEXT Context,
  3686. PSTR *Arguments,
  3687. ULONG ArgumentCount
  3688. )
  3689. /*++
  3690. Routine Description:
  3691. This routine handles the profile command. It essentially just forwards on
  3692. to the profile handler.
  3693. Arguments:
  3694. Context - Supplies a pointer to the application context.
  3695. Arguments - Supplies an array of strings containing the arguments. The
  3696. first argument is the command itself.
  3697. ArgumentCount - Supplies the count of arguments. This is always at least
  3698. one.
  3699. Return Value:
  3700. 0 on success.
  3701. Returns an error code on failure.
  3702. --*/
  3703. {
  3704. INT Result;
  3705. Result = DbgrDispatchProfilerCommand(Context,
  3706. Arguments + 1,
  3707. ArgumentCount - 1);
  3708. return Result;
  3709. }
  3710. INT
  3711. DbgrRebootCommand (
  3712. PDEBUGGER_CONTEXT Context,
  3713. PSTR *Arguments,
  3714. ULONG ArgumentCount
  3715. )
  3716. /*++
  3717. Routine Description:
  3718. This routine handles the profile command. It essentially just forwards on
  3719. to the profile handler.
  3720. Arguments:
  3721. Context - Supplies a pointer to the application context.
  3722. Arguments - Supplies an array of strings containing the arguments. The
  3723. first argument is the command itself.
  3724. ArgumentCount - Supplies the count of arguments. This is always at least
  3725. one.
  3726. Return Value:
  3727. 0 on success.
  3728. Returns an error code on failure.
  3729. --*/
  3730. {
  3731. BOOL PrintUsage;
  3732. DEBUG_REBOOT_TYPE RebootType;
  3733. PrintUsage = FALSE;
  3734. RebootType = DebugRebootWarm;
  3735. if (ArgumentCount > 2) {
  3736. PrintUsage = TRUE;
  3737. } else if (ArgumentCount > 1) {
  3738. if (strcasecmp(Arguments[1], "-s") == 0) {
  3739. RebootType = DebugRebootShutdown;
  3740. } else if (strcasecmp(Arguments[1], "w") == 0) {
  3741. RebootType = DebugRebootWarm;
  3742. } else if (strcasecmp(Arguments[1], "-c") == 0) {
  3743. RebootType = DebugRebootCold;
  3744. } else {
  3745. PrintUsage = TRUE;
  3746. }
  3747. }
  3748. if (PrintUsage != FALSE) {
  3749. DbgOut("Usage: reboot [-s|-w|-c]\n"
  3750. "This command forcefully reboots the target machine. If the \n"
  3751. "target does not support the given option, a cold reboot is \n"
  3752. "performed. Options are:\n"
  3753. " -s -- Shut down the machine.\n"
  3754. " -w -- Warm reset the machine (default).\n"
  3755. " -c -- Cold reset the machine.\n\n");
  3756. return 1;
  3757. }
  3758. return DbgReboot(Context, RebootType);
  3759. }
  3760. INT
  3761. DbgrContinue (
  3762. PDEBUGGER_CONTEXT Context,
  3763. BOOL SetOneTimeBreak,
  3764. ULONGLONG Address
  3765. )
  3766. /*++
  3767. Routine Description:
  3768. This routine sends the "go" command to the target, signaling to continue
  3769. execution.
  3770. Arguments:
  3771. Context - Supplies a pointer to the application context.
  3772. SetOneTimeBreak - Supplies a flag indicating whether to go unconditionally
  3773. (FALSE) or with a one-time breakpoint (TRUE).
  3774. Address - Supplies the address of the one-time breakpoint if one was
  3775. specified.
  3776. Return Value:
  3777. 0 on success.
  3778. Returns an error code on failure.
  3779. --*/
  3780. {
  3781. PDEBUGGER_BREAK_POINT Breakpoint;
  3782. PLIST_ENTRY CurrentEntry;
  3783. INT Result;
  3784. ULONG SignalToDeliver;
  3785. //
  3786. // Look to see if there's already an enabled breakpoint at that address,
  3787. // and do nothing if there is.
  3788. //
  3789. CurrentEntry = Context->BreakpointList.Next;
  3790. while ((SetOneTimeBreak != FALSE) &&
  3791. (CurrentEntry != &(Context->BreakpointList))) {
  3792. Breakpoint = LIST_VALUE(CurrentEntry, DEBUGGER_BREAK_POINT, ListEntry);
  3793. if ((Breakpoint->Enabled != FALSE) &&
  3794. (Breakpoint->Type == BreakpointTypeExecution) &&
  3795. (Breakpoint->Address == Address)) {
  3796. SetOneTimeBreak = FALSE;
  3797. }
  3798. CurrentEntry = CurrentEntry->Next;
  3799. }
  3800. //
  3801. // Set the one time break point if requested.
  3802. //
  3803. if (SetOneTimeBreak != FALSE) {
  3804. Result = DbgrpSetBreakpointAtAddress(
  3805. Context,
  3806. Address,
  3807. &(Context->OneTimeBreakOriginalValue));
  3808. Context->OneTimeBreakAddress = Address;
  3809. if (Result != 0) {
  3810. DbgOut("Error: Failed to set breakpoint at %I64x.\n", Address);
  3811. return Result;
  3812. }
  3813. Context->OneTimeBreakValid = TRUE;
  3814. }
  3815. //
  3816. // If there's a breakpoint to restore, then do a single step, restore the
  3817. // breakpoint, and then continue.
  3818. //
  3819. if (Context->BreakpointToRestore != NULL) {
  3820. Result = DbgrSingleStep(Context);
  3821. if (Result != 0) {
  3822. DbgOut("Error: Failed to single step.\n");
  3823. return Result;
  3824. }
  3825. Result = DbgWaitForEvent(Context);
  3826. if (Result != 0) {
  3827. DbgOut("Error: Failed to wait for a response after single step.\n");
  3828. return Result;
  3829. }
  3830. if (Context->CurrentEvent.Type != DebuggerEventBreak) {
  3831. DbgOut("Failed to get a break after a single step.\n");
  3832. return EINVAL;
  3833. }
  3834. Result = DbgrpSetBreakpointAtAddress(
  3835. Context,
  3836. Context->BreakpointToRestore->Address,
  3837. &(Context->BreakpointToRestore->OriginalValue));
  3838. if (Result != 0) {
  3839. DbgOut("Failed to restore breakpoint %d at %I64x.\n",
  3840. Context->BreakpointToRestore->Index,
  3841. Context->BreakpointToRestore->Address);
  3842. return Result;
  3843. }
  3844. Context->BreakpointToRestore = NULL;
  3845. }
  3846. SignalToDeliver = DbgGetSignalToDeliver(Context);
  3847. Result = DbgContinue(Context, SignalToDeliver);
  3848. if (Result != 0) {
  3849. return Result;
  3850. }
  3851. Result = 0;
  3852. return Result;
  3853. }
  3854. VOID
  3855. DbgrShowSourceAtAddress (
  3856. PDEBUGGER_CONTEXT Context,
  3857. ULONGLONG Address
  3858. )
  3859. /*++
  3860. Routine Description:
  3861. This routine loads the source file and highlights the source line
  3862. corresponding to the given target address.
  3863. Arguments:
  3864. Context - Supplies a pointer to the application context.
  3865. Address - Supplies the target's executing virtual address.
  3866. Return Value:
  3867. None.
  3868. --*/
  3869. {
  3870. PDEBUGGER_MODULE CurrentModule;
  3871. ULONGLONG DebasedAddress;
  3872. BOOL Result;
  3873. PSOURCE_LINE_SYMBOL SourceLine;
  3874. PSTR SourcePath;
  3875. //
  3876. // Acquire the standard out lock to synchronize with remote threads trying
  3877. // to send updated source information.
  3878. //
  3879. AcquireDebuggerLock(Context->StandardOut.Lock);
  3880. DbgrUnhighlightCurrentLine(Context);
  3881. SourcePath = NULL;
  3882. CurrentModule = DbgpFindModuleFromAddress(Context,
  3883. Address,
  3884. &DebasedAddress);
  3885. if (CurrentModule != NULL) {
  3886. SourceLine = DbgLookupSourceLine(CurrentModule->Symbols,
  3887. DebasedAddress);
  3888. if (SourceLine != NULL) {
  3889. SourcePath = DbgrpCreateFullPath(SourceLine->ParentSource);
  3890. if (SourcePath == NULL) {
  3891. goto ShowSourceAtAddressEnd;
  3892. }
  3893. //
  3894. // If the source file is different than what was previously
  3895. // displayed, load the new source file.
  3896. //
  3897. if ((Context->SourceFile.Path == NULL) ||
  3898. (strcmp(Context->SourceFile.Path, SourcePath) != 0)) {
  3899. if (Context->SourceFile.Path != NULL) {
  3900. free(Context->SourceFile.Path);
  3901. Context->SourceFile.Path = NULL;
  3902. }
  3903. if (Context->SourceFile.ActualPath != NULL) {
  3904. free(Context->SourceFile.ActualPath);
  3905. Context->SourceFile.ActualPath = NULL;
  3906. }
  3907. if (Context->SourceFile.Contents != NULL) {
  3908. free(Context->SourceFile.Contents);
  3909. Context->SourceFile.Contents = 0;
  3910. }
  3911. Context->SourceFile.Path = SourcePath;
  3912. SourcePath = NULL;
  3913. Context->SourceFile.LineNumber = 0;
  3914. Result = DbgrpLoadSourceFile(Context,
  3915. Context->SourceFile.Path,
  3916. &(Context->SourceFile.ActualPath),
  3917. &(Context->SourceFile.Contents),
  3918. &(Context->SourceFile.Size));
  3919. if (Result == 0) {
  3920. Result = UiLoadSourceFile(Context->SourceFile.ActualPath,
  3921. Context->SourceFile.Contents,
  3922. Context->SourceFile.Size);
  3923. if (Result != FALSE) {
  3924. DbgrpHighlightExecutingLine(Context,
  3925. SourceLine->LineNumber);
  3926. }
  3927. //
  3928. // The file load failed. Clear the screen. Do notify the
  3929. // remotes too, maybe they'll have better luck loading the
  3930. // file on their own.
  3931. //
  3932. } else {
  3933. UiLoadSourceFile(NULL, NULL, 0);
  3934. Context->SourceFile.LineNumber = SourceLine->LineNumber;
  3935. DbgrpServerNotifyClients(Context);
  3936. }
  3937. //
  3938. // It's the same file as before, just highlight a different line.
  3939. //
  3940. } else {
  3941. DbgrpHighlightExecutingLine(Context, SourceLine->LineNumber);
  3942. }
  3943. }
  3944. }
  3945. ShowSourceAtAddressEnd:
  3946. ReleaseDebuggerLock(Context->StandardOut.Lock);
  3947. if (SourcePath != NULL) {
  3948. free(SourcePath);
  3949. }
  3950. return;
  3951. }
  3952. INT
  3953. DbgrDumpType (
  3954. PDEBUGGER_CONTEXT Context,
  3955. PSTR *Arguments,
  3956. ULONG ArgumentCount,
  3957. PVOID RawDataStream,
  3958. ULONG RawDataStreamSizeInBytes
  3959. )
  3960. /*++
  3961. Routine Description:
  3962. This routine prints information about a type description or value. If only
  3963. a type is specified, the type format will be printed. If an address is
  3964. passed as a second parameter, then the values will be dumped. If a global
  3965. or local variable is passed as the first parameter, the values will also be
  3966. dumped.
  3967. Arguments:
  3968. Context - Supplies a pointer to the application context.
  3969. Arguments - Supplies a pointer to an array of argument strings.
  3970. ArgumentCount - Supplies the number of arguments in the argument array.
  3971. RawDataStream - Supplies the actual memory to dump in the given type form.
  3972. If this parameter is non-NULL, then the AddressString parameter is
  3973. ignored. The size of this buffer must be non-zero.
  3974. RawDataStreamSizeInBytes - Supplies the size of the raw data stream buffer,
  3975. in bytes.
  3976. Return Value:
  3977. 0 if the information was printed successfully.
  3978. Returns an error code on failure.
  3979. --*/
  3980. {
  3981. ULONGLONG Address;
  3982. ULONG AddressIndex;
  3983. ULONG AddressStartIndex;
  3984. ULONG BytesRead;
  3985. PDATA_SYMBOL DataResult;
  3986. PVOID DataStream;
  3987. PDATA_SYMBOL Local;
  3988. ULONGLONG Pc;
  3989. INT Result;
  3990. SYMBOL_SEARCH_RESULT SearchResult;
  3991. PDEBUG_SYMBOLS Symbols;
  3992. PSTR SymbolString;
  3993. PTYPE_SYMBOL Type;
  3994. ULONG TypeSize;
  3995. Address = 0;
  3996. AddressStartIndex = 1;
  3997. DataStream = NULL;
  3998. Type = NULL;
  3999. assert((Arguments != NULL) && (ArgumentCount != 0));
  4000. //
  4001. // Test to see if the first argument is a local variable name. Local
  4002. // variables must be tested first because a local variable may match a
  4003. // structure name, at which point the wrong data would be printed. Do not
  4004. // perform this test when raw data is supplied.
  4005. //
  4006. if ((ArgumentCount == 1) &&
  4007. ((RawDataStream == NULL) || (RawDataStreamSizeInBytes == 0))) {
  4008. Result = DbgpFindLocal(Context,
  4009. &(Context->FrameRegisters),
  4010. Arguments[0],
  4011. &Symbols,
  4012. &Local,
  4013. &Pc);
  4014. if (Result == 0) {
  4015. //
  4016. // In order to dump the local variable, the local data symbol must
  4017. // be evaluated for type information.
  4018. //
  4019. Result = DbgGetDataSymbolTypeInformation(Local, &Type, &TypeSize);
  4020. if (Result == FALSE) {
  4021. DbgOut("Error: unable to get type information for the local "
  4022. "variable %s\n",
  4023. Arguments[0]);
  4024. Result = EINVAL;
  4025. goto DumpTypeEnd;
  4026. }
  4027. //
  4028. // Allocate memory to collect the data for the data symbol.
  4029. //
  4030. DataStream = malloc(TypeSize);
  4031. if (DataStream == NULL) {
  4032. DbgOut("Error: unable to allocate %d bytes of memory\n",
  4033. TypeSize);
  4034. Result = ENOMEM;
  4035. goto DumpTypeEnd;
  4036. }
  4037. //
  4038. // Read the symbol data from the local data symbol.
  4039. //
  4040. Result = DbgGetDataSymbolData(Context,
  4041. Symbols,
  4042. Local,
  4043. Pc,
  4044. DataStream,
  4045. TypeSize,
  4046. NULL,
  4047. 0);
  4048. if (Result == 0) {
  4049. //
  4050. // Resolve the data into something useful to dump.
  4051. //
  4052. Address = 0;
  4053. Result = DbgrpResolveDumpType(Context,
  4054. &Type,
  4055. &DataStream,
  4056. &TypeSize,
  4057. &Address);
  4058. if (Result != 0) {
  4059. DbgOut("Error: could not resolve dump type %s.\n",
  4060. Type->Name);
  4061. goto DumpTypeEnd;
  4062. }
  4063. if (Address != 0) {
  4064. DbgOut("Dumping memory at 0x%08x\n", (ULONG)Address);
  4065. }
  4066. Result = DbgPrintType(Context,
  4067. Type,
  4068. DataStream,
  4069. TypeSize,
  4070. 0,
  4071. DEFAULT_RECURSION_DEPTH);
  4072. goto DumpTypeEnd;
  4073. //
  4074. // If failed with something other than not found (for not currently
  4075. // active locals), then bail to the end.
  4076. //
  4077. } else if (Result != ENOENT) {
  4078. goto DumpTypeEnd;
  4079. }
  4080. }
  4081. }
  4082. //
  4083. // If a local type was not found, search symbols for the first argument.
  4084. // It should either by a type or a global variable.
  4085. //
  4086. SymbolString = Arguments[0];
  4087. SearchResult.Variety = SymbolResultInvalid;
  4088. Result = DbgpFindSymbol(Context, SymbolString, &SearchResult);
  4089. if (Result == FALSE) {
  4090. DbgOut("Error: Invalid type or global variable %s\n", SymbolString);
  4091. Result = EINVAL;
  4092. goto DumpTypeEnd;
  4093. }
  4094. switch (SearchResult.Variety) {
  4095. case SymbolResultType:
  4096. Type = SearchResult.U.TypeResult;
  4097. AddressStartIndex = 1;
  4098. break;
  4099. case SymbolResultData:
  4100. DataResult = SearchResult.U.DataResult;
  4101. Type = DbgGetType(DataResult->TypeOwner, DataResult->TypeNumber);
  4102. //
  4103. // This argument was an address itself.
  4104. //
  4105. AddressStartIndex = 0;
  4106. break;
  4107. default:
  4108. DbgOut("Error: Invalid symbol type %d for argument 1: %s\n",
  4109. SearchResult.Variety,
  4110. SymbolString);
  4111. break;
  4112. }
  4113. if (Type != NULL) {
  4114. Type = DbgSkipTypedefs(Type);
  4115. }
  4116. //
  4117. // If a type was not found, print the error and exit.
  4118. //
  4119. if (Type == NULL) {
  4120. DbgOut("Error: could not find type %s.\n", SymbolString);
  4121. goto DumpTypeEnd;
  4122. }
  4123. //
  4124. // If a raw data stream was supplied, print the contents of that in terms
  4125. // of the type.
  4126. //
  4127. TypeSize = DbgGetTypeSize(Type, 0);
  4128. if ((RawDataStream != NULL) && (RawDataStreamSizeInBytes != 0)) {
  4129. if (RawDataStreamSizeInBytes < TypeSize) {
  4130. DbgOut("Error: Supplied buffer of size %d is not big enough to "
  4131. "print type of size %d.\n",
  4132. RawDataStreamSizeInBytes,
  4133. TypeSize);
  4134. Result = EINVAL;
  4135. goto DumpTypeEnd;
  4136. }
  4137. Result = DbgPrintType(Context,
  4138. Type,
  4139. RawDataStream,
  4140. RawDataStreamSizeInBytes,
  4141. 0,
  4142. DEFAULT_RECURSION_DEPTH);
  4143. if (Result != 0) {
  4144. goto DumpTypeEnd;
  4145. }
  4146. //
  4147. // If an address was specified, print the type's contents.
  4148. //
  4149. } else if (ArgumentCount - AddressStartIndex != 0) {
  4150. DataStream = malloc(TypeSize);
  4151. if (DataStream == NULL) {
  4152. Result = ENOMEM;
  4153. goto DumpTypeEnd;
  4154. }
  4155. for (AddressIndex = AddressStartIndex;
  4156. AddressIndex < ArgumentCount;
  4157. AddressIndex += 1) {
  4158. //
  4159. // Evaluate the address. Failure here indicates a syntax error, but
  4160. // is not a fatal error.
  4161. //
  4162. Result = DbgEvaluate(Context, Arguments[AddressIndex], &Address);
  4163. if (Result != 0) {
  4164. DbgOut("Syntax error in address parameter!\n");
  4165. goto DumpTypeEnd;
  4166. }
  4167. Result = DbgReadMemory(Context,
  4168. TRUE,
  4169. Address,
  4170. TypeSize,
  4171. DataStream,
  4172. &BytesRead);
  4173. if (Result != 0) {
  4174. DbgOut("Error reading virtual memory, only read %d bytes, type "
  4175. "is %d bytes!\n",
  4176. TypeSize,
  4177. BytesRead);
  4178. goto DumpTypeEnd;
  4179. }
  4180. //
  4181. // Resolve the type to something useful to dump.
  4182. //
  4183. Result = DbgrpResolveDumpType(Context,
  4184. &Type,
  4185. &DataStream,
  4186. &TypeSize,
  4187. &Address);
  4188. if (Result != 0) {
  4189. DbgOut("Error: could not resolve dump type %s.\n", Type->Name);
  4190. goto DumpTypeEnd;
  4191. }
  4192. //
  4193. // Print the values.
  4194. //
  4195. DbgOut("Dumping memory at 0x%08x\n", (ULONG)Address);
  4196. Result = DbgPrintType(Context,
  4197. Type,
  4198. DataStream,
  4199. TypeSize,
  4200. 0,
  4201. DEFAULT_RECURSION_DEPTH);
  4202. if (AddressIndex != ArgumentCount - 1) {
  4203. DbgOut("\n");
  4204. }
  4205. if (Result != 0) {
  4206. goto DumpTypeEnd;
  4207. }
  4208. }
  4209. //
  4210. // No address was specified, so print the type description.
  4211. //
  4212. } else {
  4213. DbgPrintTypeName(Type);
  4214. DbgOut(" = ");
  4215. DbgPrintTypeDescription(Type, 0, DEFAULT_RECURSION_DEPTH);
  4216. }
  4217. Result = 0;
  4218. DumpTypeEnd:
  4219. if (DataStream != NULL) {
  4220. free(DataStream);
  4221. }
  4222. return Result;
  4223. }
  4224. INT
  4225. DbgrpHighlightExecutingLine (
  4226. PDEBUGGER_CONTEXT Context,
  4227. ULONGLONG LineNumber
  4228. )
  4229. /*++
  4230. Routine Description:
  4231. This routine highlights the currently executing source line and scrolls to
  4232. it, or removes the highlight.
  4233. Arguments:
  4234. Context - Supplies the application context.
  4235. LineNumber - Supplies the one-based line number to highlight, or 0 to
  4236. disable highlighting.
  4237. Return Value:
  4238. 0 on success.
  4239. Non-zero on failure.
  4240. --*/
  4241. {
  4242. BOOL Result;
  4243. if (Context->SourceFile.LineNumber == LineNumber) {
  4244. return 0;
  4245. }
  4246. //
  4247. // Unhighlight the current line first.
  4248. //
  4249. if (Context->SourceFile.LineNumber != 0) {
  4250. UiHighlightExecutingLine(Context->SourceFile.LineNumber, FALSE);
  4251. }
  4252. //
  4253. // Set the new line number and notify the connected clients.
  4254. //
  4255. Context->SourceFile.LineNumber = LineNumber;
  4256. DbgrpServerNotifyClients(Context);
  4257. //
  4258. // If a new line is being highlighted, set it in the UI.
  4259. //
  4260. if (LineNumber != 0) {
  4261. Result = UiHighlightExecutingLine(Context->SourceFile.LineNumber, TRUE);
  4262. if (Result == FALSE) {
  4263. return -1;
  4264. }
  4265. }
  4266. return 0;
  4267. }
  4268. INT
  4269. DbgrpLoadSourceFile (
  4270. PDEBUGGER_CONTEXT Context,
  4271. PSTR Path,
  4272. PSTR *FoundPath,
  4273. PVOID *Contents,
  4274. PULONGLONG Size
  4275. )
  4276. /*++
  4277. Routine Description:
  4278. This routine loads a source file into memory.
  4279. Arguments:
  4280. Context - Supplies a pointer to the application context.
  4281. Path - Supplies a pointer to the path to load.
  4282. FoundPath - Supplies a pointer where a pointer to the path of the actual
  4283. file loaded will be returned. The path may be modified by the source
  4284. path list, so this represents the final found path.
  4285. Contents - Supplies a pointer where a pointer to the loaded file will be
  4286. returned on success. The caller is responsible for freeing this memory.
  4287. Size - Supplies a pointer where the size of the file will be returned on
  4288. success.
  4289. Return Value:
  4290. 0 on success.
  4291. Returns an error code on failure.
  4292. --*/
  4293. {
  4294. PLIST_ENTRY CurrentEntry;
  4295. PDEBUGGER_SOURCE_PATH Entry;
  4296. size_t PathLength;
  4297. PSTR Potential;
  4298. size_t PotentialSize;
  4299. INT Result;
  4300. *FoundPath = NULL;
  4301. *Contents = NULL;
  4302. *Size = 0;
  4303. PathLength = strlen(Path);
  4304. Potential = NULL;
  4305. PotentialSize = 0;
  4306. //
  4307. // Loop over all the source paths trying to find a file path that
  4308. // exists.
  4309. //
  4310. CurrentEntry = Context->SourcePathList.Next;
  4311. while (CurrentEntry != &(Context->SourcePathList)) {
  4312. Entry = LIST_VALUE(CurrentEntry, DEBUGGER_SOURCE_PATH, ListEntry);
  4313. CurrentEntry = CurrentEntry->Next;
  4314. //
  4315. // If the prefix is empty or matches this path, chop the prefix off,
  4316. // replace it with the path, and try to load that file.
  4317. //
  4318. if ((Entry->PrefixLength == 0) ||
  4319. (strncmp(Path, Entry->Prefix, Entry->PrefixLength) == 0)) {
  4320. PotentialSize = Entry->PathLength +
  4321. (PathLength - Entry->PrefixLength) + 1;
  4322. Potential = malloc(PotentialSize);
  4323. if (Potential == NULL) {
  4324. continue;
  4325. }
  4326. memcpy(Potential, Entry->Path, Entry->PathLength);
  4327. memcpy(Potential + Entry->PathLength,
  4328. Path + Entry->PrefixLength,
  4329. PathLength - Entry->PrefixLength);
  4330. Potential[PotentialSize - 1] = '\0';
  4331. Result = DbgrpLoadFile(Potential, Contents, Size);
  4332. if ((Context->Flags & DEBUGGER_FLAG_PRINT_SOURCE_LOADS) != 0) {
  4333. //
  4334. // Use printf directly here and not DbgOut as the standard out
  4335. // lock is held already.
  4336. //
  4337. printf("Load %s: %s\n", Potential, strerror(Result));
  4338. }
  4339. if (Result == 0) {
  4340. *FoundPath = Potential;
  4341. return 0;
  4342. }
  4343. free(Potential);
  4344. }
  4345. }
  4346. //
  4347. // Finally, try the source by itself.
  4348. //
  4349. PotentialSize = PathLength + 1;
  4350. Potential = strdup(Path);
  4351. if (Potential == NULL) {
  4352. return ENOMEM;
  4353. }
  4354. Result = DbgrpLoadFile(Potential, Contents, Size);
  4355. if ((Context->Flags & DEBUGGER_FLAG_PRINT_SOURCE_LOADS) != 0) {
  4356. //
  4357. // Use printf directly here and not DbgOut as the standard out lock is
  4358. // held already.
  4359. //
  4360. printf("Load %s: %s\n", Potential, strerror(Result));
  4361. }
  4362. if (Result == 0) {
  4363. *FoundPath = Potential;
  4364. return 0;
  4365. }
  4366. return Result;
  4367. }
  4368. INT
  4369. DbgrpAddSourcePath (
  4370. PDEBUGGER_CONTEXT Context,
  4371. PSTR PathString
  4372. )
  4373. /*++
  4374. Routine Description:
  4375. This routine adds a source path entry to the given application context.
  4376. Arguments:
  4377. Context - Supplies a pointer to the application context.
  4378. PathString - Supplies a pointer to the path string, which takes the form
  4379. prefix=path. If there is no equals sign, then the prefix is assumed to
  4380. be empty.
  4381. Return Value:
  4382. 0 on success.
  4383. Returns an error code on failure.
  4384. --*/
  4385. {
  4386. PDEBUGGER_SOURCE_PATH Entry;
  4387. PSTR Equals;
  4388. PSTR Path;
  4389. UINTN PathLength;
  4390. PSTR Prefix;
  4391. UINTN PrefixLength;
  4392. INT Status;
  4393. if (strlen(PathString) == 0) {
  4394. return 0;
  4395. }
  4396. Entry = NULL;
  4397. Prefix = NULL;
  4398. PrefixLength = 0;
  4399. Path = NULL;
  4400. PathLength = 0;
  4401. //
  4402. // Split on the equals.
  4403. //
  4404. Equals = strchr(PathString, '=');
  4405. if (Equals != NULL) {
  4406. if (Equals != PathString) {
  4407. PrefixLength = (UINTN)Equals - (UINTN)PathString;
  4408. Prefix = malloc(PrefixLength + 1);
  4409. if (Prefix == NULL) {
  4410. Status = ENOMEM;
  4411. goto AddSourcePathEnd;
  4412. }
  4413. memcpy(Prefix, PathString, PrefixLength);
  4414. Prefix[PrefixLength] = '\0';
  4415. }
  4416. PathLength = strlen(Equals + 1);
  4417. Path = strdup(Equals + 1);
  4418. } else {
  4419. PathLength = strlen(PathString);
  4420. Path = strdup(PathString);
  4421. }
  4422. if (Path == NULL) {
  4423. Status = ENOMEM;
  4424. goto AddSourcePathEnd;
  4425. }
  4426. //
  4427. // Don't bother adding dumb entries.
  4428. //
  4429. if ((PathLength == 0) && (PrefixLength == 0)) {
  4430. Status = 0;
  4431. goto AddSourcePathEnd;
  4432. }
  4433. //
  4434. // Create the entry and add it to the end.
  4435. //
  4436. Entry = malloc(sizeof(DEBUGGER_SOURCE_PATH));
  4437. if (Entry == NULL) {
  4438. Status = ENOMEM;
  4439. goto AddSourcePathEnd;
  4440. }
  4441. Entry->Prefix = Prefix;
  4442. Entry->PrefixLength = PrefixLength;
  4443. Entry->Path = Path;
  4444. Entry->PathLength = PathLength;
  4445. Path = NULL;
  4446. Prefix = NULL;
  4447. INSERT_BEFORE(&(Entry->ListEntry), &(Context->SourcePathList));
  4448. Status = 0;
  4449. AddSourcePathEnd:
  4450. if (Path != NULL) {
  4451. free(Path);
  4452. }
  4453. if (Prefix != NULL) {
  4454. free(Prefix);
  4455. }
  4456. return Status;
  4457. }
  4458. VOID
  4459. DbgrpDestroyAllSourcePaths (
  4460. PDEBUGGER_CONTEXT Context
  4461. )
  4462. /*++
  4463. Routine Description:
  4464. This routine destroys all source path entries in the given application
  4465. context.
  4466. Arguments:
  4467. Context - Supplies a pointer to the application context.
  4468. Return Value:
  4469. 0 on success.
  4470. Returns an error code on failure.
  4471. --*/
  4472. {
  4473. PDEBUGGER_SOURCE_PATH SourcePathEntry;
  4474. while (LIST_EMPTY(&(Context->SourcePathList)) == FALSE) {
  4475. SourcePathEntry = LIST_VALUE(Context->SourcePathList.Next,
  4476. DEBUGGER_SOURCE_PATH,
  4477. ListEntry);
  4478. LIST_REMOVE(&(SourcePathEntry->ListEntry));
  4479. DbgrpDestroySourcePath(SourcePathEntry);
  4480. }
  4481. return;
  4482. }
  4483. //
  4484. // --------------------------------------------------------- Internal Functions
  4485. //
  4486. INT
  4487. DbgrpSetBreakpointAtAddress (
  4488. PDEBUGGER_CONTEXT Context,
  4489. ULONGLONG Address,
  4490. PULONG OriginalValue
  4491. )
  4492. /*++
  4493. Routine Description:
  4494. This routine modifies the instruction stream to set a breakpoint at the
  4495. given address.
  4496. Arguments:
  4497. Context - Supplies a pointer to the application context.
  4498. Address - Supplies the target address to change to a breakpoint instruction.
  4499. OriginalValue - Supplies a pointer that receives the original contents
  4500. of memory that the breakpoint instruction replaced.
  4501. Return Value:
  4502. 0 on success.
  4503. Returns an error code on failure.
  4504. --*/
  4505. {
  4506. ULONG BreakInstruction;
  4507. ULONG BytesComplete;
  4508. ULONGLONG MemoryAddress;
  4509. INT Result;
  4510. ULONG Size;
  4511. MemoryAddress = Address;
  4512. if (Context->MachineType == MACHINE_TYPE_X86) {
  4513. BreakInstruction = X86_BREAK_INSTRUCTION;
  4514. Size = X86_BREAK_INSTRUCTION_LENGTH;
  4515. } else if (Context->MachineType == MACHINE_TYPE_ARM) {
  4516. if ((Address & ARM_THUMB_BIT) != 0) {
  4517. BreakInstruction = THUMB_BREAK_INSTRUCTION;
  4518. Size = THUMB_BREAK_INSTRUCTION_LENGTH;
  4519. MemoryAddress = Address & ~ARM_THUMB_BIT;
  4520. } else {
  4521. BreakInstruction = ARM_BREAK_INSTRUCTION;
  4522. Size = ARM_BREAK_INSTRUCTION_LENGTH;
  4523. }
  4524. } else {
  4525. DbgOut("Unknown machine type %d.\n", Context->MachineType);
  4526. return EINVAL;
  4527. }
  4528. //
  4529. // Read the original contents.
  4530. //
  4531. *OriginalValue = 0;
  4532. Result = DbgReadMemory(Context,
  4533. TRUE,
  4534. MemoryAddress,
  4535. Size,
  4536. OriginalValue,
  4537. &BytesComplete);
  4538. if ((Result != 0) || (BytesComplete != Size)) {
  4539. if (Result == 0) {
  4540. Result = EINVAL;
  4541. }
  4542. return Result;
  4543. }
  4544. //
  4545. // Write out the breakpoint instruction.
  4546. //
  4547. Result = DbgWriteMemory(Context,
  4548. TRUE,
  4549. MemoryAddress,
  4550. Size,
  4551. &BreakInstruction,
  4552. &BytesComplete);
  4553. if ((Result != 0) || (BytesComplete != Size)) {
  4554. if (Result == 0) {
  4555. Result = EINVAL;
  4556. }
  4557. //
  4558. // Attempt to restore the original value.
  4559. //
  4560. DbgrpClearBreakpointAtAddress(Context, Address, *OriginalValue);
  4561. return Result;
  4562. }
  4563. return 0;
  4564. }
  4565. INT
  4566. DbgrpClearBreakpointAtAddress (
  4567. PDEBUGGER_CONTEXT Context,
  4568. ULONGLONG Address,
  4569. ULONG OriginalValue
  4570. )
  4571. /*++
  4572. Routine Description:
  4573. This routine restores an instruction stream to its original form before a
  4574. breakpoint was inserted in it.
  4575. Arguments:
  4576. Context - Supplies a pointer to the application context.
  4577. Address - Supplies the target address to change to a breakpoint instruction.
  4578. OriginalValue - Supplies the original value returned when the breakpoint
  4579. was set.
  4580. Return Value:
  4581. 0 on success.
  4582. Returns an error code on failure.
  4583. --*/
  4584. {
  4585. ULONG BreakInstruction;
  4586. ULONG BytesComplete;
  4587. ULONG CurrentValue;
  4588. ULONGLONG MemoryAddress;
  4589. INT Result;
  4590. ULONG Size;
  4591. MemoryAddress = Address;
  4592. if (Context->MachineType == MACHINE_TYPE_X86) {
  4593. BreakInstruction = X86_BREAK_INSTRUCTION;
  4594. Size = X86_BREAK_INSTRUCTION_LENGTH;
  4595. } else if (Context->MachineType == MACHINE_TYPE_ARM) {
  4596. if ((Address & ARM_THUMB_BIT) != 0) {
  4597. BreakInstruction = THUMB_BREAK_INSTRUCTION;
  4598. Size = THUMB_BREAK_INSTRUCTION_LENGTH;
  4599. MemoryAddress = Address & ~ARM_THUMB_BIT;
  4600. } else {
  4601. BreakInstruction = ARM_BREAK_INSTRUCTION;
  4602. Size = ARM_BREAK_INSTRUCTION_LENGTH;
  4603. }
  4604. } else {
  4605. DbgOut("Unknown machine type %d.\n", Context->MachineType);
  4606. return EINVAL;
  4607. }
  4608. //
  4609. // Read what's there. If it's not a break instruction, warn the user that
  4610. // perhaps something's wrong.
  4611. //
  4612. CurrentValue = 0;
  4613. Result = DbgReadMemory(Context,
  4614. TRUE,
  4615. MemoryAddress,
  4616. Size,
  4617. &CurrentValue,
  4618. &BytesComplete);
  4619. if ((Result != 0) || (BytesComplete != Size)) {
  4620. if (Result == 0) {
  4621. Result = EINVAL;
  4622. }
  4623. goto ClearBreakpointAtAddressEnd;
  4624. }
  4625. if (CurrentValue == OriginalValue) {
  4626. goto ClearBreakpointAtAddressEnd;
  4627. }
  4628. //
  4629. // Write out the original instruction.
  4630. //
  4631. Result = DbgWriteMemory(Context,
  4632. TRUE,
  4633. MemoryAddress,
  4634. Size,
  4635. &OriginalValue,
  4636. &BytesComplete);
  4637. if ((Result != 0) || (BytesComplete != Size)) {
  4638. if (Result == 0) {
  4639. Result = EINVAL;
  4640. }
  4641. goto ClearBreakpointAtAddressEnd;
  4642. }
  4643. ClearBreakpointAtAddressEnd:
  4644. if ((Result != 0) &&
  4645. (CurrentValue != BreakInstruction) &&
  4646. (CurrentValue != OriginalValue)) {
  4647. DbgOut("Warning: Clearing a breakpoint at address %I64x, but instead "
  4648. "of finding the breakpoint instruction %x at that address, %x "
  4649. "was found instead.\n",
  4650. Address,
  4651. BreakInstruction,
  4652. CurrentValue);
  4653. }
  4654. return Result;
  4655. }
  4656. ULONG
  4657. DbgrpHandleBreakpoints (
  4658. PDEBUGGER_CONTEXT Context
  4659. )
  4660. /*++
  4661. Routine Description:
  4662. This routine is called when a new break notification comes in. It looks to
  4663. see if any breakpoints were hit, and if they were, backs up the instruction
  4664. pointer and fixes the instruction.
  4665. Arguments:
  4666. Context - Supplies a pointer to the application context.
  4667. Return Value:
  4668. Returns the breakpoint number of the breakpoint that was hit, or -1 if no
  4669. breakpoint was hit.
  4670. --*/
  4671. {
  4672. PDEBUGGER_BREAK_POINT Breakpoint;
  4673. ULONG BreakpointNumber;
  4674. PLIST_ENTRY CurrentEntry;
  4675. BOOL Result;
  4676. ULONG Size;
  4677. BreakpointNumber = -1;
  4678. //
  4679. // If there's a breakpoint to restore, do it. This code may restore the
  4680. // breakpoint (as opposed to the code in Continue) if the user requests a
  4681. // single step.
  4682. //
  4683. if (Context->BreakpointToRestore != NULL) {
  4684. Result = DbgrpSetBreakpointAtAddress(
  4685. Context,
  4686. Context->BreakpointToRestore->Address,
  4687. &(Context->BreakpointToRestore->OriginalValue));
  4688. if (Result != 0) {
  4689. DbgOut("Failed to restore breakpoint %d at %I64x.\n",
  4690. Context->BreakpointToRestore->Index,
  4691. Context->BreakpointToRestore->Address);
  4692. return -1;
  4693. }
  4694. Context->BreakpointToRestore = NULL;
  4695. }
  4696. //
  4697. // Check the breakpoint list to see if that's the cause of the break, and
  4698. // clean up after it if it is.
  4699. //
  4700. CurrentEntry = Context->BreakpointList.Next;
  4701. while (CurrentEntry != &(Context->BreakpointList)) {
  4702. Breakpoint = LIST_VALUE(CurrentEntry,
  4703. DEBUGGER_BREAK_POINT,
  4704. ListEntry);
  4705. if (Context->MachineType == MACHINE_TYPE_X86) {
  4706. Size = X86_BREAK_INSTRUCTION_LENGTH;
  4707. } else if (Context->MachineType == MACHINE_TYPE_ARM) {
  4708. if ((Breakpoint->Address & ARM_THUMB_BIT) != 0) {
  4709. Size = THUMB_BREAK_INSTRUCTION_LENGTH;
  4710. } else {
  4711. Size = ARM_BREAK_INSTRUCTION_LENGTH;
  4712. }
  4713. } else {
  4714. DbgOut("Unknown machine type %d.\n", Context->MachineType);
  4715. return -1;
  4716. }
  4717. //
  4718. // If the instruction pointer is exactly after the breakpoint address,
  4719. // then it must have stopped for the breakpoint. Hide the breakpoint
  4720. // from the user.
  4721. //
  4722. if ((Breakpoint->Enabled != FALSE) &&
  4723. (Breakpoint->Type == BreakpointTypeExecution) &&
  4724. (Context->CurrentEvent.BreakNotification.InstructionPointer ==
  4725. Breakpoint->Address + Size)) {
  4726. BreakpointNumber = Breakpoint->Index;
  4727. Result = DbgrpAdjustInstructionPointerForBreakpoint(
  4728. Context,
  4729. Breakpoint->OriginalValue);
  4730. if (Result != 0) {
  4731. DbgOut("Unable to adjust instruction pointer for breakpoint "
  4732. "%d.\n",
  4733. Breakpoint->Index);
  4734. goto HandleBreakpointsEnd;
  4735. }
  4736. //
  4737. // Put the right instruction back in memory.
  4738. //
  4739. Result = DbgrpClearBreakpointAtAddress(Context,
  4740. Breakpoint->Address,
  4741. Breakpoint->OriginalValue);
  4742. if (Result != 0) {
  4743. DbgOut("Error: Unable to temporarily clear breakpoint at "
  4744. "%08x.\n",
  4745. Breakpoint->Address);
  4746. goto HandleBreakpointsEnd;
  4747. }
  4748. //
  4749. // Mark this breakpoint as needing to be restored.
  4750. //
  4751. Context->BreakpointToRestore = Breakpoint;
  4752. break;
  4753. }
  4754. CurrentEntry = CurrentEntry->Next;
  4755. }
  4756. //
  4757. // Check the one-time break point.
  4758. //
  4759. if (Context->OneTimeBreakValid != FALSE) {
  4760. if (Context->MachineType == MACHINE_TYPE_X86) {
  4761. Size = X86_BREAK_INSTRUCTION_LENGTH;
  4762. } else if (Context->MachineType == MACHINE_TYPE_ARM) {
  4763. if ((Context->OneTimeBreakAddress & ARM_THUMB_BIT) != 0) {
  4764. Size = THUMB_BREAK_INSTRUCTION_LENGTH;
  4765. } else {
  4766. Size = ARM_BREAK_INSTRUCTION_LENGTH;
  4767. }
  4768. } else {
  4769. DbgOut("Unknown machine type %d.\n", Context->MachineType);
  4770. return -1;
  4771. }
  4772. if (Context->CurrentEvent.BreakNotification.InstructionPointer ==
  4773. Context->OneTimeBreakAddress + Size) {
  4774. Result = DbgrpAdjustInstructionPointerForBreakpoint(
  4775. Context,
  4776. Context->OneTimeBreakOriginalValue);
  4777. if (Result != 0) {
  4778. DbgOut("Error: Failed to adjust instruction pointer for one "
  4779. "time break.");
  4780. goto HandleBreakpointsEnd;
  4781. }
  4782. }
  4783. //
  4784. // Remove the one time breakpoint.
  4785. //
  4786. Result = DbgrpClearBreakpointAtAddress(
  4787. Context,
  4788. Context->OneTimeBreakAddress,
  4789. Context->OneTimeBreakOriginalValue);
  4790. if (Result != 0) {
  4791. DbgOut("Error: Failed to clear one time break point.\n");
  4792. goto HandleBreakpointsEnd;
  4793. }
  4794. Context->OneTimeBreakValid = FALSE;
  4795. }
  4796. HandleBreakpointsEnd:
  4797. return BreakpointNumber;
  4798. }
  4799. INT
  4800. DbgrpAdjustInstructionPointerForBreakpoint (
  4801. PDEBUGGER_CONTEXT Context,
  4802. ULONG OriginalValue
  4803. )
  4804. /*++
  4805. Routine Description:
  4806. This routine potentially moves the instruction pointer back and hides a
  4807. breakpoint instruction.
  4808. Arguments:
  4809. Context - Supplies a pointer to the application context.
  4810. OriginalValue - Supplies the original instruction stream contents at that
  4811. address.
  4812. Return Value:
  4813. 0 on success.
  4814. Returns an error code on failure.
  4815. --*/
  4816. {
  4817. PBREAK_NOTIFICATION BreakNotification;
  4818. ULONG ByteIndex;
  4819. PUSHORT Pointer16;
  4820. PULONG Pointer32;
  4821. BOOL Result;
  4822. ULONG Size;
  4823. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  4824. BreakNotification = &(Context->CurrentEvent.BreakNotification);
  4825. if (Context->MachineType == MACHINE_TYPE_X86) {
  4826. Size = X86_BREAK_INSTRUCTION_LENGTH;
  4827. //
  4828. // On x86, debug breaks are traps, meaning the instruction pointer
  4829. // points to the next instruction. Move the instruction pointer back
  4830. // and replace the original value in the first position.
  4831. //
  4832. BreakNotification->InstructionPointer -= Size;
  4833. BreakNotification->Registers.X86.Eip -= Size;
  4834. for (ByteIndex = sizeof(BreakNotification->InstructionStream) - 1;
  4835. ByteIndex > 0;
  4836. ByteIndex -= 1) {
  4837. BreakNotification->InstructionStream[ByteIndex] =
  4838. BreakNotification->InstructionStream[ByteIndex - 1];
  4839. }
  4840. BreakNotification->InstructionStream[0] = (UCHAR)OriginalValue;
  4841. } else if (Context->MachineType == MACHINE_TYPE_ARM) {
  4842. Size = ARM_BREAK_INSTRUCTION_LENGTH;
  4843. if ((BreakNotification->Registers.Arm.Cpsr & PSR_FLAG_THUMB) != 0) {
  4844. Size = THUMB_BREAK_INSTRUCTION_LENGTH;
  4845. Pointer16 = (PUSHORT)(&(BreakNotification->InstructionStream[0]));
  4846. Pointer16[1] = Pointer16[0];
  4847. Pointer16[0] = OriginalValue;
  4848. } else {
  4849. Pointer32 = (PULONG)(&(BreakNotification->InstructionStream[0]));
  4850. *Pointer32 = OriginalValue;
  4851. }
  4852. //
  4853. // On ARM, the break instruction also points to the next one. In this
  4854. // case though the instruction size is known, so there's no need to
  4855. // carefully shift the whole instruction stream buffer.
  4856. //
  4857. BreakNotification->InstructionPointer -= Size;
  4858. BreakNotification->Registers.Arm.R15Pc -= Size;
  4859. } else {
  4860. DbgOut("Unknown machine type %d.\n", Context->MachineType);
  4861. return FALSE;
  4862. }
  4863. //
  4864. // Reflect the register change in the target as well.
  4865. //
  4866. Result = DbgSetRegisters(Context, &(BreakNotification->Registers));
  4867. if (Result != 0) {
  4868. DbgOut("Error adjusting EIP on breakpoint instruction.\n");
  4869. return Result;
  4870. }
  4871. return 0;
  4872. }
  4873. INT
  4874. DbgrpProcessBreakNotification (
  4875. PDEBUGGER_CONTEXT Context
  4876. )
  4877. /*++
  4878. Routine Description:
  4879. This routine is called when a new break notification comes in.
  4880. Arguments:
  4881. Context - Supplies a pointer to the application context.
  4882. Return Value:
  4883. 0 on success.
  4884. Returns an error code on failure.
  4885. --*/
  4886. {
  4887. ULONG BreakpointNumber;
  4888. PBREAK_NOTIFICATION CurrentBreak;
  4889. BOOL ForceModuleUpdate;
  4890. BOOL InRange;
  4891. ULONGLONG InstructionPointer;
  4892. INT Result;
  4893. Context->TargetFlags &= ~DEBUGGER_TARGET_RUNNING;
  4894. //
  4895. // Synchronize symbols with the target.
  4896. //
  4897. CurrentBreak = &(Context->CurrentEvent.BreakNotification);
  4898. ForceModuleUpdate = FALSE;
  4899. if (Context->PreviousProcess != CurrentBreak->Process) {
  4900. ForceModuleUpdate = TRUE;
  4901. }
  4902. Context->PreviousProcess = CurrentBreak->Process;
  4903. Result = DbgrpValidateLoadedModules(Context,
  4904. CurrentBreak->LoadedModuleCount,
  4905. CurrentBreak->LoadedModuleSignature,
  4906. ForceModuleUpdate);
  4907. if (Result != 0) {
  4908. DbgOut("Failed to validate loaded modules.\n");
  4909. }
  4910. //
  4911. // Handle any breakpoint stuff.
  4912. //
  4913. BreakpointNumber = DbgrpHandleBreakpoints(Context);
  4914. InstructionPointer = CurrentBreak->InstructionPointer;
  4915. //
  4916. // Print the exception.
  4917. //
  4918. switch (CurrentBreak->Exception) {
  4919. case ExceptionDebugBreak:
  4920. case ExceptionSingleStep:
  4921. case ExceptionSignal:
  4922. if (CurrentBreak->Exception == ExceptionSignal) {
  4923. if (Context->CurrentEvent.SignalParameters.SignalNumber !=
  4924. SIGNAL_TRAP) {
  4925. DbgOut("Caught signal %d.\n",
  4926. Context->CurrentEvent.SignalParameters.SignalNumber);
  4927. }
  4928. }
  4929. if (BreakpointNumber != -1) {
  4930. DbgOut("Breakpoint %d hit!\n", BreakpointNumber);
  4931. //
  4932. // If the range step is valid, then only break if the address qualifies.
  4933. //
  4934. } else if (Context->RangeStepValid != FALSE) {
  4935. InRange = FALSE;
  4936. if ((InstructionPointer >=
  4937. Context->RangeStepParameters.BreakRangeMinimum) &&
  4938. (InstructionPointer <
  4939. Context->RangeStepParameters.BreakRangeMaximum)) {
  4940. InRange = TRUE;
  4941. if ((InstructionPointer >=
  4942. Context->RangeStepParameters.RangeHoleMinimum) &&
  4943. (InstructionPointer <
  4944. Context->RangeStepParameters.RangeHoleMaximum)) {
  4945. InRange = FALSE;
  4946. }
  4947. }
  4948. if (InRange == FALSE) {
  4949. Result = DbgrSingleStep(Context);
  4950. if (Result != 0) {
  4951. DbgOut("Failed to single step over %I64x.\n",
  4952. InstructionPointer);
  4953. goto ProcessBreakNotificationEnd;
  4954. }
  4955. Context->TargetFlags |= DEBUGGER_TARGET_RUNNING;
  4956. goto ProcessBreakNotificationEnd;
  4957. }
  4958. }
  4959. break;
  4960. case ExceptionAssertionFailure:
  4961. break;
  4962. case ExceptionAccessViolation:
  4963. DbgOut("\n *** Access violation: Error code 0x%08x ***\n",
  4964. CurrentBreak->ErrorCode);
  4965. break;
  4966. case ExceptionDoubleFault:
  4967. DbgOut("\n *** Double Fault ***\n");
  4968. break;
  4969. case ExceptionInvalid:
  4970. DbgOut("Error: Invalid exception received!\n");
  4971. break;
  4972. case ExceptionIllegalInstruction:
  4973. DbgOut("\n *** Illegal Instruction ***\n");
  4974. break;
  4975. case ExceptionUnknown:
  4976. DbgOut("Error: Unknown exception received!\n");
  4977. break;
  4978. default:
  4979. DbgOut("Error: Unknown exception %d received!\n",
  4980. CurrentBreak->Exception);
  4981. break;
  4982. }
  4983. //
  4984. // This break is really going to the user. Turn off any range stepping.
  4985. //
  4986. Context->RangeStepValid = FALSE;
  4987. //
  4988. // Set the globals indicating where to disassemble from and where
  4989. // the current frame is.
  4990. //
  4991. Context->DisassemblyAddress = InstructionPointer;
  4992. RtlCopyMemory(&(Context->FrameRegisters),
  4993. &(Context->CurrentEvent.BreakNotification.Registers),
  4994. sizeof(REGISTERS_UNION));
  4995. Context->CurrentFrame = 0;
  4996. Context->LastMemoryDump.Virtual = TRUE;
  4997. Context->LastMemoryDump.NextAddress = InstructionPointer;
  4998. Context->LastMemoryDump.Columns = 0;
  4999. Context->LastMemoryDump.TotalValues = 0;
  5000. Context->LastMemoryDump.PrintCharacters = TRUE;
  5001. //
  5002. // Load up the source file in the source window.
  5003. //
  5004. DbgrShowSourceAtAddress(Context, InstructionPointer);
  5005. //
  5006. // Print the instruction that's about to execute.
  5007. //
  5008. DbgrpPrintDisassembly(Context,
  5009. CurrentBreak->InstructionStream,
  5010. InstructionPointer,
  5011. 1,
  5012. &(Context->BreakInstructionLength));
  5013. Result = 0;
  5014. ProcessBreakNotificationEnd:
  5015. return Result;
  5016. }
  5017. INT
  5018. DbgrpRangeStep (
  5019. PDEBUGGER_CONTEXT Context,
  5020. PRANGE_STEP RangeStep
  5021. )
  5022. /*++
  5023. Routine Description:
  5024. This routine continues execution until a range of execution addresses is
  5025. reached.
  5026. Arguments:
  5027. Context - Supplies a pointer to the application context.
  5028. RangeStep - Supplies a pointer to the range to go to.
  5029. Return Value:
  5030. 0 on success.
  5031. Returns an error code on failure.
  5032. --*/
  5033. {
  5034. BOOL Result;
  5035. ULONG SignalToDeliver;
  5036. //
  5037. // First attempt to use the direct API method. The kernel debugger for
  5038. // instance has support for doing range stepping on its own so it doesn't
  5039. // have to send break notifications back and forth for every singls step.
  5040. //
  5041. SignalToDeliver = DbgGetSignalToDeliver(Context);
  5042. Result = DbgRangeStep(Context, RangeStep, SignalToDeliver);
  5043. if (Result == 0) {
  5044. return 0;
  5045. }
  5046. //
  5047. // The API is unavailable, so it's going to have to be done the old
  5048. // fashioned way.
  5049. //
  5050. RtlCopyMemory(&(Context->RangeStepParameters),
  5051. RangeStep,
  5052. sizeof(RANGE_STEP));
  5053. Context->RangeStepValid = TRUE;
  5054. return DbgrSingleStep(Context);
  5055. }
  5056. INT
  5057. DbgrpValidateLoadedModules (
  5058. PDEBUGGER_CONTEXT Context,
  5059. ULONG ModuleCount,
  5060. ULONGLONG Signature,
  5061. BOOL ForceReload
  5062. )
  5063. /*++
  5064. Routine Description:
  5065. This routine validates that the debugger's list of loaded modules is in sync
  5066. with the target. This routine may load or unload symbols.
  5067. Arguments:
  5068. Context - Supplies a pointer to the application context.
  5069. ModuleCount - Supplies the number of modules loaded in the target.
  5070. Signature - Supplies the total of the timestamps and loaded addresses of
  5071. all loaded modules. This is used esseentially as a quick way to
  5072. determine whether or not the list is in sync without transmitting much
  5073. data.
  5074. ForceReload - Supplies a boolean indicating if the module list should be
  5075. reloaded no matter what.
  5076. Return Value:
  5077. 0 on success.
  5078. Returns an error code on failure.
  5079. --*/
  5080. {
  5081. BOOL AlreadyPrinted;
  5082. ULONG BinaryNameLength;
  5083. PLIST_ENTRY CurrentEntry;
  5084. PLOADED_MODULE_ENTRY CurrentTargetModule;
  5085. PDEBUGGER_MODULE ExistingModule;
  5086. PSTR FriendlyName;
  5087. ULONG FriendlyNameLength;
  5088. PSTR FriendlyNameStart;
  5089. PMODULE_LIST_HEADER ModuleListHeader;
  5090. ULONG RemoteModuleCount;
  5091. INT Result;
  5092. AlreadyPrinted = FALSE;
  5093. ModuleListHeader = NULL;
  5094. //
  5095. // If the two checksum totals match, then the debugger symbols are in sync.
  5096. // No action is required.
  5097. //
  5098. if ((Signature == Context->ModuleList.Signature) &&
  5099. (ModuleCount == Context->ModuleList.ModuleCount) &&
  5100. (ForceReload == FALSE)) {
  5101. Result = 0;
  5102. goto ValidateLoadedModulesEnd;
  5103. }
  5104. //
  5105. // If the signature hasn't changed since the last time it wasn't in sync,
  5106. // don't bother going through all that again.
  5107. //
  5108. if ((Signature == Context->RemoteModuleListSignature) &&
  5109. (ForceReload == FALSE)) {
  5110. AlreadyPrinted = TRUE;
  5111. Result = 0;
  5112. goto ValidateLoadedModulesEnd;
  5113. }
  5114. //
  5115. // Request the loaded modules list header to determine how many modules
  5116. // are loaded in the target.
  5117. //
  5118. Result = DbgGetLoadedModuleList(Context, &ModuleListHeader);
  5119. if (Result != 0) {
  5120. DbgOut("Error: Failed to get loaded module list.\n");
  5121. goto ValidateLoadedModulesEnd;
  5122. }
  5123. Signature = ModuleListHeader->Signature;
  5124. RemoteModuleCount = ModuleListHeader->ModuleCount;
  5125. CurrentTargetModule = (PLOADED_MODULE_ENTRY)(ModuleListHeader + 1);
  5126. //
  5127. // Mark all modules as unloaded.
  5128. //
  5129. CurrentEntry = Context->ModuleList.ModulesHead.Next;
  5130. while (CurrentEntry != &(Context->ModuleList.ModulesHead)) {
  5131. ExistingModule = LIST_VALUE(CurrentEntry,
  5132. DEBUGGER_MODULE,
  5133. ListEntry);
  5134. ExistingModule->Loaded = FALSE;
  5135. CurrentEntry = CurrentEntry->Next;
  5136. }
  5137. //
  5138. // Get all modules. For each module, attempt to match it to an existing
  5139. // loaded module. If none is found, attempt to load the module.
  5140. //
  5141. while (RemoteModuleCount != 0) {
  5142. //
  5143. // Create a friendly name from the binary name by chopping off the
  5144. // extension and any path stuff at the beginning.
  5145. //
  5146. assert(CurrentTargetModule->StructureSize >=
  5147. sizeof(LOADED_MODULE_ENTRY));
  5148. BinaryNameLength = CurrentTargetModule->StructureSize -
  5149. sizeof(LOADED_MODULE_ENTRY) +
  5150. (ANYSIZE_ARRAY * sizeof(CHAR));
  5151. DbgpGetFriendlyName(CurrentTargetModule->BinaryName,
  5152. BinaryNameLength,
  5153. &FriendlyNameStart,
  5154. &FriendlyNameLength);
  5155. FriendlyName = malloc(FriendlyNameLength + 1);
  5156. if (FriendlyName == NULL) {
  5157. DbgOut("Error: Failed to allocate %d bytes for friendly name.\n",
  5158. FriendlyNameLength + 1);
  5159. Result = ENOMEM;
  5160. goto ValidateLoadedModulesEnd;
  5161. }
  5162. RtlStringCopy(FriendlyName, FriendlyNameStart, FriendlyNameLength + 1);
  5163. FriendlyName[FriendlyNameLength] = '\0';
  5164. ExistingModule = DbgpFindModuleFromEntry(Context, CurrentTargetModule);
  5165. if (ExistingModule != NULL) {
  5166. ExistingModule->Loaded = TRUE;
  5167. } else {
  5168. DbgpLoadModule(Context,
  5169. CurrentTargetModule->BinaryName,
  5170. FriendlyName,
  5171. CurrentTargetModule->BaseAddress,
  5172. CurrentTargetModule->Size,
  5173. CurrentTargetModule->LowestAddress,
  5174. CurrentTargetModule->Timestamp,
  5175. CurrentTargetModule->Process);
  5176. }
  5177. free(FriendlyName);
  5178. RemoteModuleCount -= 1;
  5179. CurrentTargetModule =
  5180. (PLOADED_MODULE_ENTRY)((PUCHAR)CurrentTargetModule +
  5181. CurrentTargetModule->StructureSize);
  5182. }
  5183. //
  5184. // Unload any modules no longer in the list.
  5185. //
  5186. CurrentEntry = Context->ModuleList.ModulesHead.Next;
  5187. while (CurrentEntry != &(Context->ModuleList.ModulesHead)) {
  5188. ExistingModule = LIST_VALUE(CurrentEntry,
  5189. DEBUGGER_MODULE,
  5190. ListEntry);
  5191. CurrentEntry = CurrentEntry->Next;
  5192. if (ExistingModule->Loaded == FALSE) {
  5193. DbgrpUnloadModule(Context, ExistingModule, TRUE);
  5194. }
  5195. }
  5196. Context->RemoteModuleListSignature = Signature;
  5197. Result = 0;
  5198. ValidateLoadedModulesEnd:
  5199. if (Result == 0) {
  5200. if ((Context->ModuleList.Signature != Signature) &&
  5201. (AlreadyPrinted == FALSE)) {
  5202. DbgOut("*** Module signatures don't match after synchronization. "
  5203. "***\nDebugger: 0x%I64x, Target: 0x%I64x\n",
  5204. Context->ModuleList.Signature,
  5205. Signature);
  5206. }
  5207. }
  5208. if (ModuleListHeader != NULL) {
  5209. free(ModuleListHeader);
  5210. }
  5211. return Result;
  5212. }
  5213. VOID
  5214. DbgrpUnloadModule (
  5215. PDEBUGGER_CONTEXT Context,
  5216. PDEBUGGER_MODULE Module,
  5217. BOOL Verbose
  5218. )
  5219. /*++
  5220. Routine Description:
  5221. This routine unloads a module, removing its binary and symbol information.
  5222. Arguments:
  5223. Context - Supplies a pointer to the application context.
  5224. Module - Supplies a pointer to the loaded module to unload. Once this
  5225. function is called, this pointer will no longer be valid.
  5226. Verbose - Supplies a flag indicating whether or not this unload should be
  5227. printed to the user.
  5228. Return Value:
  5229. None.
  5230. --*/
  5231. {
  5232. //
  5233. // Subtract the checksum out of the checksum total, and remove the module
  5234. // from the list.
  5235. //
  5236. Context->ModuleList.Signature -= Module->Timestamp + Module->LowestAddress;
  5237. Context->ModuleList.ModuleCount -= 1;
  5238. LIST_REMOVE(&(Module->ListEntry));
  5239. if (Verbose != FALSE) {
  5240. DbgOut("Module unloaded: %s.\n", Module->ModuleName);
  5241. }
  5242. //
  5243. // Free all the symbols.
  5244. //
  5245. if (Module->Symbols != NULL) {
  5246. DbgUnloadSymbols(Module->Symbols);
  5247. Module->Symbols = NULL;
  5248. }
  5249. if (Module->Filename != NULL) {
  5250. free(Module->Filename);
  5251. }
  5252. if (Module->ModuleName != NULL) {
  5253. free(Module->ModuleName);
  5254. }
  5255. free(Module);
  5256. return;
  5257. }
  5258. VOID
  5259. DbgrpUnloadAllModules (
  5260. PDEBUGGER_CONTEXT Context,
  5261. BOOL Verbose
  5262. )
  5263. /*++
  5264. Routine Description:
  5265. This routine unloads all modules and symbols from the debugger.
  5266. Arguments:
  5267. Context - Supplies a pointer to the application context.
  5268. Verbose - Supplies a flag indicating whether or not this unload should be
  5269. printed to the user.
  5270. Return Value:
  5271. Returns TRUE if information was printed, or FALSE if module information
  5272. could not be found for the address.
  5273. --*/
  5274. {
  5275. PLIST_ENTRY CurrentEntry;
  5276. PDEBUGGER_MODULE CurrentModule;
  5277. if (Context->ModuleList.ModuleCount == 0) {
  5278. assert(Context->ModuleList.Signature == 0);
  5279. assert(Context->RemoteModuleListSignature == 0);
  5280. return;
  5281. }
  5282. CurrentEntry = Context->ModuleList.ModulesHead.Next;
  5283. while (CurrentEntry != &(Context->ModuleList.ModulesHead)) {
  5284. CurrentModule = LIST_VALUE(CurrentEntry, DEBUGGER_MODULE, ListEntry);
  5285. CurrentEntry = CurrentEntry->Next;
  5286. DbgrpUnloadModule(Context, CurrentModule, Verbose);
  5287. }
  5288. assert(Context->ModuleList.ModuleCount == 0);
  5289. assert(Context->ModuleList.Signature == 0);
  5290. Context->RemoteModuleListSignature = 0;
  5291. return;
  5292. }
  5293. INT
  5294. DbgrpPrintDisassembly (
  5295. PDEBUGGER_CONTEXT Context,
  5296. PBYTE InstructionStream,
  5297. ULONGLONG InstructionPointer,
  5298. ULONG InstructionCount,
  5299. PULONG BytesDecoded
  5300. )
  5301. /*++
  5302. Routine Description:
  5303. This routine prints the disassembly of one or more instructions.
  5304. Arguments:
  5305. Context - Supplies a pointer to the application context.
  5306. InstructionStream - Supplies a pointer to the binary instruction stream to
  5307. disassemble. It is assumed that this buffer contains enough bytes to
  5308. completely disassemble the specified number of instructions.
  5309. InstructionPointer - Supplies the location in the target's memory where
  5310. these instructions reside.
  5311. InstructionCount - Supplies the number of instructions to disassemble.
  5312. BytesDecoded - Supplies a pointer where the number of bytes decoded from the
  5313. instruction stream is returned.
  5314. Return Value:
  5315. 0 on success.
  5316. Returns an error code on failure.
  5317. --*/
  5318. {
  5319. ULONG CurrentInstructionByte;
  5320. DISASSEMBLED_INSTRUCTION Disassembly;
  5321. PSTR DisassemblyBuffer;
  5322. MACHINE_LANGUAGE Language;
  5323. ULONGLONG OperandAddress;
  5324. INT Result;
  5325. if (BytesDecoded != NULL) {
  5326. *BytesDecoded = 0;
  5327. }
  5328. DisassemblyBuffer = malloc(200);
  5329. if (DisassemblyBuffer == NULL) {
  5330. Result = ENOMEM;
  5331. goto PrintDisassemblyEnd;
  5332. }
  5333. switch (Context->MachineType) {
  5334. case MACHINE_TYPE_X86:
  5335. Language = MachineLanguageX86;
  5336. break;
  5337. case MACHINE_TYPE_ARM:
  5338. Language = MachineLanguageArm;
  5339. if ((InstructionPointer & ARM_THUMB_BIT) != 0) {
  5340. Language = MachineLanguageThumb2;
  5341. }
  5342. break;
  5343. default:
  5344. DbgOut("Error: Unknown machine type %d.\n", Context->MachineType);
  5345. Result = EINVAL;
  5346. goto PrintDisassemblyEnd;
  5347. }
  5348. Result = DbgPrintAddressSymbol(Context, InstructionPointer);
  5349. if (Result == 0) {
  5350. DbgOut(":\n");
  5351. }
  5352. while (InstructionCount > 0) {
  5353. //
  5354. // Print the instruction pointer and attempt to decode the instruction.
  5355. //
  5356. DbgOut("%08I64x ", InstructionPointer);
  5357. Result = DbgDisassemble(InstructionPointer,
  5358. InstructionStream,
  5359. DisassemblyBuffer,
  5360. 200,
  5361. &Disassembly,
  5362. Language);
  5363. if (Result == FALSE) {
  5364. DbgOut("*** Error decoding instruction ***\n");
  5365. Result = EINVAL;
  5366. goto PrintDisassemblyEnd;
  5367. }
  5368. if ((Language == MachineLanguageArm) ||
  5369. (Language == MachineLanguageThumb2)) {
  5370. if (Disassembly.BinaryLength == 2) {
  5371. DbgOut("%04x ", *((PUSHORT)InstructionStream));
  5372. } else {
  5373. assert(Disassembly.BinaryLength == 4);
  5374. if (Language == MachineLanguageThumb2) {
  5375. DbgOut("%04x %04x ",
  5376. *((PUSHORT)InstructionStream),
  5377. *((PUSHORT)InstructionStream + 1));
  5378. } else {
  5379. DbgOut("%08x ", *((PULONG)InstructionStream));
  5380. }
  5381. }
  5382. }
  5383. DbgOut("%s\t", Disassembly.Mnemonic);
  5384. //
  5385. // Print the first (destination) operand if one exists.
  5386. //
  5387. if (Disassembly.DestinationOperand != NULL) {
  5388. if ((Disassembly.AddressIsDestination != FALSE) &&
  5389. (Disassembly.AddressIsValid != FALSE)) {
  5390. OperandAddress = Disassembly.OperandAddress;
  5391. Result = DbgPrintAddressSymbol(Context, OperandAddress);
  5392. if (Result == 0) {
  5393. DbgOut(" ");
  5394. }
  5395. if (Disassembly.DestinationOperand[0] == '[') {
  5396. DbgOut("%s", Disassembly.DestinationOperand);
  5397. } else {
  5398. DbgOut("%s (0x%08I64x)",
  5399. Disassembly.DestinationOperand,
  5400. OperandAddress);
  5401. }
  5402. } else {
  5403. DbgOut("%s", Disassembly.DestinationOperand);
  5404. }
  5405. }
  5406. //
  5407. // Print the second (source) operand if one exists.
  5408. //
  5409. if (Disassembly.SourceOperand != NULL) {
  5410. DbgOut(", ");
  5411. if ((Disassembly.AddressIsDestination == FALSE) &&
  5412. (Disassembly.AddressIsValid != FALSE)) {
  5413. OperandAddress = Disassembly.OperandAddress;
  5414. Result = DbgPrintAddressSymbol(Context, OperandAddress);
  5415. if (Result == 0) {
  5416. DbgOut(" ");
  5417. }
  5418. if (Disassembly.SourceOperand[0] == '[') {
  5419. DbgOut("%s", Disassembly.SourceOperand);
  5420. } else {
  5421. DbgOut("%s (0x%08I64x)",
  5422. Disassembly.SourceOperand,
  5423. OperandAddress);
  5424. }
  5425. } else {
  5426. DbgOut("%s", Disassembly.SourceOperand);
  5427. }
  5428. }
  5429. //
  5430. // Print the third operand if one exists. This operand will not have a
  5431. // symbol associated with it.
  5432. //
  5433. if (Disassembly.ThirdOperand != NULL) {
  5434. DbgOut(", %s", Disassembly.ThirdOperand);
  5435. }
  5436. //
  5437. // Print the fourth operand if one exists. This one also will not have
  5438. // a symbol associated with it.
  5439. //
  5440. if (Disassembly.FourthOperand != NULL) {
  5441. DbgOut(", %s", Disassembly.FourthOperand);
  5442. }
  5443. //
  5444. // For x86 disassembly, print out the bytes of the actual instruction.
  5445. //
  5446. if (Language == MachineLanguageX86) {
  5447. DbgOut("\t; ");
  5448. for (CurrentInstructionByte = 0;
  5449. CurrentInstructionByte < Disassembly.BinaryLength;
  5450. CurrentInstructionByte += 1) {
  5451. DbgOut("%02x", *InstructionStream);
  5452. InstructionStream += 1;
  5453. }
  5454. } else {
  5455. InstructionStream += Disassembly.BinaryLength;
  5456. }
  5457. DbgOut("\n");
  5458. //
  5459. // Update the variables and loop.
  5460. //
  5461. if (BytesDecoded != NULL) {
  5462. *BytesDecoded += Disassembly.BinaryLength;
  5463. }
  5464. InstructionPointer += Disassembly.BinaryLength;
  5465. InstructionCount -= 1;
  5466. }
  5467. Result = 0;
  5468. PrintDisassemblyEnd:
  5469. if (DisassemblyBuffer != NULL) {
  5470. free(DisassemblyBuffer);
  5471. }
  5472. return Result;
  5473. }
  5474. PSTR
  5475. DbgrpCreateFullPath (
  5476. PSOURCE_FILE_SYMBOL Source
  5477. )
  5478. /*++
  5479. Routine Description:
  5480. This routine makes a full source file path from the given source file. The
  5481. caller must remember to free memory allocated here.
  5482. Arguments:
  5483. Source - Supplies a pointer to the source line symbol.
  5484. Return Value:
  5485. Returns a pointer to string containing the full path, or NULL if there was
  5486. an error. This memory has been allocated in the function, and must be freed
  5487. by the caller.
  5488. --*/
  5489. {
  5490. UINTN DirectoryLength;
  5491. UINTN FileLength;
  5492. ULONG Index;
  5493. CHAR LastCharacter;
  5494. BOOL NeedsSlash;
  5495. PSTR Path;
  5496. ULONG PathLength;
  5497. //
  5498. // Validate parameters.
  5499. //
  5500. if ((Source == NULL) || (Source->SourceFile == NULL)) {
  5501. return NULL;
  5502. }
  5503. DirectoryLength = 0;
  5504. FileLength = strlen(Source->SourceFile);
  5505. PathLength = FileLength;
  5506. NeedsSlash = FALSE;
  5507. //
  5508. // Get the length of the full path, depending on whether or not a directory
  5509. // was specified.
  5510. //
  5511. if (Source->SourceDirectory != NULL) {
  5512. DirectoryLength = strlen(Source->SourceDirectory);
  5513. PathLength += DirectoryLength;
  5514. if (DirectoryLength != 0) {
  5515. LastCharacter = Source->SourceDirectory[DirectoryLength - 1];
  5516. if ((LastCharacter != '/') && (LastCharacter != '\\')) {
  5517. NeedsSlash = TRUE;
  5518. PathLength += 1;
  5519. }
  5520. }
  5521. }
  5522. //
  5523. // Allocate the buffer.
  5524. //
  5525. Path = malloc(PathLength + 1);
  5526. if (Path == NULL) {
  5527. return NULL;
  5528. }
  5529. if (Source->SourceDirectory != NULL) {
  5530. memcpy(Path, Source->SourceDirectory, DirectoryLength);
  5531. if (NeedsSlash != FALSE) {
  5532. Path[DirectoryLength] = '/';
  5533. DirectoryLength += 1;
  5534. }
  5535. }
  5536. memcpy(Path + DirectoryLength, Source->SourceFile, FileLength + 1);
  5537. //
  5538. // Change any backslashes to forward slashes.
  5539. //
  5540. for (Index = 0; Index < PathLength; Index += 1) {
  5541. if (Path[Index] == '\\') {
  5542. Path[Index] = '/';
  5543. }
  5544. }
  5545. return Path;
  5546. }
  5547. INT
  5548. DbgrpPrintMemory (
  5549. PDEBUGGER_CONTEXT Context,
  5550. ULONGLONG Address,
  5551. BOOL VirtualAddress,
  5552. ULONG TypeSize,
  5553. ULONG Columns,
  5554. ULONG TotalValues,
  5555. BOOL PrintCharacters
  5556. )
  5557. /*++
  5558. Routine Description:
  5559. This routine prints the contents of memory in a formatted way.
  5560. Arguments:
  5561. Context - Supplies a pointer to the application context.
  5562. Address - Supplies the address of the memory in the debuggee to print.
  5563. VirtualAddress - Supplies a flag indicating whether or not Address is a
  5564. virtual address (TRUE) or physical address (FALSE).
  5565. TypeSize - Supplies the unit of integers to print, in bytes. Valid values
  5566. are 1, 2, 4, and 8.
  5567. Columns - Supplies the number of columns to print for each line. To use a
  5568. default value, set this parameter to 0.
  5569. TotalValues - Supplies the total number of integers to print (the total
  5570. amount of memory will depend on the type size as well). To use a default
  5571. value, set this parameter to 0.
  5572. PrintCharacters - Supplies a flag indicating whether or not to print
  5573. characters alongside the integers.
  5574. Return Value:
  5575. 0 on success.
  5576. Returns an error code on failure.
  5577. --*/
  5578. {
  5579. PUCHAR Buffer;
  5580. PUCHAR CharacterPointer;
  5581. ULONG ColumnIndex;
  5582. ULONGLONG CurrentAddress;
  5583. PUCHAR CurrentByte;
  5584. PUCHAR InvalidBytes;
  5585. ULONG ItemsPrinted;
  5586. INT Result;
  5587. ULONG ValidBytes;
  5588. Buffer = NULL;
  5589. ItemsPrinted = 0;
  5590. //
  5591. // If the number of columns was 0, then pick a default number of columns to
  5592. // print.
  5593. //
  5594. if (Columns == 0) {
  5595. Columns = 2;
  5596. if (TypeSize == 4) {
  5597. Columns *= 2;
  5598. }
  5599. if (TypeSize == 2) {
  5600. Columns *= 4;
  5601. }
  5602. if (TypeSize == 1) {
  5603. Columns *= 8;
  5604. }
  5605. }
  5606. //
  5607. // If the number of items was 0, then pick a default number of items to
  5608. // print.
  5609. //
  5610. if (TotalValues == 0) {
  5611. TotalValues = Columns * DEFAULT_MEMORY_PRINT_ROWS;
  5612. }
  5613. //
  5614. // Allocate a buffer big enough to hold all the values.
  5615. //
  5616. Buffer = malloc(TotalValues * TypeSize);
  5617. if (Buffer == NULL) {
  5618. Result = ENOMEM;
  5619. goto PrintMemoryEnd;
  5620. }
  5621. //
  5622. // Read the memory in from the debuggee.
  5623. //
  5624. Result = DbgReadMemory(Context,
  5625. VirtualAddress,
  5626. Address,
  5627. TotalValues * TypeSize,
  5628. Buffer,
  5629. &ValidBytes);
  5630. if (Result != 0) {
  5631. DbgOut("Error retrieving memory!\n");
  5632. goto PrintMemoryEnd;
  5633. }
  5634. InvalidBytes = Buffer + ValidBytes;
  5635. //
  5636. // Print every value.
  5637. //
  5638. ColumnIndex = 0;
  5639. CurrentAddress = Address;
  5640. CurrentByte = Buffer;
  5641. CharacterPointer = Buffer;
  5642. for (ItemsPrinted = 0; ItemsPrinted < TotalValues; ItemsPrinted += 1) {
  5643. //
  5644. // If this is the beginning of a new column, print the address.
  5645. //
  5646. if (ColumnIndex == 0) {
  5647. DbgOut("%08I64x: ", CurrentAddress);
  5648. }
  5649. //
  5650. // Depending on the size, print the value.
  5651. //
  5652. if (TypeSize == 8) {
  5653. if (CurrentByte + 7 >= InvalidBytes) {
  5654. DbgOut("????????`???????? ");
  5655. } else {
  5656. DbgOut("%08x`%08x ",
  5657. *((PULONG)CurrentByte + 1),
  5658. *((PULONG)CurrentByte));
  5659. }
  5660. } else if (TypeSize == 4) {
  5661. if (CurrentByte + 3 >= InvalidBytes) {
  5662. DbgOut("???????? ");
  5663. } else {
  5664. DbgOut("%08x ", *((PULONG)CurrentByte));
  5665. }
  5666. } else if (TypeSize == 2) {
  5667. if (CurrentByte + 1 >= InvalidBytes) {
  5668. DbgOut("???? ");
  5669. } else {
  5670. DbgOut("%04x ", *((PUSHORT)CurrentByte));
  5671. }
  5672. } else if (TypeSize == 1) {
  5673. if (ColumnIndex == 7) {
  5674. if (CurrentByte >= InvalidBytes) {
  5675. DbgOut("?""?-");
  5676. } else {
  5677. DbgOut("%02x-", *CurrentByte);
  5678. }
  5679. } else {
  5680. if (CurrentByte >= InvalidBytes) {
  5681. DbgOut("?? ");
  5682. } else {
  5683. DbgOut("%02x ", *CurrentByte);
  5684. }
  5685. }
  5686. }
  5687. //
  5688. // Advance all the pointers and whatnot.
  5689. //
  5690. CurrentByte += TypeSize;
  5691. ColumnIndex += 1;
  5692. CurrentAddress += TypeSize;
  5693. //
  5694. // If this is the last column in the row, and characters are to be
  5695. // printed, print them.
  5696. //
  5697. if (ColumnIndex == Columns) {
  5698. if (PrintCharacters != FALSE) {
  5699. DbgOut(" ");
  5700. for (ColumnIndex = 0;
  5701. ColumnIndex < (Columns * TypeSize);
  5702. ColumnIndex += 1) {
  5703. //
  5704. // If the character is printable, print it. Otherwise, print
  5705. // a dot. If the memory doesn't exist, print a question
  5706. // mark.
  5707. //
  5708. if (CharacterPointer >= InvalidBytes) {
  5709. DbgOut("?");
  5710. } else if (*CharacterPointer < 0x20) {
  5711. DbgOut(".");
  5712. } else {
  5713. DbgOut("%c", *CharacterPointer);
  5714. }
  5715. CharacterPointer += 1;
  5716. }
  5717. assert(CharacterPointer == CurrentByte);
  5718. }
  5719. ColumnIndex = 0;
  5720. DbgOut("\n");
  5721. }
  5722. }
  5723. //
  5724. // Print one more newline if a column was not complete.
  5725. //
  5726. if (ColumnIndex != 0) {
  5727. DbgOut("\n");
  5728. }
  5729. Result = 0;
  5730. PrintMemoryEnd:
  5731. if (Buffer != NULL) {
  5732. free(Buffer);
  5733. }
  5734. return Result;
  5735. }
  5736. VOID
  5737. DbgrpProcessShutdown (
  5738. PDEBUGGER_CONTEXT Context
  5739. )
  5740. /*++
  5741. Routine Description:
  5742. This routine processes a shutdown event coming from the debuggee.
  5743. Arguments:
  5744. Context - Supplies a pointer to the application context.
  5745. Return Value:
  5746. None.
  5747. --*/
  5748. {
  5749. assert(Context->CurrentEvent.Type == DebuggerEventShutdown);
  5750. switch (Context->CurrentEvent.ShutdownNotification.ShutdownType) {
  5751. case ShutdownTypeTransition:
  5752. DbgOut("Target disconnected.\n");
  5753. DbgrConnect(Context);
  5754. break;
  5755. case ShutdownTypeExit:
  5756. DbgOut("Process %x exited with status %d.\n",
  5757. Context->CurrentEvent.ShutdownNotification.Process,
  5758. Context->CurrentEvent.ShutdownNotification.ExitStatus);
  5759. break;
  5760. case ShutdownTypeSynchronizationLost:
  5761. DbgOut("Resynchronizing...\n");
  5762. DbgrConnect(Context);
  5763. break;
  5764. default:
  5765. DbgOut("Shutdown occurred, unknown reason %d.\n",
  5766. Context->CurrentEvent.ShutdownNotification.ShutdownType);
  5767. break;
  5768. }
  5769. if (Context->CurrentEvent.ShutdownNotification.UnloadAllSymbols != FALSE) {
  5770. DbgrpUnloadAllModules(Context, TRUE);
  5771. }
  5772. return;
  5773. }
  5774. PDEBUGGER_MODULE
  5775. DbgpLoadModule (
  5776. PDEBUGGER_CONTEXT Context,
  5777. PSTR BinaryName,
  5778. PSTR FriendlyName,
  5779. ULONGLONG BaseAddress,
  5780. ULONGLONG Size,
  5781. ULONGLONG LowestAddress,
  5782. ULONGLONG Timestamp,
  5783. ULONG Process
  5784. )
  5785. /*++
  5786. Routine Description:
  5787. This routine loads a new module and adds it to the debugger's loaded module
  5788. list.
  5789. Arguments:
  5790. Context - Supplies a pointer to the application context.
  5791. BinaryName - Supplies the name of the binary to load. This routine will use
  5792. the known symbol path to try to find this binary.
  5793. FriendlyName - Supplies the friendly name of the module.
  5794. BaseAddress - Supplies the base address to load the module at.
  5795. Size - Supplies the size of the module.
  5796. LowestAddress - Supplies the lowest address of the module in memory.
  5797. Timestamp - Supplies the timestamp of the module.
  5798. Checksum - Supplies the required checksum of the module.
  5799. Process - Supplies the ID of the process this module is specific to.
  5800. Return Value:
  5801. Returns a pointer to the loaded module on success.
  5802. NULL on failure.
  5803. --*/
  5804. {
  5805. PSTR BackupPotential;
  5806. ULONGLONG BackupPotentialTimestamp;
  5807. PSTR CurrentPath;
  5808. ULONG CurrentPathLength;
  5809. ULONGLONG Delta;
  5810. IMAGE_MACHINE_TYPE ImageMachineType;
  5811. UINTN LastIndex;
  5812. ULONG NameIndex;
  5813. ULONG NameLength;
  5814. PDEBUGGER_MODULE NewModule;
  5815. PSTR OriginalBinaryName;
  5816. ULONG PathCount;
  5817. ULONG PathIndex;
  5818. PSTR PotentialBinary;
  5819. ULONGLONG PotentialTimestamp;
  5820. BOOL Result;
  5821. struct stat Stat;
  5822. INT Status;
  5823. time_t Time;
  5824. char *TimeString;
  5825. struct tm *TimeStructure;
  5826. OriginalBinaryName = BinaryName;
  5827. BackupPotential = NULL;
  5828. BackupPotentialTimestamp = 0;
  5829. //
  5830. // Determine the image machine type.
  5831. //
  5832. switch (Context->MachineType) {
  5833. case MACHINE_TYPE_X86:
  5834. ImageMachineType = ImageMachineTypeX86;
  5835. break;
  5836. case MACHINE_TYPE_ARM:
  5837. ImageMachineType = ImageMachineTypeArm32;
  5838. break;
  5839. default:
  5840. ImageMachineType = ImageMachineTypeUnknown;
  5841. break;
  5842. }
  5843. //
  5844. // Create an entry for the module.
  5845. //
  5846. NewModule = malloc(sizeof(DEBUGGER_MODULE));
  5847. if (NewModule == NULL) {
  5848. Result = FALSE;
  5849. goto LoadModuleEnd;
  5850. }
  5851. memset(NewModule, 0, sizeof(DEBUGGER_MODULE));
  5852. NameLength = strlen(BinaryName);
  5853. if (NameLength == 0) {
  5854. Result = FALSE;
  5855. goto LoadModuleEnd;
  5856. }
  5857. PathCount = Context->SymbolPathCount;
  5858. //
  5859. // Find the base name to stick on the path.
  5860. //
  5861. NameIndex = NameLength - 1;
  5862. while ((NameIndex != 0) && (BinaryName[NameIndex - 1] != '/') &&
  5863. (BinaryName[NameIndex - 1] != '\\')) {
  5864. NameIndex -= 1;
  5865. }
  5866. BinaryName += NameIndex;
  5867. NameLength -= NameIndex;
  5868. //
  5869. // Attempt to load the binary using each path in the symbol path.
  5870. //
  5871. for (PathIndex = 0; PathIndex < PathCount; PathIndex += 1) {
  5872. CurrentPath = Context->SymbolPath[PathIndex];
  5873. CurrentPathLength = strlen(CurrentPath);
  5874. //
  5875. // Create the full binary path.
  5876. //
  5877. PotentialBinary = malloc(CurrentPathLength + NameLength + 2);
  5878. if (PotentialBinary == NULL) {
  5879. DbgOut("Error: Could not allocate memory for potential binary.\n");
  5880. Result = FALSE;
  5881. goto LoadModuleEnd;
  5882. }
  5883. if (CurrentPathLength != 0) {
  5884. memcpy(PotentialBinary, CurrentPath, CurrentPathLength);
  5885. PotentialBinary[CurrentPathLength] = '/';
  5886. CurrentPathLength += 1;
  5887. }
  5888. strcpy(PotentialBinary + CurrentPathLength, BinaryName);
  5889. Status = stat(PotentialBinary, &Stat);
  5890. if (Status == 0) {
  5891. //
  5892. // Compare the timestamps. Allow for a difference of one because
  5893. // some file systems like FAT only store modification date to
  5894. // two second granules.
  5895. //
  5896. PotentialTimestamp = Stat.st_mtime - SYSTEM_TIME_TO_EPOCH_DELTA;
  5897. if ((Timestamp == 0) ||
  5898. (PotentialTimestamp == Timestamp) ||
  5899. (PotentialTimestamp + 1 == Timestamp) ||
  5900. (PotentialTimestamp - 1 == Timestamp)) {
  5901. //
  5902. // The file name and timestamps match, try to load symbols in
  5903. // this file.
  5904. //
  5905. Status = DbgLoadSymbols(PotentialBinary,
  5906. ImageMachineType,
  5907. Context,
  5908. &(NewModule->Symbols));
  5909. if (Status == 0) {
  5910. NewModule->Timestamp = Timestamp;
  5911. NewModule->Filename = PotentialBinary;
  5912. break;
  5913. }
  5914. //
  5915. // The name matches, but the timestamp doesn't. If nothing better
  5916. // is found keep this around to try at the end.
  5917. //
  5918. } else if (BackupPotential == NULL) {
  5919. BackupPotential = PotentialBinary;
  5920. BackupPotentialTimestamp = Stat.st_mtime -
  5921. SYSTEM_TIME_TO_EPOCH_DELTA;
  5922. PotentialBinary = NULL;
  5923. }
  5924. }
  5925. if (PotentialBinary != NULL) {
  5926. free(PotentialBinary);
  5927. }
  5928. }
  5929. //
  5930. // Attempt to load the binary without any symbol path.
  5931. //
  5932. if (NewModule->Symbols == NULL) {
  5933. Status = stat(OriginalBinaryName, &Stat);
  5934. if (Status == 0) {
  5935. PotentialTimestamp = Stat.st_mtime - SYSTEM_TIME_TO_EPOCH_DELTA;
  5936. NewModule->Filename = strdup(OriginalBinaryName);
  5937. if (NewModule->Filename == NULL) {
  5938. DbgOut("Error: Unable to allocate space for filename.\n");
  5939. Result = FALSE;
  5940. goto LoadModuleEnd;
  5941. }
  5942. //
  5943. // Attempt to load symbols if the timestamps match.
  5944. //
  5945. if ((Timestamp == 0) ||
  5946. (PotentialTimestamp == Timestamp) ||
  5947. (PotentialTimestamp + 1 == Timestamp) ||
  5948. (PotentialTimestamp - 1 == Timestamp)) {
  5949. Status = DbgLoadSymbols(NewModule->Filename,
  5950. ImageMachineType,
  5951. Context,
  5952. &(NewModule->Symbols));
  5953. if (Status == 0) {
  5954. //
  5955. // A module was successfully loaded this way, so skip the
  5956. // symbol path searching.
  5957. //
  5958. PathCount = 0;
  5959. NewModule->Timestamp = Timestamp;
  5960. } else {
  5961. free(NewModule->Filename);
  5962. NewModule->Filename = NULL;
  5963. }
  5964. //
  5965. // The timestamps don't match but the name does, save this as a
  5966. // backup if there's nothing better.
  5967. //
  5968. } else if (BackupPotential == NULL) {
  5969. BackupPotential = NewModule->Filename;
  5970. BackupPotentialTimestamp = PotentialTimestamp;
  5971. NewModule->Filename = NULL;
  5972. }
  5973. }
  5974. }
  5975. //
  5976. // If nothing was found but there's a backup, try the backup.
  5977. //
  5978. if ((NewModule->Symbols == NULL) && (BackupPotential != NULL)) {
  5979. Status = DbgLoadSymbols(BackupPotential,
  5980. ImageMachineType,
  5981. Context,
  5982. &(NewModule->Symbols));
  5983. if (Status == 0) {
  5984. //
  5985. // Warn the user that a module with a different timestamp is being
  5986. // loaded, as it could easily mean the symbols are out of sync.
  5987. // Don't bother warning them for timestamps that are different by 2
  5988. // seconds or less, as some file systems (FAT) and compression
  5989. // formats (ZIP) only have 2-second resolution.
  5990. //
  5991. Delta = BackupPotentialTimestamp - Timestamp;
  5992. if (Timestamp > BackupPotentialTimestamp) {
  5993. Delta = Timestamp - BackupPotentialTimestamp;
  5994. }
  5995. if (Delta > 2) {
  5996. Time = Timestamp + SYSTEM_TIME_TO_EPOCH_DELTA;
  5997. TimeStructure = localtime(&Time);
  5998. TimeString = asctime(TimeStructure);
  5999. LastIndex = strlen(TimeString);
  6000. if (LastIndex != 0) {
  6001. if (TimeString[LastIndex - 1] == '\n') {
  6002. TimeString[LastIndex - 1] = '\0';
  6003. }
  6004. }
  6005. DbgOut("Warning: Target timestamp for %s is %s\n",
  6006. FriendlyName,
  6007. TimeString);
  6008. Time = BackupPotentialTimestamp + SYSTEM_TIME_TO_EPOCH_DELTA;
  6009. TimeStructure = localtime(&Time);
  6010. TimeString = asctime(TimeStructure);
  6011. LastIndex = strlen(TimeString);
  6012. if (LastIndex != 0) {
  6013. if (TimeString[LastIndex - 1] == '\n') {
  6014. TimeString[LastIndex - 1] = '\0';
  6015. }
  6016. }
  6017. DbgOut("but file '%s' has timestamp %s.\n",
  6018. BackupPotential,
  6019. TimeString);
  6020. }
  6021. NewModule->Filename = BackupPotential;
  6022. NewModule->Timestamp = Timestamp;
  6023. BackupPotential = NULL;
  6024. }
  6025. }
  6026. //
  6027. // Populate the other fields of the module.
  6028. //
  6029. NameLength = strlen(FriendlyName);
  6030. if (NameLength == 0) {
  6031. Result = FALSE;
  6032. goto LoadModuleEnd;
  6033. }
  6034. NewModule->ModuleName = malloc(NameLength + 1);
  6035. if (NewModule->ModuleName == NULL) {
  6036. Result = FALSE;
  6037. goto LoadModuleEnd;
  6038. }
  6039. strcpy(NewModule->ModuleName, FriendlyName);
  6040. NewModule->BaseAddress = BaseAddress;
  6041. NewModule->LowestAddress = LowestAddress;
  6042. NewModule->Size = Size;
  6043. NewModule->Process = Process;
  6044. NewModule->Loaded = TRUE;
  6045. INSERT_BEFORE(&(NewModule->ListEntry), &(Context->ModuleList.ModulesHead));
  6046. if (NewModule->Symbols != NULL) {
  6047. if (NewModule->BaseAddress == -1ULL) {
  6048. NewModule->BaseAddress = NewModule->Symbols->ImageBase;
  6049. }
  6050. NewModule->BaseDifference = NewModule->BaseAddress -
  6051. NewModule->Symbols->ImageBase;
  6052. }
  6053. DbgOut("Module loaded 0x%08I64x: %s -> ",
  6054. NewModule->BaseAddress,
  6055. NewModule->ModuleName);
  6056. if (NewModule->Symbols == NULL) {
  6057. DbgOut(" *** Error: Symbols could not be loaded. ***\n");
  6058. } else {
  6059. DbgOut("%s\n", NewModule->Filename);
  6060. }
  6061. //
  6062. // Update the total checksum.
  6063. //
  6064. Context->ModuleList.Signature += NewModule->Timestamp +
  6065. NewModule->LowestAddress;
  6066. Context->ModuleList.ModuleCount += 1;
  6067. Result = TRUE;
  6068. LoadModuleEnd:
  6069. if (BackupPotential != NULL) {
  6070. free(BackupPotential);
  6071. }
  6072. if (Result == FALSE) {
  6073. if (NewModule != NULL) {
  6074. if (NewModule->Filename != NULL) {
  6075. free(NewModule->Filename);
  6076. }
  6077. if (NewModule->ModuleName != NULL) {
  6078. free(NewModule->ModuleName);
  6079. }
  6080. if (NewModule->Symbols != NULL) {
  6081. DbgUnloadSymbols(NewModule->Symbols);
  6082. NewModule->Symbols = NULL;
  6083. }
  6084. free(NewModule);
  6085. NewModule = NULL;
  6086. }
  6087. }
  6088. return NewModule;
  6089. }
  6090. INT
  6091. DbgrpResolveDumpType (
  6092. PDEBUGGER_CONTEXT Context,
  6093. PTYPE_SYMBOL *Type,
  6094. PVOID *Data,
  6095. PUINTN DataSize,
  6096. PULONGLONG Address
  6097. )
  6098. /*++
  6099. Routine Description:
  6100. This routine resolves a dump type and data to something valuable that can
  6101. be dumped. For example, it will follow pointers until a structure type and
  6102. data is found.
  6103. Arguments:
  6104. Context - Supplies a pointer to the applicaton context.
  6105. Type - Supplies a pointer that receives the resolved type. It also supplies
  6106. thie initial type.
  6107. Data - Supplies a pointer that receives the data to be dumped. It also
  6108. supplies the dump data for the given type.
  6109. DataSize - Supplies a pointer that on input contains the size of the
  6110. existing data buffer. This will be updated on output.
  6111. Address - Supplies a pointer that receives the address of the final
  6112. data if pointers are followed.
  6113. Return Value:
  6114. 0 on success.
  6115. Returns an error code on failure.
  6116. --*/
  6117. {
  6118. ULONG BytesRead;
  6119. PVOID CurrentData;
  6120. ULONG CurrentSize;
  6121. PTYPE_SYMBOL CurrentType;
  6122. ULONGLONG PointerValue;
  6123. PDATA_TYPE_RELATION RelationData;
  6124. ULONG RelativeSize;
  6125. PTYPE_SYMBOL RelativeType;
  6126. INT Result;
  6127. SYMBOL_SEARCH_RESULT SearchResult;
  6128. CurrentData = *Data;
  6129. CurrentSize = *DataSize;
  6130. CurrentType = *Type;
  6131. while (TRUE) {
  6132. Result = FALSE;
  6133. //
  6134. // Resolve the current type until a void, pointer, array, function, or
  6135. // non-relation type is found.
  6136. //
  6137. CurrentType = DbgSkipTypedefs(CurrentType);
  6138. if (CurrentType == NULL) {
  6139. Result = EINVAL;
  6140. goto ResolveDumpTypeEnd;
  6141. }
  6142. //
  6143. // If the type resolved to a non-relation type, then exit successfully.
  6144. //
  6145. if (CurrentType->Type != DataTypeRelation) {
  6146. break;
  6147. }
  6148. RelationData = &(CurrentType->U.Relation);
  6149. RelativeType = DbgGetType(RelationData->OwningFile,
  6150. RelationData->TypeNumber);
  6151. //
  6152. // If the resolved type is a void, an array, or a function, then there
  6153. // is nothing more to resolve.
  6154. //
  6155. if ((RelativeType == CurrentType) ||
  6156. (RelationData->Array.Minimum != RelationData->Array.Maximum) ||
  6157. (RelationData->Function != FALSE)) {
  6158. break;
  6159. }
  6160. //
  6161. // If the relative type is a structure with zero size, search for a
  6162. // structure with the same name and a non-zero size.
  6163. //
  6164. RelativeSize = DbgGetTypeSize(RelativeType, 0);
  6165. if ((RelativeType->Type == DataTypeStructure) && (RelativeSize == 0)) {
  6166. SearchResult.Variety = SymbolResultType;
  6167. Result = DbgpFindSymbol(Context,
  6168. RelativeType->Name,
  6169. &SearchResult);
  6170. if (Result != FALSE) {
  6171. RelativeType = SearchResult.U.TypeResult;
  6172. RelativeSize = DbgGetTypeSize(RelativeType, 0);
  6173. }
  6174. }
  6175. //
  6176. // Follow pointers, reading the relative type data from the pointer.
  6177. // The pointer value is stored in the current data and the size of the
  6178. // current data should not be bigger than a pointer size.
  6179. //
  6180. assert(RelationData->Pointer != 0);
  6181. CurrentSize = DbgGetTypeSize(CurrentType, 0);
  6182. if (CurrentSize > sizeof(ULONGLONG)) {
  6183. DbgOut("Pointer for type %s is of size %d.\n",
  6184. CurrentType->Name,
  6185. CurrentSize);
  6186. Result = EINVAL;
  6187. goto ResolveDumpTypeEnd;
  6188. }
  6189. assert((CurrentData != *Data) || (*DataSize == CurrentSize));
  6190. //
  6191. // Make sure to not follow a NULL pointer.
  6192. //
  6193. PointerValue = 0;
  6194. memcpy(&PointerValue, CurrentData, CurrentSize);
  6195. if (PointerValue == 0) {
  6196. DbgOut("Pointer is NULL.\n", CurrentType->Name);
  6197. Result = FALSE;
  6198. goto ResolveDumpTypeEnd;
  6199. }
  6200. //
  6201. // Allocate a new buffer and read the type data.
  6202. //
  6203. free(CurrentData);
  6204. CurrentSize = RelativeSize;
  6205. CurrentData = malloc(CurrentSize);
  6206. if (CurrentData == NULL) {
  6207. DbgOut("Error unable to allocate %d bytes of memory.\n",
  6208. RelativeSize);
  6209. Result = ENOMEM;
  6210. goto ResolveDumpTypeEnd;
  6211. }
  6212. *Address = PointerValue;
  6213. Result = DbgReadMemory(Context,
  6214. TRUE,
  6215. PointerValue,
  6216. RelativeSize,
  6217. CurrentData,
  6218. &BytesRead);
  6219. if ((Result != 0) || (BytesRead != RelativeSize)) {
  6220. if (Result == 0) {
  6221. Result = EINVAL;
  6222. }
  6223. DbgOut("Error reading memory at 0x%I64x. Expected %d bytes and "
  6224. "read %d bytes\n",
  6225. PointerValue,
  6226. RelativeSize,
  6227. BytesRead);
  6228. goto ResolveDumpTypeEnd;
  6229. }
  6230. CurrentType = RelativeType;
  6231. }
  6232. Result = 0;
  6233. ResolveDumpTypeEnd:
  6234. if (Result != 0) {
  6235. if (CurrentData != NULL) {
  6236. free(CurrentData);
  6237. CurrentData = NULL;
  6238. }
  6239. CurrentSize = 0;
  6240. }
  6241. *Type = CurrentType;
  6242. *Data = CurrentData;
  6243. *DataSize = CurrentSize;
  6244. return Result;
  6245. }
  6246. INT
  6247. DbgrpSetFrame (
  6248. PDEBUGGER_CONTEXT Context,
  6249. ULONG FrameNumber
  6250. )
  6251. /*++
  6252. Routine Description:
  6253. This routine changes the current frame, so that local variables may come
  6254. from a different function in the call stack.
  6255. Arguments:
  6256. Context - Supplies a pointer to the application context.
  6257. FrameNumber - Supplies the frame number. Zero represents the currently
  6258. executing function, 1 represents 0's caller, 2 represents 1's caller,
  6259. etc.
  6260. Return Value:
  6261. 0 on success.
  6262. Returns an error code on failure.
  6263. --*/
  6264. {
  6265. STACK_FRAME Frame;
  6266. ULONG FrameIndex;
  6267. REGISTERS_UNION Registers;
  6268. INT Status;
  6269. BOOL Unwind;
  6270. assert(Context->CurrentEvent.Type == DebuggerEventBreak);
  6271. Status = 0;
  6272. //
  6273. // Attempt to unwind to the given frame.
  6274. //
  6275. RtlCopyMemory(&Registers,
  6276. &(Context->CurrentEvent.BreakNotification.Registers),
  6277. sizeof(REGISTERS_UNION));
  6278. //
  6279. // Set the return address to the current PC so that if it's frame 0, the
  6280. // highlighted line returns to the PC.
  6281. //
  6282. Frame.ReturnAddress = DbgGetPc(Context, &Registers);
  6283. //
  6284. // Unwind the desired number of frames.
  6285. //
  6286. Unwind = TRUE;
  6287. for (FrameIndex = 0; FrameIndex < FrameNumber; FrameIndex += 1) {
  6288. Status = DbgStackUnwind(Context, &Registers, &Unwind, &Frame);
  6289. if (Status == EOF) {
  6290. DbgOut("Error: Only %d frames on the stack.\n", FrameIndex);
  6291. break;
  6292. } else if (Status != 0) {
  6293. DbgOut("Error: Failed to unwind stack: %s.\n",
  6294. strerror(Status));
  6295. break;
  6296. }
  6297. }
  6298. //
  6299. // If the stack was successfully unwound to the given frame, set that
  6300. // as the current information.
  6301. //
  6302. if (Status == 0) {
  6303. RtlCopyMemory(&(Context->FrameRegisters),
  6304. &Registers,
  6305. sizeof(REGISTERS_UNION));
  6306. Context->CurrentFrame = FrameNumber;
  6307. //
  6308. // Load and highlight the source line of the new frame.
  6309. //
  6310. DbgrShowSourceAtAddress(Context, Frame.ReturnAddress);
  6311. }
  6312. return Status;
  6313. }
  6314. INT
  6315. DbgrpEnableBreakPoint (
  6316. PDEBUGGER_CONTEXT Context,
  6317. LONG BreakPointIndex,
  6318. BOOL Enable
  6319. )
  6320. /*++
  6321. Routine Description:
  6322. This routine enables or disables a breakpoint identified by its zero-based
  6323. index.
  6324. Arguments:
  6325. Context - Supplies a pointer to the application context.
  6326. BreakPointIndex - Supplies the zero-based index of the breakpoint to enable
  6327. or disable. To specify all breakpoints, set Index to -1.
  6328. Enable - Supplies a flag indicating whether or not to enable (TRUE) or
  6329. disable (FALSE) this breakpoint.
  6330. Return Value:
  6331. 0 on success.
  6332. Returns an error code on failure.
  6333. --*/
  6334. {
  6335. PDEBUGGER_BREAK_POINT Breakpoint;
  6336. PLIST_ENTRY CurrentEntry;
  6337. INT Status;
  6338. //
  6339. // Loop through looking for the breakpoint in the list.
  6340. //
  6341. CurrentEntry = Context->BreakpointList.Next;
  6342. while (CurrentEntry != &(Context->BreakpointList)) {
  6343. Breakpoint = LIST_VALUE(CurrentEntry, DEBUGGER_BREAK_POINT, ListEntry);
  6344. if ((Breakpoint->Index == BreakPointIndex) || (BreakPointIndex == -1)) {
  6345. //
  6346. // Attempt to enable the breakpoint if it's not already enabled.
  6347. //
  6348. if (Enable != FALSE) {
  6349. if (Breakpoint->Enabled == FALSE) {
  6350. Status = DbgrpSetBreakpointAtAddress(
  6351. Context,
  6352. Breakpoint->Address,
  6353. &(Breakpoint->OriginalValue));
  6354. if (Status != 0) {
  6355. goto EnableBreakPointEnd;
  6356. }
  6357. Breakpoint->Enabled = TRUE;
  6358. }
  6359. //
  6360. // Disable the breakpoint if it's not already disabled.
  6361. //
  6362. } else {
  6363. if (Breakpoint->Enabled != FALSE) {
  6364. if (Context->BreakpointToRestore == Breakpoint) {
  6365. Context->BreakpointToRestore = NULL;
  6366. }
  6367. Status = DbgrpClearBreakpointAtAddress(
  6368. Context,
  6369. Breakpoint->Address,
  6370. Breakpoint->OriginalValue);
  6371. if (Status != 0) {
  6372. goto EnableBreakPointEnd;
  6373. }
  6374. Breakpoint->Enabled = FALSE;
  6375. }
  6376. }
  6377. if (BreakPointIndex != -1) {
  6378. break;
  6379. }
  6380. }
  6381. CurrentEntry = CurrentEntry->Next;
  6382. }
  6383. if ((CurrentEntry == &(Context->BreakpointList)) &&
  6384. (BreakPointIndex != -1)) {
  6385. DbgOut("Breakpoint %d not found.\n", BreakPointIndex);
  6386. Status = EINVAL;
  6387. goto EnableBreakPointEnd;
  6388. }
  6389. Status = 0;
  6390. EnableBreakPointEnd:
  6391. return Status;
  6392. }
  6393. VOID
  6394. DbgrpDestroySourcePath (
  6395. PDEBUGGER_SOURCE_PATH SourcePath
  6396. )
  6397. /*++
  6398. Routine Description:
  6399. This routine destroys a source path entry. It is assumed the entry is
  6400. already removed from its list.
  6401. Arguments:
  6402. SourcePath - Supplies a pointer to the source path to destroy.
  6403. Return Value:
  6404. 0 on success.
  6405. Returns an error code on failure.
  6406. --*/
  6407. {
  6408. if (SourcePath->Prefix != NULL) {
  6409. free(SourcePath->Prefix);
  6410. }
  6411. if (SourcePath->Path != NULL) {
  6412. free(SourcePath->Path);
  6413. }
  6414. free(SourcePath);
  6415. return;
  6416. }
  6417. INT
  6418. DbgrpLoadFile (
  6419. PSTR Path,
  6420. PVOID *Contents,
  6421. PULONGLONG Size
  6422. )
  6423. /*++
  6424. Routine Description:
  6425. This routine loads a file into memory.
  6426. Arguments:
  6427. Path - Supplies a pointer to the path to load.
  6428. Contents - Supplies a pointer where a pointer to the loaded file will be
  6429. returned on success. The caller is responsible for freeing this memory.
  6430. Size - Supplies a pointer where the size of the file will be returned on
  6431. success.
  6432. Return Value:
  6433. 0 on success.
  6434. Returns an error code on failure.
  6435. --*/
  6436. {
  6437. PVOID Buffer;
  6438. ssize_t BytesRead;
  6439. int File;
  6440. INT Result;
  6441. struct stat Stat;
  6442. ULONGLONG TotalBytesRead;
  6443. *Contents = NULL;
  6444. *Size = 0;
  6445. Result = stat(Path, &Stat);
  6446. if (Result != 0) {
  6447. return errno;
  6448. }
  6449. Buffer = malloc(Stat.st_size);
  6450. if (Buffer == NULL) {
  6451. return ENOMEM;
  6452. }
  6453. File = open(Path, O_RDONLY | O_BINARY);
  6454. if (File < 0) {
  6455. Result = errno;
  6456. goto LoadFileEnd;
  6457. }
  6458. TotalBytesRead = 0;
  6459. while (TotalBytesRead < Stat.st_size) {
  6460. BytesRead = read(File,
  6461. Buffer + TotalBytesRead,
  6462. Stat.st_size - TotalBytesRead);
  6463. if (BytesRead <= 0) {
  6464. if (errno == EINTR) {
  6465. continue;
  6466. }
  6467. Result = errno;
  6468. goto LoadFileEnd;
  6469. }
  6470. TotalBytesRead += BytesRead;
  6471. }
  6472. Result = 0;
  6473. LoadFileEnd:
  6474. if (File >= 0) {
  6475. close(File);
  6476. }
  6477. if (Result != 0) {
  6478. if (Buffer != NULL) {
  6479. free(Buffer);
  6480. Buffer = NULL;
  6481. }
  6482. }
  6483. *Contents = Buffer;
  6484. *Size = Stat.st_size;
  6485. return Result;
  6486. }