1
0

dbgrcomm.c 212 KB

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